项目场景:报表导出,复杂表头
需求:项目需要导出一份报表,表头比较复杂。表头存在三行,并且各种组合。
问题分析:虽然复杂,但是静态表头
说明:需要的报表表头虽然复杂,好在不是动态表头,上面的列名是固定的,产生读取模板后填充数据的想法。
根据提供的样表,得到excel模板:“消耗品.xlsx”
解决方案:
首先明确一下基本概念:
先创建一个工作簿,一个工作簿可以有多个工作表,一个工作表可以有多个行,一个行可以有多个单元格
- 工作簿 ----------->XSSFWorkbook
- 工作表 ----------->XSSFSheet
- 行 ----------->XSSFRow
- 单元格 ----------->XSSFCell
关键代码拆分:
第一步:从模板表加载复杂表头。
//测试2:加载模板的表头
string TempletFileName = Server.MapPath("~/DownloadFile/消耗品.xlsx");
FileStream file = new FileStream(TempletFileName, FileMode.Open, FileAccess.Read);
XSSFWorkbook workbook = new XSSFWorkbook(file);
XSSFSheet sheet = (XSSFSheet)workbook.GetSheet("Sheet1");
第二步:往表内写入数据
//往表内写入数据
for (int i = 0; i < dt.Rows.Count; i++)
{ //数据行数 循环
IRow row = sheet.CreateRow(i + 3); //创建 行 的起始行 +3表示表头占用了3行
//模板表有35列
for (int j = 0; j < 35; j++)
{
//创建单元格
ICell cells = row.CreateCell(j);
//为单元格赋值
cells.SetCellValue(dt.Rows[i][j].ToString());
//列宽自适应
sheet.AutoSizeColumn(j);
}
}
第三步:表格导出
//将表内容写入流 通知浏览器下载
MemoryStream ms = new MemoryStream();
workbook.Write(ms);
System.Web.HttpContext.Current.Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}.xlsx", fileName));
System.Web.HttpContext.Current.Response.AddHeader("Content-Length", ms.ToArray().Length.ToString());
System.Web.HttpContext.Current.Response.BinaryWrite(ms.ToArray()); //进行二进制流下载
workbook = null;
ms.Close();
ms.Dispose();
System.Web.HttpContext.Current.Response.End();
总结:完整Demo
public void ExportExcel(DataTable dt, string fileName)
{
//测试2:加载模板的表头
string TempletFileName = Server.MapPath("~/DownloadFile/污水表.xlsx");
FileStream file = new FileStream(TempletFileName, FileMode.Open, FileAccess.Read);
XSSFWorkbook workbook = new XSSFWorkbook(file);
XSSFSheet sheet = (XSSFSheet)workbook.GetSheet("Sheet1");
//设置单元格样式:水平、垂直居中
ICellStyle titlestyle = workbook.CreateCellStyle();
titlestyle.Alignment = HorizontalAlignment.Center;
titlestyle.VerticalAlignment = VerticalAlignment.Center;
//往表内写入数据
for (int i = 0; i < dt.Rows.Count; i++)
{ //数据行数 循环
IRow row = sheet.CreateRow(i + 3); //模板表表头占用3行,所以从第四行开始填充数据
//模板表有35列
for (int j = 0; j < 35; j++)
{
ICell cells = row.CreateCell(j);
cells.CellStyle = titlestyle;
//按单元格类型 赋值
if (0 < j && j < 33){
//整数型 赋值办法
cells.SetCellValue(Convert.ToDouble(dt.Rows[i][j].ToString().Length == 0 ? null : (dt.Rows[i][j])));
}
//第一列和最后两列内容是 :字符串
else{
//字符型 赋值办法
cells.SetCellValue(dt.Rows[i][j].ToString());
sheet.AutoSizeColumn(j);//采用自适应列宽
}
}
}
//将表内容写入流 通知浏览器下载
MemoryStream ms = new MemoryStream();
workbook.Write(ms);
System.Web.HttpContext.Current.Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}.xlsx", fileName));
System.Web.HttpContext.Current.Response.AddHeader("Content-Length", ms.ToArray().Length.ToString());
System.Web.HttpContext.Current.Response.BinaryWrite(ms.ToArray()); //进行二进制流下载
workbook = null;
ms.Close();
ms.Dispose();
//这句关闭流,不加的话,下载的文件会需要修复才能打开
System.Web.HttpContext.Current.Response.End();
}