当前位置:网站首页>使用easyexcel模板导出的两个坑(Map空数据列错乱和不支持嵌套对象)
使用easyexcel模板导出的两个坑(Map空数据列错乱和不支持嵌套对象)
2022-07-05 19:11:00 【lang20150928】
在项目当中,很多同事喜欢用Map来存储数据,尤其是从数据库查询数据然后存放到List<Map<String,Object>>当中。这样会导致通过excel模板导出时数据错乱。
当前easyexcel版本
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.1.1</version>
</dependency>
假如存在以下模板(limitManage2.xlsx)。
日期 | 操作人 | 额度周期起始日 | 额度周期到期日 | 总额度(元) | 剩余额度(元) | 备注 | 状态 | 机构名称 | 已领用额度(元) | 备注2 |
---|---|---|---|---|---|---|---|---|---|---|
{bean.CREATE_DATE} | {bean.CREATOR} | {bean.LIMIT_CYCLE_START} | {bean.LIMIT_CYCLE_MTR} | {bean.TOTAL_LIMIT} | {bean.SURPLUS_LIMIT} | {bean.REMARK} | {bean.STATUS} | {bean.BRANCH_INSTITUTION_NAME} | {bean.GET_LIMIT} | {bean.fillData3.REMARK} |
首先通过List<Map<String,Object>>填充数据(故意将REMARK字段的值部分设置为空,规则是列表中索引为偶数的为空)
private static Map<String, Object> data2(){
Map<String, Object> params = new HashMap<>();
List<Map<String, String>> result = new ArrayList<>();
for (int i = 0; i < 20; i++) {
Map<String, String> curMap = new HashMap<>();
curMap.put("CREATE_DATE", "2018-06-12");
curMap.put("STATUS", "已生效");
curMap.put("LIMIT_CYCLE_START", "2018-06-12");
curMap.put("LIMIT_CYCLE_MTR", "2018-06-12");
curMap.put("BRANCH_INSTITUTION_NAME", "资产管理部");
curMap.put("SURPLUS_LIMIT", "88888888" + i);
curMap.put("CREATOR", "系统管理员" + i);
curMap.put("GET_LIMIT", "101000000");
curMap.put("PK", "2417");
curMap.put("TOTAL_LIMIT", "88888888");
if (i % 2 == 0) {
curMap.put("REMARK", "定制额度" + i);
}else {
// curMap.put("REMARK","");
}
result.add(curMap);
}
params.put("bean", result);
return params;
}
创建测试类
@Test
public void compositeFillMapIssue() {
String templateFileName =
TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "limitManage2.xlsx";
System.out.println(new File(templateFileName).getPath());
String fileName = TestFileUtil.getPath() + "compositeFill" + System.currentTimeMillis() + ".xlsx";
try (ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build()) {
WriteSheet writeSheet = EasyExcel.writerSheet().build();
Map<String, Object> data2 = data2();
FillConfig fillConfig = FillConfig.builder().build();
data2.forEach((key,value)->{
excelWriter.fill(new FillWrapper(key, (List<Map<String, String>>)value),fillConfig, writeSheet);
});
}
System.out.println(new File(fileName).getPath());
}
测试类路径 src/test/java/com/alibaba/easyexcel/test/demo/fill/FillTest.java
测试模板路径 src/test/resources/demo/fill/limitManage2.xlsx
执行结果如下所示
额度周期到期日 | 总额度(元) | 剩余额度(元) | 备注 | 状态 | 机构名称 | 已领用额度(元) | 备注2 |
---|---|---|---|---|---|---|---|
2018-06-12 | 88888888 | 888888880 | 定制额度0 | 已生效 | 资产管理部 | 101000000 | |
2018-06-12 | 88888888 | 888888881 | 定制额度2 | 已生效 | 资产管理部 | 101000000 | |
2018-06-12 | 88888888 | 888888882 | 定制额度4 | 已生效 | 资产管理部 | 101000000 | |
2018-06-12 | 88888888 | 888888883 | 定制额度6 | 已生效 | 资产管理部 | 101000000 | |
2018-06-12 | 88888888 | 888888884 | 定制额度8 | 已生效 | 资产管理部 | 101000000 | |
2018-06-12 | 88888888 | 888888885 | 定制额度10 | 已生效 | 资产管理部 | 101000000 | |
2018-06-12 | 88888888 | 888888886 | 定制额度12 | 已生效 | 资产管理部 | 101000000 | |
2018-06-12 | 88888888 | 888888887 | 定制额度14 | 已生效 | 资产管理部 | 101000000 | |
2018-06-12 | 88888888 | 888888888 | 定制额度16 | 已生效 | 资产管理部 | 101000000 | |
2018-06-12 | 88888888 | 888888889 | 定制额度18 | 已生效 | 资产管理部 | 101000000 | |
2018-06-12 | 88888888 | 8888888810 | 已生效 | 资产管理部 | 101000000 | ||
2018-06-12 | 88888888 | 8888888811 | 已生效 | 资产管理部 | 101000000 | ||
2018-06-12 | 88888888 | 8888888812 | 已生效 | 资产管理部 | 101000000 | ||
2018-06-12 | 88888888 | 8888888813 | 已生效 | 资产管理部 | 101000000 | ||
2018-06-12 | 88888888 | 8888888814 | 已生效 | 资产管理部 | 101000000 | ||
2018-06-12 | 88888888 | 8888888815 | 已生效 | 资产管理部 | 101000000 | ||
2018-06-12 | 88888888 | 8888888816 | 已生效 | 资产管理部 | 101000000 | ||
2018-06-12 | 88888888 | 8888888817 | 已生效 | 资产管理部 | 101000000 | ||
2018-06-12 | 88888888 | 8888888818 | 已生效 | 资产管理部 | 101000000 | ||
2018-06-12 | 88888888 | 8888888819 | 已生效 | 资产管理部 | 101000000 |
从上面的结果不难看出,备注栏的信息都错乱了。
通过测试发现,将Map转为对象即可。
pojo定义如下
package com.alibaba.easyexcel.test.demo.fill;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@EqualsAndHashCode
public class FillData2 {
private String CREATE_DATE;
private String STATUS;
private String LIMIT_CYCLE_START;
private String LIMIT_CYCLE_MTR;
private String BRANCH_INSTITUTION_NAME;
private String SURPLUS_LIMIT;
private String CREATOR;
private String GET_LIMIT;
private String PK;
private String TOTAL_LIMIT;
private String REMARK;
private FillData3 fillData3;
}
package com.alibaba.easyexcel.test.demo.fill;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@EqualsAndHashCode
public class FillData3 {
private String REMARK3;
}
创建测试数据
private static Map<String, List<FillData2>> data3(){
Map<String, List<FillData2>> params = new HashMap<>();
List<FillData2> result = new ArrayList<>();
for (int i = 0; i < 20; i++) {
FillData2 curMap = new FillData2();
curMap.setCREATE_DATE("2018-06-12");
curMap.setSTATUS("已生效");
curMap.setLIMIT_CYCLE_START("2018-06-12");
curMap.setLIMIT_CYCLE_MTR("2018-06-12");
curMap.setBRANCH_INSTITUTION_NAME("资产管理部");
curMap.setSURPLUS_LIMIT("88888888" + i);
curMap.setCREATOR("系统管理员" + i);
curMap.setGET_LIMIT("101000000");
curMap.setPK("2417");
curMap.setTOTAL_LIMIT("88888888");
if (i % 2 == 0) {
curMap.setREMARK("定制额度" + i);
}else {
// curMap.put("REMARK","");
}
FillData3 fillData3 = new FillData3();
fillData3.setREMARK3(curMap.getREMARK() +">>");
curMap.setFillData3(fillData3);
result.add(curMap);
}
params.put("bean", result);
return params;
}
创建测试类
@Test
public void compositeFillMapIssue3() {
String templateFileName =
TestFileUtil.getPath() + "demo" + File.separator + "fill" + File.separator + "limitManage2.xlsx";
System.out.println(new File(templateFileName).getPath());
String fileName = TestFileUtil.getPath() + "compositeFill" + System.currentTimeMillis() + ".xlsx";
// 方案1
try (ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templateFileName).build()) {
WriteSheet writeSheet = EasyExcel.writerSheet().build();
Map<String, List<FillData2>> data2 = data3();
data2.forEach((key,value)->{
excelWriter.fill(new FillWrapper(key, value), writeSheet);
});
}
System.out.println(new File(fileName).getPath());
}
测试结果如下所示
额度周期到期日 | 总额度(元) | 剩余额度(元) | 备注 | 状态 | 机构名称 | 已领用额度(元) | 备注2 |
---|---|---|---|---|---|---|---|
2018-06-12 | 88888888 | 888888880 | 定制额度0 | 已生效 | 资产管理部 | 101000000 | |
2018-06-12 | 88888888 | 888888881 | 已生效 | 资产管理部 | 101000000 | ||
2018-06-12 | 88888888 | 888888882 | 定制额度2 | 已生效 | 资产管理部 | 101000000 | |
2018-06-12 | 88888888 | 888888883 | 已生效 | 资产管理部 | 101000000 | ||
2018-06-12 | 88888888 | 888888884 | 定制额度4 | 已生效 | 资产管理部 | 101000000 | |
2018-06-12 | 88888888 | 888888885 | 已生效 | 资产管理部 | 101000000 | ||
2018-06-12 | 88888888 | 888888886 | 定制额度6 | 已生效 | 资产管理部 | 101000000 | |
2018-06-12 | 88888888 | 888888887 | 已生效 | 资产管理部 | 101000000 | ||
2018-06-12 | 88888888 | 888888888 | 定制额度8 | 已生效 | 资产管理部 | 101000000 | |
2018-06-12 | 88888888 | 888888889 | 已生效 | 资产管理部 | 101000000 | ||
2018-06-12 | 88888888 | 8888888810 | 定制额度10 | 已生效 | 资产管理部 | 101000000 | |
2018-06-12 | 88888888 | 8888888811 | 已生效 | 资产管理部 | 101000000 | ||
2018-06-12 | 88888888 | 8888888812 | 定制额度12 | 已生效 | 资产管理部 | 101000000 | |
2018-06-12 | 88888888 | 8888888813 | 已生效 | 资产管理部 | 101000000 | ||
2018-06-12 | 88888888 | 8888888814 | 定制额度14 | 已生效 | 资产管理部 | 101000000 | |
2018-06-12 | 88888888 | 8888888815 | 已生效 | 资产管理部 | 101000000 | ||
2018-06-12 | 88888888 | 8888888816 | 定制额度16 | 已生效 | 资产管理部 | 101000000 | |
2018-06-12 | 88888888 | 8888888817 | 已生效 | 资产管理部 | 101000000 | ||
2018-06-12 | 88888888 | 8888888818 | 定制额度18 | 已生效 | 资产管理部 | 101000000 | |
2018-06-12 | 88888888 | 8888888819 | 已生效 | 资产管理部 | 101000000 |
从测试结果可以看出,上面空数据错乱的问题解决了,但是最后一列没有任何数据。对应的模板为{bean.fillData3.REMARK}
,从这里看出easyexcel对于一个对象中包含复杂对象数据的模板导出不支持。
边栏推荐
- HiEngine:可媲美本地的云原生内存数据库引擎
- Common interview questions in Android, 2022 golden nine silver ten Android factory interview questions hit
- 机器学习基础(三)——KNN/朴素贝叶斯/交叉验证/网格搜索
- 潘多拉 IOT 开发板学习(HAL 库)—— 实验8 定时器中断实验(学习笔记)
- Millimeter wave radar human body sensor, intelligent perception of static presence, human presence detection application
- 微波雷达感应模块技术,实时智能检测人体存在,静止微小动静感知
- Mysql如何对json数据进行查询及修改
- Mathematical modeling of oil pipeline layout MATLAB, mathematical model of oil pipeline layout
- Tutoriel de téléchargement et d'installation du progiciel fuzor 2020
- 国海证券在网上开户安全吗?
猜你喜欢
How to quickly advance automated testing? Listen to the personal feelings of the three bat test engineers
基于FPGA的超声波测距
Millimeter wave radar human body sensor, intelligent perception of static presence, human presence detection application
How MySQL queries and modifies JSON data
UDF implementation of Dameng database
决策树与随机森林
Android面试,android音视频开发
Teach you to deal with JS reverse picture camouflage hand in hand
cf:B. Almost Ternary Matrix【对称 + 找规律 + 构造 + 我是构造垃圾】
The road of enterprise digital transformation starts from here
随机推荐
软件测试是干什么的?学习有啥要求?
Explain in detail the functions and underlying implementation logic of the groups sets statement in SQL
打新债在哪里操作开户是更安全可靠的呢
ELK分布式日志分析系统部署(华为云)
MySQL中字段类型为longtext的值导出后显示二进制串方式
Analysis of postman core functions - parameterization and test report
Ultrasonic ranging based on FPGA
Fundamentals of shell programming (Part 8: branch statements -case in)
Mysql如何对json数据进行查询及修改
The basic grammatical structure of C language
Oracle Chinese sorting Oracle Chinese field sorting
Password reset of MariaDB root user and ordinary user
Debezium系列之:记录mariadb数据库删除多张临时表debezium解析到的消息以及解决方法
Django uses mysqlclient service to connect and write to the database
Debezium系列之:postgresql从偏移量加载正确的最后一次提交 LSN
Go语言 | 02 for循环及常用函数的使用
[today in history] July 5: the mother of Google was born; Two Turing Award pioneers born on the same day
Is it safe for China Galaxy Securities to open an account? Securities account opening
大厂面试必备技能,2022Android不死我不倒
How to realize the Online timer and offline timer in the game