EasyExcel 自定义转换器、自定义导出字典映射替换、满足条件内容增加样式,完整代码+详细注释说明
虽然最之前是在其他地方看到的,但最终因缘巧合下找到了原文,还是尊重一下原作者。
参考引用了这位佬的博客,确实方便使用。
https://blog.csdn.net/qq_45914616/article/details/137200688?spm=1001.2014.3001.5502
这是一个基于Easyexcel通过注解的方式,
在巨人的肩膀上,对相关方法进行了一定的调整和说明注释,方便使用与定制调整为自己所需要的内容格式。
能做到的事情有:
- 通过注解实现自定义字典值映射,满足数字、英文等符合格式的导出字典映射,导入也支持。
- 支持字典值映射的单选或多选模式
- 支持对满足某些条件的内容,在输出时添加一些样式,比如字体颜色。
以下正文:
1.定义了一个枚举类
/*** @Description: 符号枚举类* @author: CloverAn* @email: * @created: 2023/02/27 21:01*/
public class SymbolConstant {private SymbolConstant() {}public static final String SPE1 = ",";/*** 竖线*/public static final String SPE9 = "\\|";}
多余出来的已经做了删除,这两个使用了所以保留,各位可以自行替换修改。
2.添加自定义注解
import com.data.utils.constant.SymbolConstant;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** @Description: 枚举数值的自定义注解* @author: CloverAn* @email:* @created: 2024/06/25 15:57*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface EnumFiledConvert {/*** 枚举映射map key-value,key-value,key-value,key-value* <p>* key|value,key|value* <p>* 注意,这里的key和value都是英文字符串,所以实际上他可以是数字,也可以是英文,也可以是否个字符串* 例如:0|满勤,0-1|特殊,Y|是,n|error** @return*/String enumMap() default "未匹配到映射字典";/*** 枚举类导入、导出在excel中的分隔符号** @return*/String spiteChar() default SymbolConstant.SPE1;/*** 枚举类导入导出字典分隔符*/String dictChar() default SymbolConstant.SPE9;/*** 单选 or 多选* <p>* 即多个枚举映射,都会比对输出,例如** @return* @EnumFiledConvert(enumMap = "1-篮球,2-足球,3-乒乓球,4-羽毛球",single = false)* <p>* 字段值是"1,2,3,4"* 则最终输出的是"篮球,足球,乒乓球,羽毛球"* <p>* 字典值是"1,2"* 则最终输出的是"篮球,足球"*/boolean single() default true;/*** 条件样式,对满足条件的字符串,设置红色字体*/String fontColorMap() default "";
}
1.这里将原作者的直接使用符号,以及符合使用的 逗号和横杠 调整了以下,因为个人有这一块的需求,最终使用的是 逗号和竖线。
2.修改了默认值,添加了部分注释,更通俗易懂。
3.在作者原有的基础上,增加了字体颜色的注解属性,用于接收指定的判断条件和颜色要求
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 com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.data.keepriskexport.utils.constant.SymbolConstant;
import org.springframework.util.StringUtils;import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;/*** 导入导出针对枚举类型的转换器** @author CloverAn*/
public class EasyExcelConvert implements Converter<Object> {/*** 枚举列表*/private Map<String, String> enumMap = new HashMap<>();/*** 条件列表*/private Map<String, String> fontColorMap = new HashMap<>();/*** excel转化后的类型** @return*/@Overridepublic Class<?> supportJavaTypeKey() {return Object.class;}/*** excel中的数据类型,统一设置字符串** @return*/@Overridepublic CellDataTypeEnum supportExcelTypeKey() {return CellDataTypeEnum.STRING;}/*** 导入转换** @param cellData 当前单元格对象* @param contentProperty 当前单元格属性* @param globalConfiguration* @return* @throws Exception*/@Overridepublic Object convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {String cellMsg = cellData.getStringValue();Field field = contentProperty.getField();EnumFiledConvert enumFiledConvert = field.getAnnotation(EnumFiledConvert.class);if (enumFiledConvert == null) {return null;}String enumStr = enumFiledConvert.enumMap();// 解析枚举映射关系getEnumMap(enumStr, true);// 是否为单选boolean single = enumFiledConvert.single();// 如果是单选,默认Java属性为integerif (single) {String res = enumMap.get(cellMsg);return StringUtils.hasText(res) ? Integer.valueOf(res) : null;} else {// 多选分隔符String spiteChar = enumFiledConvert.spiteChar();// 多选枚举,默认Java属性为字符串,格式为 key1,key2,key3List<String> strStr = Arrays.asList(cellMsg.split(spiteChar)).stream().map(s -> String.valueOf(enumMap.get(s))).collect(Collectors.toList());String str = String.join(spiteChar, strStr);return str;}}/*** 导出转化** @param value 当前值* @param contentProperty 当前单元格属性* @param globalConfiguration* @return* @throws Exception*/@Overridepublic WriteCellData<?> convertToExcelData(Object value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {Field field = contentProperty.getField();EnumFiledConvert enumFiledConvert = field.getAnnotation(EnumFiledConvert.class);if (enumFiledConvert == null) {return new WriteCellData();}// 解析枚举字符串String enumStr = enumFiledConvert.enumMap();getEnumMap(enumStr, false);// 是否为单选boolean single = enumFiledConvert.single();//条件样式String conditions = enumFiledConvert.fontColorMap();//解析条件样式getConditionsMap(conditions);// 如果是单选,默认Java属性为integerif (single) {//输出内容原始值String valueOf = String.valueOf(value);//输出内容转换,字典值String orDefault = enumMap.getOrDefault(valueOf, "");//创建输出内容WriteCellData writeCellData = new WriteCellData(orDefault);setWriteCellStyle(writeCellData, orDefault);return writeCellData;} else {// 多选分隔符String spiteChar = enumFiledConvert.spiteChar();// 多选枚举,默认Java属性为字符串,格式为 key1,key2,key3List<String> strStr = Arrays.asList(String.valueOf(value).split(spiteChar)).stream().map(s -> String.valueOf(enumMap.get(s))).collect(Collectors.toList());String str = String.join(spiteChar, strStr);WriteCellData writeCellData = new WriteCellData(str);return writeCellData;}}/*** 根据注解配置的枚举映射字符串进行解析到map中** @param mapStr* @param readOrWrite 读excel 、 写excel*/private void getEnumMap(String mapStr, boolean readOrWrite) {String[] enumS = mapStr.split(SymbolConstant.SPE1);for (String anEnum : enumS) {String[] data = anEnum.split(SymbolConstant.SPE9);if (readOrWrite) {// 读excel excel中的数据都是value,转换成keyenumMap.put(data[1], data[0]);} else {// 写excel Java中的数据都是key,转换成valueenumMap.put(data[0], data[1]);}}}/*** 根据注解配置的枚举映射字符串进行解析到map中* 只有写出的时候生效*/private void getConditionsMap(String conditions) {if (conditions != null && !conditions.isEmpty()) {String[] conditionsMaps = conditions.split(SymbolConstant.SPE1);for (String condition : conditionsMaps) {String[] data = condition.split(SymbolConstant.SPE9);// 写excel Java中的数据都是key,转换成valuefontColorMap.put(data[0], data[1]);}}}/**** 取到什么颜色,填充什么颜色,没有则不填充。** @param writeCellData*/private void setWriteCellStyle(WriteCellData writeCellData, String orDefault) {//输出样式转换,颜色值,默认黑色short orDefaultStyle = 0;//条件,满足条件则修改内容,可以叠加更多的条件,只要符合k-v规则,即比较k,填充v//因为这里是中文k 和 颜色索引,这里比较的就是中文,如果能保障k不重复,则k可以是数字、字符等,对应的v也就可以是数字、字符等,//这样就可以按照需求对单元格式进行一定的操作编辑//需要注意的是,这里用的转换之后的输出值进行的比较,有需要使用原始值的可以自行微调一下if (fontColorMap != null && fontColorMap.containsKey(orDefault)) {WriteFont writeFont = new WriteFont();WriteCellStyle writeCellStyle = new WriteCellStyle();orDefaultStyle = Short.parseShort(fontColorMap.getOrDefault(orDefault, ""));writeFont.setColor(orDefaultStyle);writeCellStyle.setWriteFont(writeFont);writeCellData.setWriteCellStyle(writeCellStyle);}}
}
1.这里面只是修改了部分直接引用字符的地方,将其使用字典值代替。
2.在作者原有的基础上,增加和调整了满足条件后,对字体颜色标记的功能。相关样式可以自己做调整,比如添加背景色等。
逻辑也跟简单,就是拿到转换之后的值,通过这个值,与注解传递的值进行比较,满足条件则添加样式。
因为添加样式只存在于导出的时候,所以只需要关注导出的方法体即可。多选的我暂时没有场景,没有添加,实际逻辑是一样的。
4.测试实体类(因为我懒。不是,要尊重作者! )
import com.alibaba.excel.annotation.ExcelProperty;
import com.example.test.excel.EasyExcelConvert;
import com.example.test.excel.EnumFiledConvert;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** @Author 996* @Date 2024/3/20*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ExcelDto {@ExcelProperty(value = "姓名")private String name;@ExcelProperty(value = "性别",converter = EasyExcelConvert.class)@EnumFiledConvert(enumMap = "0|保密,1|男,2|女")private Integer sex;@ExcelProperty(value = "爱好",converter = EasyExcelConvert.class)@EnumFiledConvert(enumMap = "1|篮球,2|足球,3|乒乓球,4|羽毛球",, fontColorMap = "篮球|2",single = false)private String hobbies;
}
使用时,只需要 2个步骤 ,(1)在实体类上添加自定义注解,(2)在原生的 @ExcelProperty 注解中,指定自定义解析Convert。
这时导出,对应字段列的值,就会被替换成对应的数据项。
需要注意:
1.跟原作者不一样,这里多个字典值之间使用的还是逗号,但是k-v的映射关系使用的是竖线。
2.这里的k-v不一定要符合现在的这种数字和中文的组合,只需要保证k-v分别为字符串,且内容不含逗号竖线即可。比如其他字典映射:Y|是 Y-1|特例1 N|bushi 是|正确的答案 只要符合对应的格式即可,更加灵活。
3.可以修改自定义注解中的符号,以调整对应的格式,但是需要注意,不是所有的都可以直接兼容,需要进行一定的转义,这一点肯定难不倒聪明的你。
4.注意第三个属性的注解,多加了fontColorMap,前面的是输出的值,可以对应enumMap里面的字典值转换,后面的是颜色索引,这里的2标识为红色,可以看org.apache.poi.ss.usermodel.IndexedColors; 中的IndexedColors.RED.getIndex()枚举,颜色索引很全。
基于以上字体颜色修改的逻辑,我们能够拿到所有输出的值的内容,包括原始值,那么我们就可以通过一系列的条件,来实现我们对某些特定内容的数据进行样式调整,包括但不限于字体调整、字体颜色调整、字体颜色调整、数据值调整、单元格背景颜色调整、单元格边框调整等等等等。
5.输出
这个大家都会,这里摘一部分代码套用
//数据集合,这里是用的实体类
List<ClockCount> countList = new ArrayList<>();ExcelWriter excelWriterCount = EasyExcel.write("文件完整路径,含后缀").build();
WriteSheet writeSheetCount = EasyExcel.writerSheet("表格中sheet名称").build();//我这是用实体类进行的文件输出
writeSheetCount.setClazz(ClockCount.class);
//写出数据
excelWriterCount.write(countList , writeSheetCount);
excelWriterCount.finish();
执行导出即可完成。通过循环,或者针对同一文件名,相同sheet名称或者不相同名称,可以实现对同一表格相同sheet页或多个sheet页数据写出,这个就和原生一致了。
相关文章:
EasyExcel 自定义转换器、自定义导出字典映射替换、满足条件内容增加样式,完整代码+详细注释说明
虽然最之前是在其他地方看到的,但最终因缘巧合下找到了原文,还是尊重一下原作者。 参考引用了这位佬的博客,确实方便使用。 https://blog.csdn.net/qq_45914616/article/details/137200688?spm1001.2014.3001.5502 这是一个基于Easyexcel通过…...

C语言学习笔记 Day10(指针--中)
Day10 内容梳理: 目录 Chapter 7 指针 7.4 指针 & 数组 (1)指针操作数组元素 (2)指针加减运算 1)加法 2)减法 (3)指针数组 7.5 多级指针 Chapter 7 指针 …...
网页显示打印 pdf
文件服务使用 minio,使用 nginx 反向代理。 将文件存放在 minio 上,如果是公开的文件,则统一放到一个桶,设置为公开只读。 如果是私有文件,则使用临时链接,给有权限的用户查看和打印。 要实现在 html 页…...

1948-2024.5金融许可信息明细数据
1948-2024.5金融许可信息明细数据 1、时间:1948-2024.5 2、指标:来源表、机构编码、机构名称、所属银行、机构类型、业务范围、机构住所、地理坐标、行政区划代码、所属区县、所属城市、所属省份、邮政编码、发证日期、批准日期、发证机关、流水号、是…...

【笔记】从零开始做一个精灵龙女-画贴图阶段(终)
这篇主要是细节,包括花纹和其它一些细化 皮肤 脖子 脖子一定要压暗,不然前后关系体现不出来 脸 1. 忘了有uv缝了,记得打开投影模式画 顺着头发轨迹长的方向画出发际线 背包手镯 1.先画出暗色花纹: 2.再加亮色,亮…...
从MySQL到Elasticsearch:创建酒店索引案例
在现代的数据管理中,Elasticsearch(简称ES)因其强大的搜索功能和灵活的索引结构而受到广泛欢迎。本篇博客将介绍如何根据MySQL数据库中的酒店表定义,创建一个相应的Elasticsearch索引。 MySQL与Elasticsearch的对比 在开始之前&…...
Webkit与Web Push API:提升用户体验的推送技术
Web Push API是一种允许网站向用户发送通知的Web技术,即使用户没有打开网站也能接收到信息。这项技术可以显著提升用户的参与度和满意度。Webkit,作为Safari和其他浏览器的内核,对Web Push API的支持情况如何?本文将深入探讨Web P…...
Java线程池的拒绝策略
在 Java 线程池中,常见的拒绝策略: AbortPolicy(中止策略) 特点:直接抛出 RejectedExecutionException 异常来拒绝新任务的提交。应用场景:适用于对系统的稳定性要求较高,不希望丢失任务&#…...

【C++进阶】继承
【C进阶】继承 🥕个人主页:开敲🍉 🔥所属专栏:C🥭 🌼文章目录🌼 1. 继承的概念及定义 1.1 继承的概念 1.2 继承定义 1.2.1 定义格式 1.2.2 继承父类成员访问方式的变化 1.3 继承类模…...

立体相机镜面重建(一)镜面标定
无论是单目、双目或者是多屏幕镜面重建,都需要事先对屏幕和相机的相对位置进行标定,求得相机到屏幕之间的相对变换关系。如果求得屏幕和相机之间的变换关系呢?接下来是标定流程。 (一)准备: 1)…...
【如何有效解决前端Vue中的常见难题】
🐟作者简介:一名大三在校生,喜欢编程🪴 🐙个人主页🥇:Aic山鱼🐠WeChat:z7010cyy 🦈系列专栏:🏞️ 前端-JS基础专栏✨前端-Vue框架专栏…...

CLAMP-1靶机渗透测试
一、靶机下载地址 https://www.vulnhub.com/entry/clamp-101,320/ 二、信息收集 1、主机发现 # 使用命令 nmap 192.168.145.0/24 -sn | grep -B 2 "00:0C:29:88:B4:BF" 2、端口扫描 # 使用命令 nmap 192.168.145.0/24 -p- -sV 3、指纹识别 # 使用命令 whatweb …...
JavaScript中的Truthy Falsy值以及等号判断
1.Falsy & Truthy Falsy的值false,0,-0, “”, null, undefined,NaNTruthy的值除了以上之外的其他值 2.等号判断 console.log(10 10); console.log(0 ); console.log(0 false); console.log( fa…...

uniapp——展开和收起
案例展示 代码 后台返回的数据格式如下: {1: "大富科技速度快放假手动阀",2: "第三方斯蒂芬斯蒂芬是的开发时间",4: "45345345",5: "电饭锅电饭锅地方" }<view class"tipTitle">温馨提示</view> &l…...
WebGL2学习(2): GLSL ES 3.0
更多精彩内容尽在 dt.sim3d.cn ,关注公众号【sky的数孪技术】,技术交流、源码下载请添加VX:digital_twin123 WebGL 2.0 给 GLSL 带来了重大变化。WebGL 1.0 中使用的 GLSL 版本是 GLSL ES 1.0。 WebGL 2.0 中仍然可用。但是,通过编…...

[大模型实战] DAMODEL云算力平台部署LLama3.1大语言模型
[大模型实战] DAMODEL云算力平台部署LLama3.1大语言模型 目录 一、LLama3.1二、DAMODEL云算力平台2.1 提供的服务2.1.1 AI训练2.1.2 AI推理2.1.3 高性能计算2.1.4 图像/视频渲染2.1.5 定制化部署 2.2 支持的GPU 三、在DAMODEL部署LLama3.13.1 在DAMODEL创建实例&…...
驱动开发系列09 - Linux设备模型之设备,驱动和总线
一:概述 Linux 设备模型(LDM)是 Linux 内核中引入的一个概念。用于管理内核对象(那些需要引用计数的对象、例如文件、设备、总线甚至驱动程序),以及描述它们之间的层次结构,以及这些内核对象之间绑定关系。Linux 设备模型引入了对象生命周期管理、引用计数、以及面向对象…...

HTML实现弹出层
leopard/ˈlepərd/ 豹子,豹纹 弹出层指的是鼠标悬停于某个元素之上时显示的一个界面组件。 关注和理解特性:z-index属性和动态生成HTML元素。 HTML5新增: figure:媒体内容(图像,音频,视频),用于包含一…...
Android控件详解
在Android应用程序中,界面由布局和组件组成。布局相当于框架,而控件则是框架里面的内容。了解过Android布局后,如果要设计ui界面,还需要了解和掌握各个控件的应用。 一个界面的设计,先从创建容器开始,再向…...

记忆化搜索专题篇
目录 斐波那契数 不同路径 最长递增子序列 猜数字大小II 矩阵中的最长递增路径 声明:下面将主要使用递归记忆化搜索来解决问题!!! 斐波那契数 题目 思路 斐波那契数的特点就是除了第一个数是0,第二个数是1&…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...

高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...

windows系统MySQL安装文档
概览:本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容,为学习者提供全面的操作指导。关键要点包括: 解压 :下载完成后解压压缩包,得到MySQL 8.…...