【easyExcel踩坑】自定义转换器实现数据去除空格,获取数据为 null
前言
在使用 Easy Excel做导入数据时,需求是将所有导入的参数去除空格(这里做其他处理也都可以),总不能在读取数据之后,然后在业务层进行数据的处理吧,这样太 low 也太麻烦了。easyExcel 就提供了一个自定义转换器,就是使用了这个玩意,踩了一个坑。
正文
直接上代码
简单读对象
@ApiModel(value = "导入信息")
@Data
public class ImportInfoVo implements Serializable {
private static final long serialVersionUID = 1L;
// 序号
@ApiModelProperty(value = "序号")
@ExcelProperty("序号")
private Integer index;
// 姓名
@ApiModelProperty(value = "姓名")
@ExcelProperty(value = "姓名",converter = SpaceConverter.class)
private String name;
// 年龄
@ApiModelProperty(value = "年龄")
private Integer age;
// 手机号
@ApiModelProperty(value = "手机号")
@ExcelProperty(value = "手机号",converter = SpaceConverter.class)
private String phone;
}
数据监听器
这里我做了修改,没有像官方那样写。因为官方那样写一个监听器处理一个导入时间,我这个改成一个通用的监听器,这个就适合数据不多的时候使用的监听器。数据太多会出现 oom
/**
* easyexcel 通用读取监听器
* 此方法适合数据不大时使用 数据太大会出现 oom
* @author liangdingji
* @date 2024/3/22
*/
public class EasyExcelDataListener<T> implements ReadListener<T> {
private static Logger logger = LoggerFactory.getLogger(EasyExcelDataListener.class);
/**
* 缓存的数据
*/
private List<T> cachedDataList;
public EasyExcelDataListener(List<T> cachedDataList){
this.cachedDataList = cachedDataList;
}
/**
* 这个每一条数据解析都会来调用
*
* @param data one row value. Is is same as {@link AnalysisContext#readRowHolder()}
* @param context
*/
@Override
public void invoke(T data, AnalysisContext context) {
logger.info("开始解析");
cachedDataList.add(data);
}
/**
* 所有数据解析完成了 都会来调用
*
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 这里也要保存数据,确保最后遗留的数据也存储到数据库
logger.info("所有数据解析完成!");
}
}
string类型转换器
这里官方原本是实现一些自定义类型转换的,比如 string 转date 之类的。这里我就实现了去空格的操作
/**
* string类转换器 去除空格
* @author liangdingji
* @date 2024/3/25
*/
public class SpaceConverter implements Converter<String> {
@Override
public Class supportJavaTypeKey() {
return String.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public String convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
// 去除空格
String originalValue = cellData.getStringValue();
return StringUtils.isNotEmpty(originalValue) ? originalValue.replace(" ", "") : null;
}
}
读取数据
@Test
public void simpleRead() {
String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";
List<EnterpriseImportInfoVo> voList = Lists.newArrayList();
EasyExcel.read(fileName, ImportInfoVo.class, new EasyExcelDataListener<>(voList)).sheet().doRead();
}
导入数据
序号 | 姓名 | 年龄 | 手机号 |
---|---|---|---|
1 | test | 11 | 13800138000 |
坑来了
在读取手机号,不管怎么样都是为 null 的,有几个方法是可以获取值的
- 去掉自定义转换器,这个去掉就不无法去除空格了,这个不能
- 将Excel 的单元格的格式改成文本,这个也不能控制客户的操作呀,也不现实
- 所以问题肯定是出在了转换器上
填坑
然后在 debug 的时候,就发现了端倪,看一下源码,就能看到CellData这玩意有好几种类型的值,这个我早就该想到的了,不同的数据肯定会有不同类型的数据类型去解析然后去接收,真的蠢……然后多加一个类型判断就可以了
public class CellData<T> extends AbstractCell {
private CellDataTypeEnum type;
private BigDecimal numberValue;
private String stringValue;
private Boolean booleanValue;
private T data;
private FormulaData formulaData;
}
正确的类型转换器
/**
* string类转换器 去除空格
* @author liangdingji
* @date 2024/3/25
*/
public class SpaceConverter implements Converter<String> {
@Override
public Class supportJavaTypeKey() {
return String.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public String convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
String originalValue = "";
if (cellData.getType() == CellDataTypeEnum.STRING){
originalValue = cellData.getStringValue();
}else if (cellData.getType() == CellDataTypeEnum.NUMBER){
originalValue = cellData.getNumberValue().toBigInteger().toString();
}
return StringUtils.isNotEmpty(originalValue) ? originalValue.replace(" ", "") : null;
}
}
转载自:https://juejin.cn/post/7350923935951929398