开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天,点击查看活动详情
1. 需求背景:
做导出excel功能的时候会遇到很复杂的格式,这时候我们可以选择根据模板填充表格的方式来完成。
2. 技术选型:
EasyExcel:
官网地址:https://easyexcel.opensource.alibaba.com/docs/current/quickstart/fill
4. pom 配置
尽量按这个版本配置,这个是测试过的可以使用,不然可能会出现jar包冲突的问题。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>4.1.2</version>
</dependency>
5. 代码实现
这里给的代码片段只是简单列表填充,如果有需要填充复杂模板可以看下官方文档的填充方式。最下面有官网示例截图
需要注意Boolean.FALSE 这个值,我这边列表结束就是最后一行,所以定义了false,如果不是最后一行就要定义true;
public void excel(HttpServletRequest request, HttpServletResponse response) {
//业务数据,根据自己业务查询出来要导出的数据。这个就不要复制了
List<User> userList = new ArrayList();
//创建ExcelWriter
ExcelWriter excelWriter = null;
try {
// outputStream:要导出的文件的输出流
OutputStream outputStream = response.getOutputStream();
// 模版文件
ClassPathResource classPathResource = new ClassPathResource("template/test.xlsx");
// 使用模版文件的两种方式:
// 1、文件路径:.withTemplate(templateFileName)
// 2、输入流:.withTemplate(inputStream)
// String templateFileName = classPathResource.getFile().getPath();
InputStream inputStream = classPathResource.getInputStream();
excelWriter = EasyExcel.write(outputStream).withTemplate(inputStream).
excelType(ExcelTypeEnum.XLSX).autoCloseStream(Boolean.FALSE).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.FALSE).build();
//如果有复杂模板可以参考官方给的demo。从这里往上可以完全复制(除了业务数据),
// 注意 Boolean.FALSE , "template/test.xlsx" 这几个值。
//excelWriter.fill() 这地方就是填充属性。
excelWriter.fill(userList, fillConfig, writeSheet);
//从这里往下也可以复制使用
// 设置输出流格式以及文件名:
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
String fileName = URLEncoder.encode("用户信息", "UTF-8").replaceAll("\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
// 千万别忘记close关闭流
if (excelWriter != null) {
excelWriter.close();
}
}
}
6. 可能遇见的问题
1. 官网给的常见问题
地址:easyexcel.opensource.alibaba.com/qa/
2. 遇到的问题:
1. 出现了NoClassDefFoundError
解决方法:将上面的pom 配置,配置上去。除了这个错误,官网中给另外几个错误也可以尝试使用这个方法解决。
2. 导出数据为空:
解决方法:
1. 看下自己查询出来的业务数据是否为空。这个很重要,排查问题一定不要漏掉每个细节。
2. 看下自己写的模板上的属性值是否是对的。
对象的属性如果是 name, 那么表格里就要写{name},
如果导出是列表就要加点:{.name}。
加点的这种写法针对的是下面这行代码:
WriteSheet writeSheet = EasyExcel.writerSheet().build();
FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.FALSE).build();
excelWriter.fill(userList, fillConfig, writeSheet);
注意看userList 这行,userList代表的就是业务数据的集合。
3.可能遇到的问题
注意:如果运行时报以下错,org.apache.poi.openxml4j.exceptions:Your InputStream was neither an OLE2 stream, nor an OOXML stream则需要加依赖:
这个只是可能遇到的问题,所以记录一下,以防不测。
<plugins>
<!-- 让maven不编译xls文件,但仍将其打包 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<nonFilteredFileExtensions>
<nonFilteredFileExtension>xls</nonFilteredFileExtension>
</nonFilteredFileExtensions>
</configuration>
</plugin>
</plugins>
7.后记:
如果有更复杂的需求可以看下官网给的demo, 在看的时候只需要关注红框内的内容就可以了,这个代码对应的模板是这样的
比如怎么获取模板怎么,下载,直接复用 (# 5. 代码实现)的内容就行了。 还需要注意Boolean.FALSE 这个值,我这边列表结束就是最后一行,所以定义了false,如果不是最后一行就要定义true;