实现 easyExcel 导入导出自定义字典转换器

一、easyExcel 字典转换器 Converter

easyExcel 导入导出自定义字典转换器,包括导入字典转换以及导出字典转换。适配多个逗号分隔的字典值转换。

1、excel 导入字典转换注解

java 复制代码
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * excel导入字典转换注解
 * <p>
 * 将excel导入的字典label自动转换为字典code
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using = DictItemSerialize.class)
public @interface ExcelDictItemLabel {

	/**
	 * 字典type
	 */
	String type();

}

2、excel 导出字典转换注解

java 复制代码
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * excel导出字典转换注解
 * <p>
 * 将excel导出的字典code自动转换为字典label
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using = DictItemSerialize.class)
public @interface ExcelDictItem {

	/**
	 * 字典type
	 */
	String type();

}

3、自定义 excel 转换器

java 复制代码
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.CellData;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.whitemeen.magic.common.core.constant.CacheConstants;
import com.whitemeen.magic.common.core.constant.SecurityConstants;
import com.whitemeen.magic.common.core.util.R;
import com.whitemeen.magic.common.core.util.SpringContextHolder;
import com.whitemeen.magic.upms.modules.admin.api.entity.SysDictItem;
import com.whitemeen.magic.upms.modules.admin.api.feign.RemoteDictService;
import com.whitemeen.magic.upms.modules.admin.config.ExcelDictItem;
import com.whitemeen.magic.upms.modules.admin.config.ExcelDictItemLabel;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Excel Converter字典转换器
 */
public class ExcelDictConverter implements Converter<String> {

	public ExcelDictConverter() {
	}

	@Override
	public Class supportJavaTypeKey() {
		return null;
	}

	@Override
	public CellDataTypeEnum supportExcelTypeKey() {
		return null;
	}

	/**
	 * 将excel单元格数据转换成对象属性值(适配多个逗号分隔的字典值)
	 *
	 * @param cellData             单元格的数据
	 * @param excelContentProperty excel每一行的数据内容
	 * @param globalConfiguration  global全局配置
	 * @return 转换后的对象属性值
	 * @throws Exception 异常
	 */
	@Override
	public String convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
		// 获取字典类型
		Field field = excelContentProperty.getField();
		ExcelDictItemLabel excel = field.getAnnotation(ExcelDictItemLabel.class);
		String dictType = excel.type();

		// 为空返回
		String dictLabel = cellData.getStringValue();
		if (StrUtil.isBlank(dictLabel)) {
			return dictLabel;
		}

		// 查询字典
		CacheManager cacheManager = SpringContextHolder.getBean(CacheManager.class);
		Cache dictCache = cacheManager.getCache(CacheConstants.DICT_DETAILS);
		R<List<SysDictItem>> dictItemListR = dictCache.get(dictType, R.class);

		if (dictItemListR == null) {
			RemoteDictService dictService = SpringContextHolder.getBean(RemoteDictService.class);
			dictItemListR = dictService.customize(dictType, SecurityConstants.FROM_IN);
		}
		if (dictItemListR == null || CollectionUtils.isEmpty(dictItemListR.getData())) {
			return dictLabel;
		}

		// 将字典项根据label分组
		Map<String, SysDictItem> dictItemLabelMap = dictItemListR.getData()
				.stream().collect(Collectors.toMap(SysDictItem::getLabel, Function.identity(), (v1, v2) -> v2));

		// 存在多个字典项值
		List<String> dictLabelList = Arrays.stream(dictLabel.split(",")).collect(Collectors.toList());
		StringBuilder dictValues = new StringBuilder();

		// 字典转换拼接
		for (String sourcesDictLabel : dictLabelList) {
			SysDictItem sysDictItem = dictItemLabelMap.get(sourcesDictLabel);
			if (sysDictItem == null) {
				continue;
			}

			if (StrUtil.isBlank(dictValues)) {
				dictValues.append(sysDictItem.getItemValue());
			} else {
				dictValues.append(",").append(sysDictItem.getItemValue());
			}
		}

		return String.valueOf(dictValues);
	}

	
//	/**
//	 * 将excel单元格数据转换成对象属性值(仅适配单个字典值)
//	 *
//	 * @param cellData             单元格的数据
//	 * @param excelContentProperty excel每一行的数据内容
//	 * @param globalConfiguration  global全局配置
//	 * @return 转换后的对象属性值
//	 * @throws Exception 异常
//	 */
//	@Override
//	public String convertToJavaData(CellData cellData, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
//		// 获取字典类型
//		Field field = excelContentProperty.getField();
//		ExcelDictItemLabel excel = field.getAnnotation(ExcelDictItemLabel.class);
//		String dictType = excel.type();
//
//		String dictLabel = cellData.getStringValue();
//		if (StrUtil.isBlank(dictLabel)) {
//			return dictLabel;
//		}
//		// 查询字典
//		RemoteDictService remoteDictService = SpringContextHolder.getBean(RemoteDictService.class);
//		R<List<SysDictItem>> dictItemsR = remoteDictService.getDictByType(dictType);
//		if (CollectionUtil.isEmpty(dictItemsR.getData())) {
//			return dictLabel;
//		}
//		// 进行字典翻译
//		String javaData = dictLabel;
//		List<SysDictItem> dictItems = dictItemsR.getData();
//		for (SysDictItem dictItem : dictItems) {
//			if (StrUtil.equals(dictLabel, dictItem.getLabel())) {
//				javaData = dictItem.getItemValue();
//				break;
//			}
//		}
//		return javaData;
//	}

	/**
	 * 将对象属性值转换成excel单元格数据(适配多个逗号分隔的字典值)
	 *
	 * @param dictValue            对象的属性值
	 * @param excelContentProperty excel每一行的数据内容
	 * @param globalConfiguration  global全局配置
	 * @return 转换后的对象属性值
	 * @throws Exception 异常
	 */
	@Override
	public CellData convertToExcelData(String dictValue, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
		// 获取字典类型
		Field field = excelContentProperty.getField();
		ExcelDictItem excel = field.getAnnotation(ExcelDictItem.class);
		String dictType = excel.type();

		// 为空返回
		if (StrUtil.isBlank(dictValue)) {
			return new CellData(dictValue);
		}

		// 查询字典
		CacheManager cacheManager = SpringContextHolder.getBean(CacheManager.class);
		Cache dictCache = cacheManager.getCache(CacheConstants.DICT_DETAILS);
		R<List<SysDictItem>> dictItemListR = dictCache.get(dictType, R.class);

		if (dictItemListR == null) {
			RemoteDictService dictService = SpringContextHolder.getBean(RemoteDictService.class);
			dictItemListR = dictService.customize(dictType, SecurityConstants.FROM_IN);
		}
		if (dictItemListR == null || CollectionUtils.isEmpty(dictItemListR.getData())) {
			return new CellData(dictValue);
		}

		// 将字典项根据value分组
		Map<String, SysDictItem> dictItemValueMap = dictItemListR.getData()
				.stream().collect(Collectors.toMap(SysDictItem::getItemValue, Function.identity(), (v1, v2) -> v2));

		// 存在多个字典项值
		List<String> dictValueList = Arrays.stream(dictValue.split(",")).collect(Collectors.toList());
		StringBuilder dictLabels = new StringBuilder();

		// 字典转换拼接
		for (String sourcesDictLabel : dictValueList) {
			SysDictItem sysDictItem = dictItemValueMap.get(sourcesDictLabel);
			if (sysDictItem == null) {
				continue;
			}

			if (StrUtil.isBlank(dictLabels)) {
				dictLabels.append(sysDictItem.getLabel());
			} else {
				dictLabels.append(",").append(sysDictItem.getLabel());
			}
		}

		if(StrUtil.isBlank(String.valueOf(dictLabels))){
			return new CellData(dictValue);
		}
		return new CellData(String.valueOf(dictLabels));
	}
	
//	/**
//	 * 将对象属性值转换成excel单元格数据(仅适配单个字典值)
//	 *
//	 * @param dictValue            对象的属性值
//	 * @param excelContentProperty excel每一行的数据内容
//	 * @param globalConfiguration  global全局配置
//	 * @return 转换后的对象属性值
//	 * @throws Exception 异常
//	 */
//	@Override
//	public CellData convertToExcelData(String dictValue, ExcelContentProperty excelContentProperty, GlobalConfiguration globalConfiguration) throws Exception {
//		// 获取字典类型
//		Field field = excelContentProperty.getField();
//		String fieldName = field.getName();
//		DictItem excel = field.getAnnotation(DictItem.class);
//		String dictType = excel.type();
//		// 查询字典
//		RemoteDictService remoteDictService = SpringContextHolder.getBean(RemoteDictService.class);
//		R<List<SysDictItem>> dictItemsR = remoteDictService.getDictByType(dictType);
//		if (CollectionUtil.isEmpty(dictItemsR.getData())) {
//			return new CellData(dictValue);
//		}
//		// 进行字典翻译
//		String excelData = dictValue;
//		List<SysDictItem> dictItems = dictItemsR.getData();
//		for (SysDictItem dictItem : dictItems) {
//			if (StrUtil.equals(dictValue, dictItem.getItemValue())) {
//				excelData = dictItem.getLabel();
//				break;
//			}
//		}
//		return new CellData(excelData);
//	}

}

4、使用 excel 字典转换注解

java 复制代码
	/**
	 * 性别label(用于接收与展现真实的excel内容)
	 */
	@ExcelProperty(value = "性别", converter = ExcelDictConverter.class)
	@ExcelDictItemLabel(type = "gender")
	private String genderLabel;

	/**
	 * 性别code(用来承载java对象属性值)
	 */
	@ExcelIgnore
	@ExcelDictItem(type = "gender")
	private String gender;
	
相关推荐
代码方舟9 小时前
零信任架构实战:基于天远人企关联构建自动化供应链核心企业关联穿透与利益冲突审查网关
java·人工智能·架构·自动化
多弗朗皮卡丘10 小时前
C++的IO流
开发语言·c++·io流·文件io流
liyi_hz200810 小时前
O2OA(翱途) V10.1 即将发布|功能再升级,安全再加固,协同更高效!
java·javascript·windows·开源软件
骑着蜗牛撵大象32710 小时前
AI Agent 工程化开发实战(三):用 StateGraph 给智能体搭一条可回放的状态流水线
java·开发语言·jvm·ai·状态管理·langgraph·stategraph
Random Glow10 小时前
二级索引与回表:一次回表到底多贵
数据库·mysql·性能优化·innodb·索引
itmigrate10 小时前
Rust 里的所有权误区:不是不写 clone 就叫高性能
开发语言·后端·rust
Brilliantwxx10 小时前
【Linux】 文件访问与路径解析:目录、文件名、dentry、路径缓冲与 dcache 全解析
linux·运维·服务器·开发语言·spring
CarIise10 小时前
JDBC 与数据库事务核心
数据库·笔记
见闻小天地10 小时前
新手入门:印刷包装设备的伺服和PLC运动控制方案各管什么?七步选型讲清楚
运维·网络·数据库·人工智能
鬼手点金10 小时前
KV Cache 未必是一次性的:可编辑、可组合的“笔记”
java·人工智能·笔记·学习·自动化·1024程序员节