目录
- 引言
- 一、需求场景
- 二、实现思路
- 三、代码实现
- 1、自定义注解 @ExcelSelected
- 2、码表实体与数据库查询
- 3、全局转换器 GlobalCodeConverter
- 4、实体类使用注解
- 5、注册全局转换器
- 四、效果验证
- 五、总结
引言
在实际业务中,我们经常需要将数据库中的码值(如 1, 2, 3)在导出Excel时显示为中文(如“进行中”、“已完成”、&ldq编程uo;已取php消”),而在导入Excel时,用户填写的中文需要自动转换为对应的码值。本文将介绍如何通过全局转换器(GlobalCodeConverter) 和自定义注解实现这一功能,结合数据库动态查询码表,提升代码复用性和可维护性。
一、需求场景
假设有一个订单表,字段 trans_status 存储状态码(1: 进行中,2: 已完成,3: 已取消),需满足以下需求
- 导出Excel时:将 trans_status=1 转换为“进行中”显示
- 导入Excel时:用户输入“进行中”,自动转换为 1 存储到数据库
- 支持多码表:如性别、优先级等字段也需要类似处理
二、实现思路
自定义注解:标记需要转换的字段,并指定码表类型
全局转换器:拦截注解标记的字段,动态查询数据库获取码值映射关系
缓存优化:减少频繁查询数据库,提升性能
三、代码实现
1、自定义注解 @ExcelSelected
用于标记需要转换的字段,指定码表类型
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface ExcelSelected { /** * 码表类型(如www.devze.com trans_status) */ String codeField(); }
2、码表实体与数据库查询
设计码表结构(如 sys_dict)
CREATE TABLE sys_dict ( type VARCHAR(50) COMMENT '码表类型(如trans_status)', code VARCHAR(20) COMMENT '码值', name VARCHAR(50) COMMENT '显示名称' );
3、全局转换器 GlobalCodeConverter
实现 Converter 接口,处理导入导出时的转换逻辑
public class GlobalCodeConverter implements Converter<String> { private static final Map<String, Map<String, String>> CACHE = new ConcurrentHashMap<>(); @Override public Class<String> supportJavaTypeKey() { return String.class; } @Override public CellDataTypeEnum supportExcelTypeKey() { return CellDataTypeEnum.STRING; } // 读取Excel时的转换(中文->码值) @Override public String convertToJavaData(ReadConverterContext<?> context) { String cellValue = context.getReadCellData().getStringValue(); Field field = context.getContentProperty().getField(); ExcelSelected annotation = field.getAnnotation(ExcelSelected.class); if (annotation != null) { Map<String, String> codeMap = getCodeMap(annotation.codeField()); return codeMap.entrySet().stream() .filter(entry -> entry.getValue().equals(cellValue)) .map(Map.Entry::getKey) .findFirst() .orElse(null); } return cellValue; } // 写入Excel时的转换(码值->中文) @Override public WriteCellData<String> convertToExcelData(WriteConverterContext<String> context) { String value = context.getValue(); Field field = context.getContentProperty().getField(); ExcelSelected annotation = field.getAnnotation(ExcelSelected.class); if (annotation != null) { Map<String, String> codeMap = getCodeMap(annotation.codeField()); return new WriteCellData<>(codeMap.get(value)); } return new WriteCellData<>(value); } // 获取码表数据 private Map<String, String> getCodeMap(String codeType) { // 带缓存的码表查询 return CACHE.computeIfAbsent(codeType, k -> { // 实际查询数据库的代码(示例) Map<String, String> map = new HashMap<>(); map.put("1", "进行中"); map.put("2", "已完成"); map.put("3", "已取消"); return map; }); } }
4、实体类使用注解
在需要转换的字段上添加 @ExcelSelected
public class OrderVO { @ExcelProperty("订单状态") @ExcelSelected(codeField = "trans_status") private String transStatus; }
5、注册全局转换器
在导出/导入时注册转换器
// 导出 EasyExcel.write(fileName, OrderVO.class) .registerConverter(new GlobalCodeConverter()) .sheet().doWrite(orders); // 导入 EasyExcel.read(fileName, OrderVO.class, new PageReadListener<>(list -> {})) .rejsgisterConverter(new GlobalCodeConverter()) .sheet().doReaandroidd();
四、效果验证
导出Excel:trans_status=1 显示为“进行中”
导入Excel:用户输入“进行中”,自动转换为 1 存入数据库
五、总结
通过自定义注解和全局转换器,实现了码值与中文的动态转换,代码简洁且易于扩展。这里可以结合之前写的文章EasyExcel自定义下拉注解的三种实现方式总结,进一步提升用户体验。
到此这篇关于浅析EasyExcel如何导出自动回显中文的文章就介绍到这了,更多相关EasyExcel导出自动回显中文内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论