Java EasyExcel利用填充模版动态生成多个sheet页
作者:小王博客基地
一、前言
今天收到一个导出Excel的需求,这种需求经常做,看到模版还是是有点复杂的有头有行,一般的导出是不好做,使用模板填充比较简单! 另外还有一个需求小编是第一次见,所以来记录一下,为后来人铺路!
需求:导出有单子的头信息和一些多个行信息,前端可以多选,多个放在一个excel里的sheet中
明白了需求我们技术选型,现在基本都是EasyExcel
用的比较多,今天使用的版本为:3.1.5
,低版本已经不维护,建议使用高点的版本哈!
在这里先说一下,EasyExcel单独是无法实现一个模版动态填充多个sheet页,所以我们使用POI来帮忙复制sheet页即可!
二、准备工作
1. 阉割版效果图
我简化了一些功能,自己做了一个简单的模板,但是功能都是有的,大致如下图所示:
多个就使用合同号作为sheet名称,每个里面也会有多个行垂直填充即可!
2. 填充模版
3. 导入依赖
中间使用了Hutool
来获取流,很多公司不让使用Hutool的,大家自己选择,不使用可以用:
- Spring的ResourceUtils.getFile()
- JDK的new File()
本次使用Hutool的ClassPathResource
<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.1.5</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.4</version> </dependency>
4. 导出实体
/** * @author wangzhenjun * @date 2023/7/4 17:09 */ @Data public class TestExcel { private String contractNo; private String address; private String dateTime; private List<Item> itemList; @Data public static class Item{ private String name; private BigDecimal price; } }
三、实战代码
为了方便直接写在Controller里了,大家不要学习哈,业务的处理还是要在service里写!
整体思路:
使用POI
的XSSFWorkbook
来根据要导出的个数来进行复制sheet页,名称为合同号
将复制好的sheet页转换成字节数组,然后再通过输入流的方式读取字节数组中的数据。
EasyExcel
将使用输入流中的模板数据生成 Excel 数据,并将生成的 Excel 文件写入到 HttpServletResponse
的输出流中,以便将其发送给客户端进行下载或其他处理。
创建一个 WriteSheet
对象,并将其与上面复制的sheet页名称关联,就可以往里面填充数据了!
如果有这种list多个行填充的并且list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true
不加的话会把你后面的内容给覆盖了!
但是这个就会把所有数据放到内存 会很耗内存!
用完记得把流关闭哈!
@SneakyThrows @GetMapping("/excel") public void excel (HttpServletResponse response){ int size = 2; List<TestExcel> testExcels = new ArrayList<>(); for (int i = 0; i < size; i++) { TestExcel testExcel = new TestExcel(); testExcel.setContractNo("HT07040" + (i + 1)); testExcel.setAddress("青岛" + i + "号基地"); testExcel.setDateTime("2023-07-05"); testExcels.add(testExcel); List<TestExcel.Item> itemList = new ArrayList<>(); for (int j = 0; j < size; j++) { TestExcel.Item item = new TestExcel.Item(); item.setName("商品" + (j + 1)); item.setPrice(new BigDecimal("188").multiply(new BigDecimal(j + 1))); itemList.add(item); } testExcel.setItemList(itemList); } response.setCharacterEncoding("utf-8"); String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20"); response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx"); ClassPathResource classPathResource = new ClassPathResource("template" + File.separator + "测试.xlsx"); InputStream stream = classPathResource.getStream(); // 把excel流给这个对象,后续可以操作 XSSFWorkbook workbook = new XSSFWorkbook(stream); // 设置模板的第一个sheet的名称,名称我们使用合同号 workbook.setSheetName(0, testExcels.get(0).getContractNo()); for (int i = 1; i < size; i++) { // 剩余的全部复制模板sheet0即可 workbook.cloneSheet(0, testExcels.get(i).getContractNo()); } // 把workbook写到流里 ByteArrayOutputStream baos = new ByteArrayOutputStream(); workbook.write(baos); byte[] bytes = baos.toByteArray(); stream = new ByteArrayInputStream(bytes); ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(stream).build(); for (TestExcel testExcel : testExcels) { WriteSheet writeSheet = EasyExcel.writerSheet(testExcel.getContractNo()).build(); // list不是最后一行,下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存 FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).direction(WriteDirectionEnum.VERTICAL).build(); excelWriter.fill(testExcel, writeSheet); excelWriter.fill(new FillWrapper("item", testExcel.getItemList()), fillConfig, writeSheet); } excelWriter.finish(); baos.close(); stream.close(); }
四、总结
这样就完成了,主要的难点是复制sheet页,多行填充在EasyExcel官网都是有的,还有一些我这边没有用到的东西,大家可以根据自己的需求去找找看!
到此这篇关于Java EasyExcel利用填充模版动态生成多个sheet页的文章就介绍到这了,更多相关Java EasyExcel生成多个sheet内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!