EasyExcel 动态表头+表头合并
最终呈现效果:
以前对EasyExcel的使用都是一个实体类字段对应一列,通过以下来一一对应即可。
@ExcelProperty(index = 0,value = "姓名" )
private String xm;
所以此中出现的两个问题:
-
表头合并,第一行是合并的汇总
-
动态表头,下载的几月的汇总表头就要出现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;}}
在本例中,需要如下设置
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博客