最近写了一个要导出excel的,要是比较简单一些就使用原始的方式了,遍历循环rows,并且遍历循环单元格填充值,就OK了,但是我的表头不是固定的,还需要一个行里填充4个单元格,有点像合并单元格之类的,填充数据呢,也是稍微复杂点,如果用原生的一是时间长,二是也比较困难,通过一些方式找到了hutool工具的ExcelWriter方式。
这个导出的好处就是你就关注数据本身,专注于数据本身能够怎么存储到List集合里,再把集合传给writer方法里就好了,就直接可以是一个想要的excel,咱们先来说一下使用示例
1.万物的开始需要先创建writer
1,1 创建一个起我自己需要的sheet页的一个excel
// 通过工具类创建write
// 此种方式最后会通过response设置导出
ExcelWriter writer = ExcelUtil.getWriterWithSheet("sheet页名称");
1.2 创建一个带默认sheet页的一个excel
// 此种方式最后会通过response设置导出
ExcelWriter writer = ExcelUtil.getWriter();
1.3 创建一个直接放入磁盘的一个excel
// 写入磁盘下
ExcelWriter writer = ExcelUtil.getWriter("d:/writeBeanTest.xlsx");
// 写入磁盘下并设置当前sheet页名称
ExcelWriter writer = ExcelUtil.getWriter("d:/writeBeanTest.xlsx", "sheet页名称");
2.合并使用
我要设置上图的第一行的标题需要合并单元格,才能实现1月填报数据和填报状态及数量和未填报市级在一个格子里。所以用以下方式.
合并方法:writer.merge()
第一个参数是firstRow是要合并的开始行,坐标从0开始也就是要合并第一行,
第二个参数是lastRow是要合并的最后行,这里1就代表合并第二行,第一个和第二个参数意思就 是合并第一行第二行,
第三个参数是firstColumn是要合并的开始列,坐标为0代表第一列
第四个参数是lastColumn是要合并的最后列,此为0为第一列,第三个和第四个的意思为此次不合 并列,
第五个参数是content,是内容,就是当前单元格里的内容
第6个参数isSetHeaderStyle,是否设置头格式,其实就是当前单元格内容背景为灰色
这样就把前两个标题设置完成
// 合并单元格
// 合并第一行和第二行单元格,不合并第一列,第一行第一列是序号
writer.merge(0, 1, 0, 0, "序号", false);
// 合并第一行和第二行,不合并第二列,第二列是省份名称
writer.merge(0, 1, 1, 1, "省份名称", false);
设置第三列,根据上面展示图片就知道,需要合并第三列和第五列,名称是1月填报数据
writer.merge(0, 0, 2, 4, "1月填报数据", false);
在设置填报状态、未填报数量、未填报市级,放入list集合里,
List<List<String>> rows = new ArrayList<>();
List<String> row = new ArrayList<>();
row.add("");
row.add("");
row.add("填报状态");
row.add("未填报数量");
row.add("未填报市级");
rows.add(row);
填充数据,最后将数据存储到rows集合里,就可以了
// 需要先设置跳过当前行
writer.passCurrentRow();
int index = 0;
for (int i = 0; i < 3; i++) {
List<String> rowData = new ArrayList<>();
index = i + 1;
rowData.add(index + "");
rowData.add("名称");
rowData.add("完成了");
rowData.add("20");
rowData.add("无");
rows.add(rowData);
}
将数据写到writer.write里就ok了,但不要忘记关闭资源
writer.write(rows, true);
// 关闭writer,释放内存
writer.close();
总体代码测试,运行一下看下结果
public static void main(String[] args) {
ExcelWriter writer = ExcelUtil.getWriter("d:/writeBeanTest.xlsx", "sheet页名称");
// 设置合并项
writer.merge(0, 1, 0, 0, "序号", false);
writer.merge(0, 1, 1, 1, "省份名称", false);
writer.merge(0, 0, 2, 4, "1月填报数据", false);
// 跳过当前行,否则设置合并会出问题
writer.passCurrentRow();
// 填充标题
List<List<String>> rows = new ArrayList<>();
List<String> row = new ArrayList<>();
row.add("");
row.add("");
row.add("填报状态");
row.add("未填报数量");
row.add("未填报市级");
rows.add(row);
// 填充内容
int index = 0;
for (int i = 0; i < 3; i++) {
List<String> rowData = new ArrayList<>();
index = i + 1;
rowData.add(index + "");
rowData.add("名称");
rowData.add("完成了");
rowData.add("20");
rowData.add("无");
rows.add(rowData);
}
writer.write(rows, true);
// 关闭writer,释放内存
writer.close();
}
完美~~
当然也可以导出,导出其他代码都一样就需要这样的Write,只要不带路径,就不会下载而变为导出
writer = ExcelUtil.getWriterWithSheet("shhet"); 或
ExcelUtil.getWriter();
还要设置导出的名称,格式xsl等就可以了
response.setContentType("application/vnd.ms-excel");
response.addHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.addHeader("charset", "utf-8");
response.addHeader("Pragma", "no-cache");
encodeName = URLEncoder.encode("导出名称-" + DateUtil.today() + ".xls", StandardCharsets.UTF_8.toString());
response.setHeader("Content-Disposition", "attachment; filename=\"" + encodeName + "\"; filename*=utf-8''" + encodeName);
ServletOutputStream out = response.getOutputStream();
writer.flush(out);
writer.close();
IoUtil.close(out);