工作上有一个导出数据的需求,发现用hutool工具类可以非常简洁快捷的生成excel导出。
- 前期准备
引入hutool的依赖:
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.21</version>
</dependency>
准备好导出的Excel模板:
第一行为标题文本
第二行为Bean的字段名
- 代码示例
主要使用到的有这两个类:
cn.hutool.core.util.ReflectUtil
cn.hutool.core.util.ExcelUtil
private void convertOrderListToXSSF(List<OrderVo> orderVoList, HttpServletResponse response) {
//输出文件名称
String targetFileName = DateUtil.currentSeconds() + "_order.xls";
//0.从模板中提取表头
String templateName = "导出模板.xlsx";
InputStream inputStream = getClass().getClassLoader().getResourceAsStream(templateName);
ExcelReader excelReader = ExcelUtil.getReader(inputStream);
/*
//A方法:这种方法使用了hutool提供的bean转换为excel行的方法,但有一个局限性:一个字段只能设置一个别名,因此无法生成同个字段取值的多个列,舍弃。
//从模板文件中提取 字段名-表头文字的对应关系;第一行(key)为表头文字,第一行(value)为字段名,如name:名字
Map<String, Object> filedNameTitle = excelReader.readAll().get(0);
//定义标题别名
for (Map.Entry<String, Object> entry : filedNameTitle.entrySet()) {
excelWriter.addHeaderAlias(entry.getKey(), String.valueOf(entry.getValue()));
}
//只写出加了别名的字段
excelWriter.setOnlyAlias(true);
//写出大标题
if(StringUtils.isNotBlank(targetFileTitle)) {
excelWriter.merge(filedNameTitle.size() - 1, targetFileTitle, true);
}
excelWriter.write(voList, true);
excelWriter.autoSizeColumnAll();*/
//表头文字
List<Object> titleRow = excelReader.readRow(0);
//表头文字对应的类字段名
List<Object> filedNameRow = excelReader.readRow(1);
//1.写数据
ExcelWriter excelWriter = ExcelUtil.getWriter();
//1.0 表头
excelWriter.writeRow(titleRow, true);
//1.1 内容-订单记录
for (OrderVo orderVo : orderVoList) {
//一行记录
List<Object> row = new ArrayList<>();
for (Object filedNameCell : filedNameRow) {
//使用Java的反射机制,获取订单对象字段名对应的字段值
String filedName = String.valueOf(filedNameCell);
Object filedValue = ReflectUtil.getFieldValue(orderVo, filedName);
filedValue = convertData(filedName, filedValue);
row.add(filedValue);
}
excelWriter.writeRow(row, true);
}
//2.输出数据
response.setContentType("application/vnd.ms-excel;charset=utf-8");
// Content-disposition 默认值为inline,表示在浏览器窗口打开,attachment表示下载框,filename是文件名,如为中文需要编码
response.setHeader("Content-Disposition", "attachment;filename=" + targetFileName);
ServletOutputStream out = null;
try {
out = response.getOutputStream();
} catch (IOException e) {
e.printStackTrace();
}
excelWriter.flush(out, true);
excelWriter.close();
IoUtil.close(out);
}
- 注意事项
在使用这个工具类时,发现打包不会报错,但运行时,
在读取excel模板这一步:ExcelReader excelReader = ExcelUtil.getReader(inputStream);
一直提示java.lang.NoSuchMethodError
;
排查了maven依赖后,发现项目同时还引入了org.apache.poi这个依赖且版本较低导致的,
因为是小组共用不能删除,所以更新了依赖版本就解决这个问题啦。
<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>