目录
在最近的项目开发中,遇到一个需求:用excel导出大量数据(这些数据导出到excel时需要都除以1万)。能想到的解决办法肯定是自定义一个convert将数值都除以10000。
代码如下:
一:自定义convert
/**
单位转换为万
**/
public class TenThousandDecimalConverter implements Converter<BigDecimal> {
private static final BigDecimal TEN_THOUSAND = new BigDecimal("10000");
@Override
public Class<BigDecimal> supportJavaTypeKey() {
return BigDecimal.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.NUMBER;
}
@Override
public BigDecimal convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
switch (cellData.getType()) {
case NUMBER:
BigDecimal numberValue = cellData.getNumberValue();
return Objects.nonNull(numberValue) ? numberValue.multiply(TEN_THOUSAND) : null;
case STRING:
String stringValue = cellData.getStringValue();
if (StringUtils.isBlank(stringValue) || "NA".equals(stringValue)) {
return null;
}
try {
return new BigDecimal(stringValue).multiply(TEN_THOUSAND);
} catch (NumberFormatException e){
return null;
}
default:
return null;
}
}
@Override
public CellData<?> convertToExcelData(BigDecimal decimal, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) {
return Objects.nonNull(decimal) ? new CellData<>(decimal.divide(TEN_THOUSAND, RoundingMode.HALF_UP)) : null;
}
}
二:注册使用convert
ExcelWriter writer = EasyExcel.write(monthlyExportPath).registerConverter(new
TenThousandDecimalConverter()).build();
WriteSheet sheet0 = EasyExcel.writerSheet("sheet0").build();
writer.fill(dataList,sheet0);
WriteSheet sheet1 = EasyExcel.writerSheet("sheet1").build();
writer.fill(dataList,sheet1);
可以看到将TenThousandDecimalConverter注册到EasyExcel了。
三:遇到问题
那么问题来了,在代码上线之后出现了一种情况:此需求是已经实现了,将所有数值都除以了1万。但是出现了一种状况:其他功能模块导出的excel文件中所有数值也都除以了1万。。。
关键这个bug有前提条件,在导出需要除以1万的这个excel之后,再导出其他功能模块的excel就会遇到也除以了一万的情况;如果在项目启动后,没有导出过需要除以1万的excel,导出的其他excel又是正常的,bug又不会复现了。开发大半天都没有找到原因所在,在本地怎么都复现不出来bug,而上线后用户一使用就又复现了......
四:最终解决
在仔细研读”注册使用convert代码“后,发现这里的注册方式和之前其他模块写的注册方式有一点不一样,改成如下代码:
WriteSheet sheet0 = EasyExcel.writerSheet("sheet0").registerConverter(new TenThousandDecimalConverter()).build();
WriteSheet sheet1 = EasyExcel.writerSheet("sheet1").registerConverter(new TenThousandDecimalConverter()).build();
再经过测试验证,最后的这种写法才是convert正确的使用方式。将convert注册到sheet上,就是临时生效的,不会影响到其他地方对EasyExcel的使用。