EasyExcel单字段自定义转换@ExcelProperty::converter无效


本文仅总结了本人所经历、发现的注意事项,如果无法解决可留言,再进行补充
本文是基于EasyExcel v3.1.0分析的

前提

实体

实体按照官方文档(日期数字或者自定义格式转换)声明注解
在这里插入图片描述

转换器

实现Converter接口(一定要是com.alibaba.excel.converters.Converter因为别的框架也有Converter),实现“读Excel”convertToJavaData方法,“写Excel”convertToExcelData方法

public class CustomStringStringConverter implements Converter<String> {
    @Override
    public Class<?> supportJavaTypeKey() {
        return String.class;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }

    /**
     * 这里读的时候会调用
     *
     * @param context
     * @return
     */
    @Override
    public String convertToJavaData(ReadConverterContext<?> context) {
        return "自定义:" + context.getReadCellData().getStringValue();
    }

    /**
     * 这里是写的时候会调用 不用管
     *
     * @return
     */
    @Override
    public WriteCellData<?> convertToExcelData(WriteConverterContext<String> context) {
        return new WriteCellData<>(context.getValue());
    }

}

调用

调用参考官方文档、Demo编写,使用注解声明的实体

    /**
     * 日期、数字或者自定义格式转换
     * <p>1. 创建excel对应的实体对象 参照{@link ConverterData}
     * <p>2. 使用{@link ExcelProperty}配合使用注解{@link DateTimeFormat}、{@link NumberFormat}或者自定义注解
     * <p>3. 直接写即可
     */
    @Test
    public void converterWrite() {
        String fileName = TestFileUtil.getPath() + "converterWrite" + System.currentTimeMillis() + ".xlsx";
        // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        EasyExcel.write(fileName, ConverterData.class).sheet("模板").doWrite(data());
    }

注意事项

实体构造器声明

// 使用如下注解保证有构造函数就可以
@Data
@AllArgsConstructor
@NoArgsConstructor

因为EasyExcel是通过反射实例化转换器实现的,如果没有构造方法,会有Can not instance custom converter的异常提示
在这里插入图片描述

实体属性命名规范

要求是小驼峰标准命名,如下

@ExcelProperty(value = "用户名称",converter = JavaLongToStringConvert.class)
private Long userId;

但是有的项目中可能会有前缀,如field声明、业务标识,创建的实体就会如下fUserId这种在使用EasyExcel时不可以,需要复制实体,修改属性名为上面那样

@ExcelProperty(value = "用户名称",converter = JavaLongToStringConvert.class)
private Long fUserId;

源码分析

因为EasyExcel获取实体信息后,源码中是这样匹配属性注解信息的
getExcelContentProperty获取上下文配置返回,构造过程中使用属性名匹配注解,有两个信息mapfieldName
在这里插入图片描述
map是declaredFieldContentMap方法中通过反射获取的,key是和实体中属性名一致的,value就是注解的完整信息
在这里插入图片描述
fieldName是调用工具类ClassUtils之前构造的Head(EasyExcel的对象,在com.alibaba.excel.metadata中)中的属性fieldName它获取的属性名就对命名有要求
在这里插入图片描述
小驼峰获取的属性名和反射获取的一致,在map和fieldName匹配的时候就可以正确获取
在这里插入图片描述
如果有前缀,就会变成这样,会出现大写,就匹配不上了,注解就失效了
在这里插入图片描述

实现Converter接口

注意要实现的是com.alibaba.excel.converters.Converter接口,其他框架也有该名称接口,但是实现错了,注解使用就报错了,一般不会发生

实现Converter方法

读Excel导入,走的是方法convertToJavaData
写Excel导出,走的是方法convertToExcelData
如果没有实现处理方法也是无效的

……