当前位置: 首页 > news >正文

EasyExcel 动态表头+表头合并

EasyExcel 动态表头+表头合并

​ 最终呈现效果:

请添加图片描述

​ 以前对EasyExcel的使用都是一个实体类字段对应一列,通过以下来一一对应即可。

@ExcelProperty(index = 0,value = "姓名" )
private String xm;

​ 所以此中出现的两个问题:

  1. 表头合并,第一行是合并的汇总

  2. 动态表头,下载的几月的汇总表头就要出现202x年x月销售部门员工·····

  • 表头合并:针对1. EasyExcel对相邻数据相同的单元格将自动合并。为实现上下表头以及上侧表头合并,此处用value={}的形式,即value为表头,集合内多少元素则表头有多少行,此中集合用两个元素即可。value={“currentDate”,“部门”},value={“currentDate”,“出差总人数”}······,此时效果将呈现为上侧currentDate已合并,下侧完成。接下来要做的就是对currentDate在运行时替换为前端传来的month+“销售部门员工出差效果考核情况汇总”
  • 动态表头:原理大概为通过反射进行动态代理。工具类如下:
package com.googosoft.common.utils;import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.CellType;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;/*** 注解工具类*/
public class AnnotationUtils {/*** 变更注解的属性值再处理业务,处理完业务之后恢复类的属性** @param clazz     注解所在的实体类* @param tClass    注解类* @param attrName 要修改的注解属性名* @param attrTypeEnum 要修改的注解属性的类型* @param valueMap  要设置的属性值*/public static <A extends Annotation> void changeAnnotationValueToDealProcess(Class<?> clazz,Class<A> tClass,String attrName,AttrTypeEnum attrTypeEnum,Map<String, String> valueMap,DealProcess dealProcess) {try {Map<String, Object> fieldAnnotationValueMap = new HashMap<>();Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {A annotation = field.getAnnotation(tClass);if (annotation == null) continue;Object value = setAnnotationValue(annotation, attrName, attrTypeEnum, valueMap);String fieldName = field.getName();fieldAnnotationValueMap.put(fieldName, value);}// 处理业务逻辑dealProcess.deal();// 恢复for (Field field : fields) {A annotation = field.getAnnotation(tClass);String fieldName = field.getName();if (annotation == null) continue;Object value = fieldAnnotationValueMap.get(fieldName);InvocationHandler handler = Proxy.getInvocationHandler(annotation);Field memberValuesField = handler.getClass().getDeclaredField("memberValues");memberValuesField.setAccessible(true);@SuppressWarnings("all")Map<String, Object> memberValues = (Map) memberValuesField.get(handler);memberValues.put(attrName, value);}} catch (Exception e) {e.printStackTrace();}}/*** 设置注解中的字段值** @param annotation 要修改的注解实例* @param attrName  要修改的注解属性名* @param attrTypeEnum 要修改的注解属性的类型* @param valueMap   替换属性集的map*/@SuppressWarnings("all")private static Object setAnnotationValue(Annotation annotation, String attrName,AttrTypeEnum attrTypeEnum, Map<String, String> valueMap) throws NoSuchFieldException, IllegalAccessException {InvocationHandler handler = Proxy.getInvocationHandler(annotation);Field field = handler.getClass().getDeclaredField("memberValues");field.setAccessible(true);Map memberValues = (Map) field.get(handler);Object value = memberValues.get(attrName);switch (attrTypeEnum) {case STRING: {String oldValue = (String) value;String newValue = valueMap.get(oldValue);if (StringUtils.isNotBlank(newValue)) {memberValues.put(attrName, newValue);}}break;case STRING_ARR: {String[] oldValue = (String[]) value;String[] newValue = new String[oldValue.length];for (int i = 0; i < oldValue.length; i++) {String replace = valueMap.get(oldValue[i]);newValue[i] = replace != null ? replace : oldValue[i];}memberValues.put(attrName, newValue);}break;}return value;}public enum AttrTypeEnum {STRING,STRING_ARR}public interface DealProcess {void deal() throws Exception;}}

​ 在本例中,需要在controller中如下设置

HashMap<String, String> replaceMap = new HashMap<>();
replaceMap.put("currentDate", month+"销售部门员工出差效果考核情况汇总");
sheetNameMap.put("出差效果统计",sheetNameList);
AnnotationUtils.changeAnnotationValueToDealProcess(CcxgtjInfo.class, ExcelProperty.class, "value", AnnotationUtils.AttrTypeEnum.STRING_ARR, replaceMap, new AnnotationUtils.DealProcess() {@Overridepublic void deal() {   FileDownloadUtils.downLoadMoreSheetFile(response,fileName,sheetNameMap,classMap,dataMap);}});

方法共五个参数,参数解释已于配置类中注释。例中,

1.注解所在实体类为CcxgtjInfo.class。2.注解类为easysxcel注解类。

3.要修改的注解属性名为value。4.要修改的注解属性AnnotationUtils.AttrTypeEnum.STRING_ARR,即{}字符串集合形式。

5.要替代的字符串replaceMap.put(“currentDate”, month+“销售部门员工出差效果考核情况汇总”);

在deal()方法中,将自己的业务逻辑放入即可,例子中为一个多sheet页的导出方法,此处不再展示详情。

本文参考如下:

easyExcel - 动态复杂表头的编写_easyexcel 动态表头-CSDN博客

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • C语言基础——⑩③数据结构——②栈和队列
  • (不用互三)AI绘画工具应该如何选择
  • C语言 | Leetcode C语言题解之第394题字符串解码
  • Spring Framework 学习总结博客
  • 快速入门编写一个Java程序
  • 【mysql】mysql之主从部署以及介绍
  • 无头服务(Headless Service)
  • gen_server补充基础学习
  • linux cmake版本升级教程(Centos7)
  • Vue3:el-table实现日期的格式化
  • 使用python绘制森林图的教程
  • 如何制作Vector Vflash中加载的DLL文件--自动解锁刷写过程中27服务
  • C++类与对象(下)--最后的收尾
  • jmeter依赖jar包找不到类路径
  • SQL入门题
  • [译] 理解数组在 PHP 内部的实现(给PHP开发者的PHP源码-第四部分)
  • 【译】理解JavaScript:new 关键字
  • git 常用命令
  • JavaScript设计模式之工厂模式
  • Linux Process Manage
  • node和express搭建代理服务器(源码)
  • Python打包系统简单入门
  • QQ浏览器x5内核的兼容性问题
  • React+TypeScript入门
  • Vim Clutch | 面向脚踏板编程……
  • 从伪并行的 Python 多线程说起
  • 大快搜索数据爬虫技术实例安装教学篇
  • 力扣(LeetCode)965
  • 每个JavaScript开发人员应阅读的书【1】 - JavaScript: The Good Parts
  • ​如何在iOS手机上查看应用日志
  • # 深度解析 Socket 与 WebSocket:原理、区别与应用
  • #define MODIFY_REG(REG, CLEARMASK, SETMASK)
  • (2)MFC+openGL单文档框架glFrame
  • (C++)栈的链式存储结构(出栈、入栈、判空、遍历、销毁)(数据结构与算法)
  • (LeetCode 49)Anagrams
  • (带教程)商业版SEO关键词按天计费系统:关键词排名优化、代理服务、手机自适应及搭建教程
  • (二)斐波那契Fabonacci函数
  • (免费领源码)python+django+mysql线上兼职平台系统83320-计算机毕业设计项目选题推荐
  • (篇九)MySQL常用内置函数
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (十二)Flink Table API
  • (一)python发送HTTP 请求的两种方式(get和post )
  • (转)MVC3 类型“System.Web.Mvc.ModelClientValidationRule”同时存在
  • *算法训练(leetcode)第四十五天 | 101. 孤岛的总面积、102. 沉没孤岛、103. 水流问题、104. 建造最大岛屿
  • .net core Redis 使用有序集合实现延迟队列
  • .NET 的静态构造函数是否线程安全?答案是肯定的!
  • @EnableAsync和@Async开始异步任务支持
  • @hook扩展分析
  • @media screen 针对不同移动设备
  • @Resource和@Autowired的区别
  • [ Algorithm ] N次方算法 N Square 动态规划解决
  • [ 云计算 | Azure 实践 ] 在 Azure 门户中创建 VM 虚拟机并进行验证
  • [04]Web前端进阶—JS伪数组
  • [2010-8-30]
  • [30期] 我的学习方法