我们先定义几个单元格颜色,以便导出的EXCEL看起来比较赏心悦目。
#region ISheet单元格样式
///
/// 返回单元格颜色样式
///
/// 传入的颜色HSSFColor.Blue.Index
/// ISheet
///
public static ICellStyle cellColor(short color, IWorkbook workbook)
{
ICellStyle dtlStyle = workbook.CreateCellStyle();
IFont dtlFont = workbook.CreateFont();
dtlFont.Color = color;
dtlStyle.SetFont(dtlFont);
return dtlStyle;
}
///
/// 返回单元格数值型样式
///
/// ISheet
/// 数值样式0.0000
///
public static ICellStyle cellNumericalFomat(IWorkbook workbook,string strFormat)
{
IDataFormat format = workbook.CreateDataFormat();
ICellStyle cellPriceStyle = workbook.CreateCellStyle();
cellPriceStyle.DataFormat = format.GetFormat(strFormat);
return cellPriceStyle;
}
#endregion
然后就是导出的方法,传入的参数为dtMain数据集,fileNameEXCEL名称,headerText表格标题
public void ExportToExcel(DataTable dtMain, string fileName, string headerText)
{}
//循环数据,得到数据流
public MemoryStream getDataToStr(DataTable dtMain, CYSoft.RunInfo.Common.NPOIHelper.WorkbookType type, string headerText)
{
MemoryStream ms = new MemoryStream();
IWorkbook workbook = NPOIHelper.CreateWorkbook(type); ;
{
ISheet sheet = workbook.CreateSheet(headerText);
{
int rowIndex = 0;
List
#region 表头及样式
if (!string.IsNullOrEmpty(headerText))
{
IRow headerRow = sheet.CreateRow(rowIndex++);
headerRow.HeightInPoints = 25;
headerRow.CreateCell(0).SetCellValue(headerText);
ICellStyle headStyle = workbook.CreateCellStyle();
headStyle.Alignment = HorizontalAlignment.Center;
IFont font = workbook.CreateFont();
font.FontHeightInPoints = 20;
font.Boldweight = 700;
headStyle.SetFont(font);
headerRow.GetCell(0).CellStyle = headStyle;
sheet.AddMergedRegion(new CellRangeAddress(0, 0, 0, heads.Count - 1));
}
#endregion
#region 列头及样式
{
IRow headerRow = sheet.CreateRow(rowIndex++);
headerRow.HeightInPoints = 15;
ICellStyle headStyle = Function.cellColor(HSSFColor.Black.Index, workbook);
headStyle.Alignment = HorizontalAlignment.Center;
headStyle.FillForegroundColor = HSSFColor.BlueGrey.Index;
IFont font = workbook.CreateFont();
font.FontHeightInPoints = 10;
font.Boldweight = 700;
headStyle.SetFont(font);
for (int i = 0; i < heads.Count; i++)
{
ICell cell = headerRow.CreateCell(i);
cell.SetCellValue(heads[i]);
cell.CellStyle = headStyle;
sheet.SetColumnWidth(i, 50 * 90);
}
}
#endregion
//获取第一层级,并循环构建单元格。注:我这里的数据集第一层级是PID父级ID为空,并且Level层级为1的,这里你需要改一下符合你自己的数据集。
List
dr =>
string.IsNullOrEmpty(dr["PID"].SyToString())
&& dr["Level"].SyToString() == "1"
).ToList();
foreach (DataRow dr in listDr)
{
IRow dataRow = sheet.CreateRow(rowIndex);
Dictionary
//根据主表该行的列名,判断该列的样式,并赋值
getCellByCol(dr, dataRow, colMap, workbook);
rowIndex++;
//获取该级的下级,并循环构建单元格
getchildDrToCell(dr, dtMain, ref rowIndex, colMap, workbook, sheet);
}
}
sheet.CreateFreezePane(dtMain.Columns.Count, 2);//冻结窗格 ,把标题和列头冻结
sheet.SetColumnWidth(0, 50 * 100);
sheet.SetColumnWidth(1, 70 * 160);
workbook.Write(ms);
}
return ms;
}
///
/// 获取下级的数据,并构建行
///
/// 当前行
/// 数据集
/// 行号
/// 数据列名
/// IWorkbook
/// ISheet
private void getchildDrToCell(DataRow dr, DataTable dt, ref int rowIndex, Dictionary
, ISheet sheet)
{
//获取该级的下级,并循环构建单元格
List
if (dtlListDr.Count() > 0)
{
int startRow = rowIndex;
foreach (DataRow drDtl in dtlListDr)
{
IRow dataDtlRow = sheet.CreateRow(rowIndex);
//构建当前行
getCellByCol(drDtl, dataDtlRow, colMap, workbook);
rowIndex++;
//递归寻找下级
getchildDrToCell(drDtl, dt, ref rowIndex, colMap, workbook, sheet);
}
sheet.GroupRow(startRow, rowIndex);
sheet.SetRowGroupCollapsed(startRow, false);
}
}
这个方法,实际是处理金额单价等小数位数。这里就用到了我们最开始新建的那个单元格样式几个方法。这里需要根据实际情况来写,比如单价金额需要保留几位小数四舍五入等需要特殊处理的。
//根据列,构建表格行
private void getCellByCol(DataRow dr, IRow dataRow, Dictionary
{
//根据主表该行的列名,判断该列的样式,并赋值
foreach (KeyValuePair
{
ICell cell = dataRow.CreateCell(kv.Key);
//单价是3位小数,金额0位,数量4位
if (kv.Value == "ListQty")
{ cell.CellStyle = Function.cellNumericalFomat(workbook, "0.0000"); }
else if (kv.Value == "Price")
{ cell.CellStyle = Function.cellNumericalFomat(workbook, "0.000"); }
else if (kv.Value == "Money" )
{ cell.CellStyle = Function.cellNumericalFomat(workbook, "0"); }
if (kv.Value == "Qty" || kv.Value == "Price" || kv.Value == "Money")
{
cell.SetCellValue(Convert.ToDouble(dr[kv.Value].SyToDecimal()));
}
else cell.SetCellValue(dr[kv.Value].SyToString());
}
}
这个方法是告诉程序我们需要导出的字段中文名字,
private List
{
List
heads.AddRange(new string[] { "列名1", "列名2", "列名3", "列名4", "列名5", "列名6", "列名7" });
return heads;
}
这个是告诉程序我们对应的数据集里面的列名。注:这个方法必须和上面GetExcelHead列名字段严格一一对应,不允许多列少列错位。
private Dictionary
{
Dictionary
colMap.Add(0, "ColumnName1");
colMap.Add(1, "ColumnName2");
colMap.Add(2, "ColumnName3");
colMap.Add(3, "ColumnName4");
colMap.Add(4, "ColumnName5");
colMap.Add(5, "ColumnName6");
colMap.Add(6, "ColumnName7");
return colMap;
}