前言:在导出到xls时有一些通用的元素,比如标题,列标题,内容区域,求和行,但每个xls多少有点不同,为了处理这个问题,可以使用delegate实现,这样可以把差异部分单独处理。
//为了处理计算和之类的补公式 public delegate void WriteXlsEndDelegate(DataTable dataTable, HSSFSheet sheet); //代理函数方式 public WriteXlsEndDelegate writeXlsEndDelegate=null; /* * 根据模板导出xls * 数据表,文件名,模板文件名,填充开始行,原始模板里的数据表行数(不包括表头、求和行,一般要留一条示例数据) */ public void ExportXlsByTemplate(DataTable dataTable, string filename, string templatefile, int startDataRegionRow,int orgRowCount=1) { HttpContext context = HttpContext.Current; //Excel模板 string templetFileName = context.Server.MapPath(templatefile); HSSFWorkbook wk = null; if (templetFileName != null) { using (FileStream fs = File.Open(templetFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { //把xls文件读入workbook变量里,之后就可以关闭了 wk = new HSSFWorkbook(fs); fs.Close(); } } else { return; } if (dataTable.Rows.Count>1) { HSSFSheet sheet1 = (HSSFSheet)wk.GetSheetAt(0); var rowSource = sheet1.GetRow(startDataRegionRow); var rowStyle = rowSource.RowStyle;//获取当前行样式 sheet1.ShiftRows(startDataRegionRow + orgRowCount, startDataRegionRow + orgRowCount, dataTable.Rows.Count - orgRowCount, true, false);//从下一行开始移动 for (int i = startDataRegionRow + orgRowCount; i < startDataRegionRow + orgRowCount + (dataTable.Rows.Count - orgRowCount); i++) { var rowInsert = sheet1.CreateRow(i); if (rowStyle != null) rowInsert.RowStyle = rowStyle; rowInsert.Height = rowSource.Height; for (int col = 0; col < rowSource.LastCellNum; col++) { var cellsource = rowSource.GetCell(col); var cellInsert = rowInsert.CreateCell(col,cellsource.CellType); var cellStyle = cellsource.CellStyle; //设置单元格样式 if (cellStyle != null) cellInsert.CellStyle = cellsource.CellStyle; cellInsert.SetCellValue(""); } } string nextFirstTxt = string.Empty; for (int i = startDataRegionRow; i < startDataRegionRow + dataTable.Rows.Count; i++) { IRow row = sheet1.GetRow(i); for (int j = 0; j < dataTable.Columns.Count; j++) { var drValue = dataTable.Rows[i - startDataRegionRow][j].ToString(); switch (dataTable.Columns[j].DataType.ToString()) { case "System.String"://字符串类型 row.GetCell(j).SetCellValue(drValue); break; case "System.DateTime"://日期类型 DateTime dateV; DateTime.TryParse(drValue, out dateV); row.GetCell(j).SetCellValue(dateV); break; case "System.Boolean"://布尔型 bool boolV = false; bool.TryParse(drValue, out boolV); row.GetCell(j).SetCellValue(boolV); break; case "System.Int16"://整型 case "System.Int32"://整型 case "System.Int64"://整型 case "System.Int"://整型 int invV = 0; int.TryParse(drValue, out invV); row.GetCell(j).SetCellValue(invV); break; case "System.Byte": int intV = 0; int.TryParse(drValue, out intV); row.GetCell(j).SetCellValue(intV); break; case "System.Decimal"://浮点型 case "System.Double": double doubV = 0; double.TryParse(drValue, out doubV); row.GetCell(j).SetCellValue(doubV); break;default: row.GetCell(j).SetCellValue(""); break; } } } sheet1.ForceFormulaRecalculation = true; if(writeXlsEndDelegate!=null)//结束时是否需要进行其它处理 writeXlsEndDelegate(dataTable,sheet1); } context.Response.ContentType = "application/vnd.ms-excel"; // 添加头信息,指定文件名格式 context.Response.AddHeader("Content-Disposition", "attachment;filename=" + filename); context.Response.AddHeader("Content-Transfer-Encoding", "binary"); context.Response.ContentType = "application/octet-stream"; context.Response.ContentEncoding = System.Text.Encoding.UTF8; MemoryStream file = new MemoryStream(); wk.Write(file); context.Response.BinaryWrite(file.GetBuffer()); }
通常导出xls后会进行一些后续操作,比如设置公式求和,下面例子是对第L到U列设置求和公式编写方法
ClassTest npoi=new ClassTest();
//设置公式 npoi.writeXlsEndDelegate = (dataTable1, sheet) => { int rowIndex = dataTable1.Rows.Count + 1; ///做后补操作 };
npoi.ExportXlsByTemplate(dataTable, filename, @"/Template/xls/test.xls", 1);
模板示例