EasyExcel (FastExcel)自定义转换器、自定义导出枚举类替换,完整代码+详细注释说明

这是一个基于Easyexcel(FastExcel)通过注解的方式,实现在导入导出的时候,按照指定的字段和枚举类,进行字典值映射转换的工具。

不通过枚举类、而是直接在注解中写替换枚举的,请看另外一篇文章:EasyExcel (FastExcel)自定义转换器、自定义导出字典映射替换、满足条件内容增加样式,完整代码+详细注释说明

以下正文:

1.定义枚举类


/**
 * @Description:
 * @author: CloverAn
 * @email: 285135288@qq.com
 * @created: 2024/08/14 15:01
 */
public enum SexEunm implements DoGetEnum<String> {
  
    /*需要修改的内容 - BEGIN*/
    MAN("0-1", "男"),
    WOMAN("1-2", "女");
    /*需要修改的内容 - END*/

    final String enumKey;
    final String enumDesc;

    SexEunm(String enumKey, String enumDesc) {
        this.enumKey = enumKey;
        this.enumDesc = enumDesc;
    }

    /**
     * 根据key获取value值
     *
     * @param key
     * @return
     */
    public SexEunm getEnumByKey(String key) {
        for (SexEunm sexEunm : SexEunm.values()) {
            if (sexEunm.enumKey.equals(key)) {
                return sexEunm;
            }
        }
        return null;
    }

    /**
     * 根据value获取枚举key值
     *
     * @param value
     * @return
     */
    public SexEunm getEnumByValue(String value) {
        for (SexEunm sexEunm : SexEunm.values()) {
            if (sexEunm.enumDesc.equals(value)) {
                return sexEunm;
            }
        }
        return null;
    }

    @Override
    public String getValueByKey(String key) {
        SexEunm sexEunm = getEnumByKey(key);
        return sexEunm == null ? null : sexEunm.enumDesc;
    }

    @Override
    public String getKeyByValue(String value) {
        SexEunm sexEunm = getEnumByValue(enumDesc);
        return sexEunm == null ? null : sexEunm.enumKey;
    }
}

注意:
1.定义了通过key获取value 和 通过value获取key 的两个方法。这两个方法必须在自己写的类里面必须要有。此外,对于大多数情况来说,只需要修改内容里面的枚举值即可,代码里面做了标识,整体不需要改动。
2.这里继承了一个DoGetEnum类,并实现了其中的两个方法。原因是太菜 ,没找到通过反射执行获取对应内置函数的办法,因此通过外部接口的方式,获取对应函数方法,并执行获取数据。接口代码如下:

/**
 * @Description: converter中反射获取的查询数据的方法,
 * 对反射应用不熟,没有想到办法直接写在枚举类中,所以写一个接口,让枚举类实现。
 * @Creator: CloverAn
 * @Date: 2024/8/14 17:22
 */
public interface DoGetEnum<T> {

    /**
     * 根据字典key值获取对应value值,主要用于导出时字典映射转换
     *
     * @param key 字典值
     * @return 描述
     */
    String getValueByKey(T key);

    /**
     * 根据value获取对应字典key值,主要用于导入时字典映射转换
     *
     * @param value 描述
     * @return 字典值
     */
    T getKeyByValue(String value);
}

2.定义自定义注解

import java.lang.annotation.*;
/**
 * @Description: 字典映射转换自定义注解
 * @Creator: CloverAn
 * @Date: 2024/8/14 17:22
 */
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelEnumValue {
    Class<? extends Enum<?>> value();
}

这里的枚举类,属性接收的是一个枚举类的对象。

3.重写EasyExcel转换器接口,对excel读和写方法都进行自定义


import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @Description: 自定义converter
 * @Creator: CloverAn
 * @Date: 2024/8/14 17:22
 */
public class ExcelEnumValueConverter implements Converter<Object> {

    @Override
    public Class<?> supportJavaTypeKey() {
        return Object.class;
    }

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

    @Override
    public WriteCellData<?> convertToExcelData(Object value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
        ExcelEnumValue enumValue = contentProperty.getField().getAnnotation(ExcelEnumValue.class);
        Class<?> enumClass = enumValue.value();
        Object enumConstant = enumClass.getEnumConstants()[0];
        Method method = null;
        Object invoke = null;
        try {
            //获取枚举类中的方法并执行,以期望获取到对应的value值数据
            method = enumClass.getDeclaredMethod("getValueByKey", Object.class);
            invoke = method.invoke(enumConstant, value);
        } catch (NoSuchMethodException e) {
            //抛出getValueByKey方法未找到异常
        } catch (InvocationTargetException | IllegalAccessException e) {
            //抛出getValueByKey方法调用失败异常
        }

        //Method method = null;
        //try {
        //    method = enumClass.getDeclaredMethod("getValueByKey", Object.class);
        //} catch (NoSuchMethodException e) {
        //    //抛出getValueByKey方法未找到异常
        //}
        //Object invoke = null;
        //try {
        //    invoke = method.invoke(enumConstant, value);
        //} catch (Exception e) {
        //    //抛出getValueByKey方法调用失败异常
        //}

        //注意,当枚举类中没有对应的key时,或者对应key的value是null时,invoke会返回null,此时会出现空指针。
        if (invoke == null) {
            invoke = "未找到指定key对应的value值";
        }
        return new WriteCellData<>(invoke.toString());
    }

    @Override
    public Object convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        String stringValue = cellData.getStringValue();
        ExcelEnumValue enumValue = contentProperty.getField().getAnnotation(ExcelEnumValue.class);
        Class<?> enumClass = enumValue.value();
        Object enumConstant = enumClass.getEnumConstants()[0];
        Method method = null;
        Object invoke = null;
        try {
            //获取枚举类中的方法并执行,以期望获取到对应的key值数据
            method = enumClass.getDeclaredMethod("getKeyByValue", String.class);
            invoke = method.invoke(enumConstant, stringValue);
        } catch (NoSuchMethodException e) {
            try {
                //获取枚举类中的方法并执行,以期望获取到对应的key值数据
                method = enumClass.getDeclaredMethod("getKeyByValue", Object.class);
                invoke = method.invoke(enumConstant, stringValue);
            } catch (NoSuchMethodException ex) {
                //抛出getKeyByValue方法未找到异常
            }
        }

        //Method method = null;
        //try {
        //    method = enumClass.getDeclaredMethod("getKeyByValue", String.class);
        //} catch (NoSuchMethodException e) {
        //    try {
        //        method = enumClass.getDeclaredMethod("getKeyByValue", Object.class);
        //    } catch (NoSuchMethodException ex) {
        //        //抛出getKeyByValue方法未找到异常
        //    }
        //}
        //Object invoke = null;
        //try {
        //    invoke = method.invoke(enumConstant, stringValue);
        //} catch (Exception e) {
        //    //抛出getKeyByValue方法调用失败异常
        //}

        //注意,当枚举类中没有对应的value时,或者对应value的key是null时,invoke会返回null,此时会出现空指针。
        if (invoke == null) {
            invoke = "未找到指定value对应的key值";
        }
        return invoke;
    }

}

1.原理就是,通过获取注解上传递进来的枚举类,通过反射获取类中的方法,并执行对应的方法获取数据。
2.这里可以做调整,并改为获取到执行内容后,进行其他的业务逻辑,比如添加样式、业务逻辑等。

4.测试实体类


import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;

/**
 * @Description:
 * @author: CloverAn
 * @email: 
 * @created: 2024/08/14 14:59
 */
@Data
public class SexEntity {
    @ExcelProperty(value = "性别",converter = ExcelEnumValueConverter.class)
    @ExcelEnumValue(SexEunm.class)
    String sex;
}

这里就简单模拟了。这时候导入或者导出的时候,对应的值会根据枚举值进行替换。

### 使用 EasyExcel 实现枚举类型的数据导出转换 为了实现枚举类型的导出,在使用 EasyExcel 时可以通过自定义转换器来完成这一功能。下面是一个具体的例子,展示了如何通过创建一个枚举类并利用 `@EnumValue` 注解以及编写相应的读写处理器来进行数据的正确映射。 #### 枚举类定义 首先定义好要使用的枚举类型: ```java public enum StatusEnum { SUCCESS(0, "成功"), FAIL(-1, "失败"); private final int code; private final String desc; StatusEnum(int code, String desc) { this.code = code; this.desc = desc; } public int getCode() {return code;} public String getDesc() {return desc;} /** * 根据code获取对应的枚举对象 */ public static StatusEnum parse(Integer code){ if (null != code){ for(StatusEnum status : values()){ if(status.getCode()==code.intValue()){ return status; } } } throw new IllegalArgumentException("No element matches " + code); } } ``` #### 数据模型实体类设置 接着是在实体类中加入该枚举属性,并指定其显示形式为描述文字而非默认整数编码: ```java import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.metadata.GlobalConfiguration; import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.util.StringUtils; @Data public class OrderInfo { @ExcelProperty(value="订单状态", converter=StatusConverter.class) private StatusEnum orderStatus; } // 自定义转换器用于将枚举转成字符串输出到表格里 public class StatusConverter implements Converter<StatusEnum>{ @Override public Class<?> supportJavaTypeKey(){ return StatusEnum.class; } @Override public CellDataTypeEnum supportExcelTypeKey(){ return CellDataTypeEnum.STRING; } @Override public WriteCellData<String> convertToExcelData(StatusEnum value, GlobalConfiguration globalConfiguration){ if(null!=value && !StringUtils.isEmpty(value.getDesc())){ return new WriteCellData<>(value.getDesc()); }else{ return null; } } @Override public StatusEnum convertToJavaData(CellData cellData, Type targetType, Object attractField, GlobalConfiguration globalConfiguration){ Integer intValue = ((Number)cellData.getStringValue()).intValue(); try{ return StatusEnum.parse(intValue); }catch(IllegalArgumentException e){ log.error("Invalid data found while reading excel file.",e); return null; } } } ``` 上述代码实现了从 Java 对象向 Excel 文件写出时自动把枚举值替换为其描述性的文本表示;而在从 Excel 导入回程序内部结构体的时候,则会尝试依据单元格内的数值找到匹配项恢复原始枚举实例[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我不_CloverAn。

如果文章对你有帮助,感谢支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值