背景:
使用easypoi 作为导入导出框架,引入的版本号是:
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>4.0.0</version>
</dependency>
使用场景:
使用@ExcelEntity ,指定分组名称,理想状态能按顺序输出如下表格:
public class ContractTurnOverExcelVO {
/**
* 固定租金
*/
@ExcelEntity(name ="固定租金",show = true,id = "CostDTO.class")
private CostDTO fixedRent;
/**
* 预估营业额
*/
@ExcelEntity(name ="预估营业额",show = true,id = "CostDTO.class")
private CostDTO turnover;
/**
* 提成租金
*/
@ExcelEntity(name ="提成租金",show = true,id = "CostDTO.class")
private CostDTO royaltyRent;
/**
* 实付租金(根据计租模型来确定数据)
*/
@ExcelEntity(name ="实付租金",show = true,id = "CostDTO.class")
private CostDTO actualRent;
/**
* 房租合同其他费用合计
*/
@ExcelEntity(name ="房租合同其他费用合计",show = true,id = "CostDTO.class")
private CostDTO otherRent;
/**
* 其他合同费用合计
*/
@ExcelEntity(name ="其他合同费用合计",show = true,id = "CostDTO.class")
private CostDTO otherContractRent;
/**
* 所有费用合计
* 【其他合同固定费用合计】+【房租合同实付租金】+【房租合同其他费用合计】
*/
@ExcelEntity(name ="合计",show = true,id = "CostDTO.class")
private CostDTO totalRent;
}
实际现象:
导出的 @ExcelEntity 并没有按照顺序输出
解决方案:
使用1,2,3,4代替分组名称。然后再用Map 自定义映射分组名称。再拿到Workbook后遍历所在行,遍历替换想要输出的表格名称。由此解决乱序问题。
/**
* 固定租金
*/
@ExcelEntity(name ="1",show = true,id = "CostDTO.class")
private CostDTO fixedRent;
/**
* 预估营业额
*/
@ExcelEntity(name ="2",show = true,id = "CostDTO.class")
private CostDTO turnover;
/**
* 提成租金
*/
@ExcelEntity(name ="3",show = true,id = "CostDTO.class")
private CostDTO royaltyRent;
static {
TITLE_MAP.put("1", "固定租金");
TITLE_MAP.put("2", "预估营业额");
TITLE_MAP.put("3", "提成租金");
TITLE_MAP.put("4", "实付租金");
TITLE_MAP.put("5", "房租合同其他费用合计");
TITLE_MAP.put("6", "其他合同费用合计");
TITLE_MAP.put("7", "合计");
}
//导出多个表格
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, ContractTurnOverExcelVO.class, contractTurnOverExcelVOS);
//处理导出的名字映射
workbook.getSheetAt(0).getRow(0).forEach(cell -> {
String value = (String) TITLE_MAP.get(cell.getStringCellValue());
if (ObjectUtil.isNotEmpty(value)) {
cell.setCellValue(value);
}
});
分析原因:
跟踪easypoi 源码可以发现:在ExcelExportService类中insertDataToSheet方法通过sortAllParams(excelParams)把导出类的属性重新排序了一遍。
跟进sortAllParams方法中可以看到源码中使用HashMap存放分组和分组中具体的数据。由于HashMap的存放顺序和key 的hash值有关。所以在HashMap 遍历链表的时候,和push的顺序无关,导致乱序。
了解到问题的本质后,我们就可以采用确定顺序hash 的数字代替文本。保证按照我们想要的顺序输出,最后得到表格结果后就可以根据预设的映射替换成我们需要的真实文字导出。
至此乱序问题就完美解决啦。。。。