基于EasyExcel实现通用版一对一、一对多、多层嵌套结构数据导出并支持主动归并单元格

[复制链接]
发表于 2025-11-11 09:17:53 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
接口功能

        通用
        支持一对一数据结构导出
        支持一对多数据结构导出
        支持多层嵌套数据结构导出
        支持单元格主动归并

原文来自:
新增及修复

基于我自己的利用场景,新增并能修复一下功能:


  • 修复了只有单条一对一数据无法导出标题;
  • 修复了多层嵌套数据结构中存在某个嵌套聚集为空无法导出标题;
  • 修复了只有一条一对多数据导出时报错标题;
完备源码分析

自界说注解:


  • @MyExcelProperty 作用到导出字段上面,表现这是Excel的一列
  • @MyExcelCollection 表现一个聚集,紧张针对一对多的导出,比如一个老师对应多个科目,科目就可以用聚集表现
  • @MyExcelEntity 表现一个还存在嵌套关系的导出实体(我的利用场景中并未用到该解释)
property为根本数据范例的注解类

  1. package com.example.excel.annotation;
  2. import java.lang.annotation.*;
  3. @Inherited
  4. @Target({ElementType.FIELD})
  5. @Retention(RetentionPolicy.RUNTIME)
  6. public @interface MyExcelProperty {
  7.     String name() default "";
  8.     int index() default Integer.MAX_VALUE;
  9. }
复制代码
property为聚集的注解类

  1. package com.example.excel.annotation;
  2. import java.lang.annotation.ElementType;
  3. import java.lang.annotation.Retention;
  4. import java.lang.annotation.RetentionPolicy;
  5. import java.lang.annotation.Target;
  6. @Target({ElementType.FIELD})
  7. @Retention(RetentionPolicy.RUNTIME)
  8. public @interface MyExcelCollection {
  9.     String name();
  10. }
复制代码
property为实体对象的注解类

  1. package com.example.excel.annotation;
  2. import java.lang.annotation.ElementType;
  3. import java.lang.annotation.Retention;
  4. import java.lang.annotation.RetentionPolicy;
  5. import java.lang.annotation.Target;
  6. @Target({ElementType.FIELD})
  7. @Retention(RetentionPolicy.RUNTIME)
  8. public @interface MyExcelEntity {
  9.     String name() default "";
  10. }
复制代码
导出参数类

  1. package com.example.excel.excel;
  2. import lombok.Data;
  3. import lombok.experimental.Accessors;
  4. @Data
  5. @Accessors(chain = true)
  6. public class ExportParam {
  7.     private String fieldName;
  8.     private String columnName;
  9.     private Integer order;
  10. }
复制代码
导出实体类

  1. package com.example.excel.excel;
  2. import lombok.Data;
  3. import java.util.List;
  4. import java.util.Map;
  5. @Data
  6. public class ExportEntity {
  7.     /**
  8.      * 导出参数
  9.      */
  10.     private List<ExportParam> exportParams;
  11.     /**
  12.      * 平铺后的数据
  13.      */
  14.     private List<Map<String,Object>> data;
  15.     /**
  16.      * 每列的合并行数组
  17.      */
  18.     private Map<String, List<Integer[]>> mergeRowMap;
  19. }
复制代码
导出工具类

  1. package com.example.excel.excel;
  2. import com.alibaba.excel.EasyExcel;
  3. import com.example.excel.annotation.MyExcelCollection;
  4. import com.example.excel.annotation.MyExcelEntity;
  5. import com.example.excel.annotation.MyExcelProperty;
  6. import com.google.common.base.Preconditions;
  7. import com.google.common.collect.Lists;
  8. import jakarta.servlet.http.HttpServletResponse;
  9. import org.apache.commons.collections4.CollectionUtils;
  10. import org.apache.commons.lang3.StringUtils;
  11. import java.io.IOException;
  12. import java.lang.reflect.Field;
  13. import java.lang.reflect.ParameterizedType;
  14. import java.net.URLEncoder;
  15. import java.util.*;
  16. import java.util.stream.Collectors;
  17. public class MyExcelUtil {
  18.     private final String DELIMITER = ".";
  19.     /**
  20.      * @param sourceData 导出数据源
  21.      * @param fileName   导出文件名
  22.      * @param response
  23.      */
  24.     public void exportData(Collection<Object> sourceData, String sheetName, HttpServletResponse response) {
  25.         if (CollectionUtils.isEmpty(sourceData))
  26.             return;
  27.         // 将源数据平铺成List<Map<String, Object>>类型
  28.         ExportEntity exportEntity = flattenObject(sourceData);
  29.         // 获取要导出的列字段
  30.         List<String> columnList = exportEntity.getExportParams().stream()
  31.                 .sorted(Comparator.comparing(ExportParam::getOrder))
  32.                 .map(ExportParam::getFieldName)
  33.                 .collect(Collectors.toList());
  34.         // 获取导出数据集
  35.         List<List<Object>> exportDataList = new ArrayList<>();
  36.         for (Map<String, Object> objectMap : exportEntity.getData()) {
  37.             List<Object> data = new ArrayList<>();
  38.             columnList.stream().forEach(columnName -> {
  39.                 data.add(objectMap.get(columnName));
  40.             });
  41.             exportDataList.add(data);
  42.         }
  43.         List<List<String>> headList = columnList.stream().map(Lists::newArrayList).collect(Collectors.toList());
  44.         try {
  45.             response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
  46.             response.setCharacterEncoding("utf-8");
  47.             WriteCellStyle[] cellStyles = cellStyleStrategy();
  48.             EasyExcel.write(response.getOutputStream()).sheet(sheetName)
  49.                     .head(headList)
  50.                     .registerWriteHandler(new MergeStrategy(exportEntity))
  51.                     .registerWriteHandler(new HeadHandler(exportEntity))
  52.                     .registerWriteHandler(new HorizontalCellStyleStrategy(cellStyle[0], cellStyle[1]))
  53.                     .doWrite(exportDataList);
  54.         } catch (IOException e) {
  55.             e.printStackTrace();
  56.         }
  57.     }
  58.     /**
  59.      * 获取导出数据:导出字段-值
  60.      * 合并区间map:导出字段-[start, end]
  61.      *
  62.      * @param sourceData
  63.      * @return
  64.      */
  65.     public ExportEntity flattenObject(Collection<Object> sourceData) {
  66.         Map<String, List<Integer[]>> mergeMap = new HashMap<>();
  67.         // 判断源数据class
  68.         Class aClass = sourceData.stream().findFirst().get().getClass();
  69.         // 获取导出字段
  70.         List<ExportParam> exportParams = getAllExportField(aClass, "");
  71.         Preconditions.checkArgument(!exportParams.isEmpty(), "export field not found !");
  72.         // 获取导出数据:导出字段-值 合并区间map:导出字段-[start, end]
  73.         List<Map<String, Object>> target = new ArrayList<>();
  74.         Integer startRow = 0;
  75.         for (Object sourceDataLine : sourceData) {
  76.             List<Map<String, Object>> flatData = flattenObject(sourceDataLine, "", startRow, mergeMap);
  77.             startRow += flatData.size();
  78.             target.addAll(flatData);
  79.         }
  80.         // 包装为导出实体
  81.         ExportEntity exportEntity = new ExportEntity();
  82.         exportEntity.setExportParams(exportParams);
  83.         exportEntity.setData(target);
  84.         exportEntity.setMergeRowMap(mergeMap);
  85.         return exportEntity;
  86.     }
  87.     /**
  88.      * @param data     数据行
  89.      * @param preNode  上一层级字段名
  90.      * @param startRow 当前数据行所在行数
  91.      * @param mergeMap 各字段合并行数组
  92.      * @return
  93.      */
  94.     private List<Map<String, Object>> flattenObject(Object data, String preNode, Integer startRow,
  95.             Map<String, List<Integer[]>> mergeMap) {
  96.         List<Map<String, Object>> flatList = new ArrayList<>();
  97.         if (null == data)
  98.             return flatList;
  99.         // 获取不为null的excel导出字段
  100.         Class<?> aClass = data.getClass();
  101.         List<Field> collectionFields = new ArrayList<>();
  102.         List<Field> entityFields = new ArrayList<>();
  103.         List<Field> propertyFields = new ArrayList<>();
  104.         for (Field field : aClass.getDeclaredFields()) {
  105.             Object value = getFieldValue(field, data);
  106.             if (null == value)
  107.                 continue;
  108.             if (isCollection(field)) {
  109.                 collectionFields.add(field);
  110.             } else if (isEntity(field)) {
  111.                 entityFields.add(field);
  112.             } else if (isProperty(field)) {
  113.                 propertyFields.add(field);
  114.             }
  115.         }
  116.         // 对被@MyExcelCollection和@MyExcelEntity注解修饰的field继续flat
  117.         List<Map<String, Object>> entityFlatData = flattenEntityFields(entityFields, data, preNode, startRow, mergeMap);
  118.         List<List<Map<String, Object>>> collectionFlatData = flattenCollectionFields(collectionFields, data, preNode,
  119.                 startRow, mergeMap);
  120.         Map<String, Object> objectMap = Collections.emptyMap();
  121.         if (collectionFields.isEmpty() && entityFields.isEmpty()) {
  122.             objectMap = flattenPropertyFields(propertyFields, data, preNode);
  123.         }
  124.         // 解决当前层级collecting和entity属性对应的值都是null时,导致property属性也被自动忽略,无法导出的问题
  125.         if (collectionFlatData.isEmpty() && entityFlatData.isEmpty()) {
  126.             objectMap = flattenPropertyFields(propertyFields, data, preNode);
  127.         }
  128.         if (!objectMap.isEmpty()) {
  129.             flatList.add(objectMap);
  130.         }
  131.         // 当前层级所有平铺列表
  132.         List<List<Map<String, Object>>> allFlatData = Lists.newArrayList();
  133.         if (!entityFlatData.isEmpty()) {
  134.             allFlatData.add(entityFlatData);
  135.         }
  136.         if (!collectionFlatData.isEmpty()) {
  137.             allFlatData.addAll(collectionFlatData);
  138.         }
  139.         List<Map<String, Object>> mergeList = mergeList(data, allFlatData, propertyFields, preNode, startRow, mergeMap);
  140.         if (!mergeList.isEmpty()) {
  141.             flatList.addAll(mergeList);
  142.         }
  143.         return flatList;
  144.     }
  145.     /**
  146.      * flat被@MyExcelEntity注解修饰的field的平铺结果和合并列表
  147.      *
  148.      * @return
  149.      */
  150.     private List<Map<String, Object>> flattenEntityFields(List<Field> entityFields, Object data, String preNode,
  151.             Integer startRow, Map<String, List<Integer[]>> mergeMap) {
  152.         List<Map<String, Object>> entityFlatData = Lists.newArrayList();
  153.         for (Field entityField : entityFields) {
  154.             entityFlatData = flattenObject(getFieldValue(entityField, data),
  155.                     buildPreNode(preNode, entityField.getName()), startRow, mergeMap);
  156.         }
  157.         return entityFlatData;
  158.     }
  159.     /**
  160.      * flat被@MyExcelCcollection注解修饰的field的平铺结果和合并列表
  161.      *
  162.      * @return
  163.      */
  164.     private List<List<Map<String, Object>>> flattenCollectionFields(List<Field> collectionFields, Object data,
  165.             String preNode, Integer startRow, Map<String, List<Integer[]>> mergeMap) {
  166.         List<List<Map<String, Object>>> collectionFlatData = Lists.newArrayList();
  167.         for (Field collectionField : collectionFields) {
  168.             Collection collectionValue = (Collection) getFieldValue(collectionField, data);
  169.             // 当前集合字段平铺而成的数据列表
  170.             List<Map<String, Object>> collectionObjectValue = new ArrayList<>();
  171.             // 间隔行数
  172.             Integer row = 0;
  173.             for (Object value : collectionValue) {
  174.                 List<Map<String, Object>> flatData = flattenObject(value,
  175.                         buildPreNode(preNode, collectionField.getName()), startRow + row, mergeMap);
  176.                 if (!flatData.isEmpty()) {
  177.                     collectionObjectValue.addAll(flatData);
  178.                     // 下条数据的起始间隔行
  179.                     row += flatData.size();
  180.                 }
  181.             }
  182.             if (!collectionObjectValue.isEmpty()) {
  183.                 collectionFlatData.add(collectionObjectValue);
  184.             }
  185.         }
  186.         return collectionFlatData;
  187.     }
  188.     /**
  189.      * flat被@MyExcelProperty注解修饰的field的平铺结果和合并列表
  190.      *
  191.      * @return
  192.      */
  193.     private Map<String, Object> flattenPropertyFields(List<Field> propertyFields, Object data, String preNode) {
  194.         Map<String, Object> flatMap = new HashMap<>();
  195.         for (Field field : propertyFields) {
  196.             flatMap.put(buildPreNode(preNode, field.getName()), getFieldValue(field, data));
  197.         }
  198.         return flatMap;
  199.     }
  200.     /**
  201.      * 返回待合并的集合 层级字段名:[start, end]
  202.      *
  203.      * @return
  204.      */
  205.     private List<Map<String, Object>> mergeList(Object data, List<List<Map<String, Object>>> allFlatData,
  206.             List<Field> propertyFields, String preNode, Integer startRow, Map<String, List<Integer[]>> mergeMap) {
  207.         List<Map<String, Object>> flatList = new ArrayList<>();
  208.         // 当前层级下多个集合字段的最大长度即为当前层级其他字段的合并行数
  209.         Integer maxSize = 0;
  210.         for (List<Map<String, Object>> list : allFlatData) {
  211.             maxSize = Math.max(maxSize, list.size());
  212.         }
  213.         // 记录集合同层级其他字段的合并行数
  214.         if (maxSize > 0) {
  215.             buildMerge(propertyFields, preNode, startRow, startRow + maxSize, mergeMap);
  216.         }
  217.         // 需要合并
  218.         if (maxSize > 1) {
  219.             // 重新构建平铺的list
  220.             List<Map<String, Object>> mergeFlatData = new ArrayList<>(maxSize);
  221.             for (int i = 0; i < maxSize; i++) {
  222.                 mergeFlatData.add(new HashMap<>());
  223.             }
  224.             for (List<Map<String, Object>> flatData : allFlatData) {
  225.                 for (int i = 0; i < flatData.size(); i++) {
  226.                     Map<String, Object> flatMap = new HashMap<>();
  227.                     flatMap.putAll(flatData.get(i));
  228.                     // 添加同层级字段值
  229.                     if (CollectionUtils.isNotEmpty(propertyFields)) {
  230.                         for (Field field : propertyFields) {
  231.                             flatMap.put(buildPreNode(preNode, field.getName()), getFieldValue(field, data));
  232.                         }
  233.                     }
  234.                     mergeFlatData.get(i).putAll(flatMap);
  235.                 }
  236.             }
  237.             flatList.addAll(mergeFlatData);
  238.         } else {
  239.             // 解决只有单行数据时,前节点无法flat的问题
  240.             Map<String, Object> result = new HashMap<>();
  241.             for (List<Map<String, Object>> list : allFlatData) {
  242.                 for (Field propertyField : propertyFields) {
  243.                     result.put(buildPreNode(preNode, propertyField.getName()), getFieldValue(propertyField, data));
  244.                 }
  245.                 result.putAll(li.get(0));
  246.             }
  247.             if (!result.isEmpty()) {
  248.                 flatList.add(result);
  249.             }
  250.         }
  251.         return flatList;
  252.     }
  253.     /**
  254.      * @param mergeFields   需要合并的字段
  255.      * @param preNode       上一层级字段名
  256.      * @param mergeStartRow 合并开始行
  257.      * @param mergeEndRow   合并结束行
  258.      * @param mergeMap      各字段合并行数组
  259.      */
  260.     private void buildMerge(List<Field> mergeFields, String preNode, Integer mergeStartRow, Integer mergeEndRow,
  261.             Map<String, List<Integer[]>> mergeMap) {
  262.         for (int k = 0; k < mergeFields.size(); k++) {
  263.             String fieldName = buildPreNode(preNode, mergeFields.get(k).getName());
  264.             List<Integer[]> list = mergeMap.get(fieldName);
  265.             if (null == list) {
  266.                 mergeMap.put(fieldName, new ArrayList<>());
  267.             }
  268.             Integer[] rowInterval = new Integer[2];
  269.             // 合并开始行
  270.             rowInterval[0] = mergeStartRow;
  271.             // 合并结束行
  272.             rowInterval[1] = mergeEndRow;
  273.             mergeMap.get(fieldName).add(rowInterval);
  274.         }
  275.     }
  276.     /**
  277.      * 获取导出参数
  278.      *
  279.      * @param clazz   导出类
  280.      * @param preNode 上一层级字段名
  281.      * @return
  282.      */
  283.     private List<ExportParam> getAllExportField(Class<?> clazz, String preNode) {
  284.         List<ExportParam> exportFields = new ArrayList<>();
  285.         // 遍历类对象中声明的所有field
  286.         for (Field declaredField : clazz.getDeclaredFields()) {
  287.             // 检查field是否被注解
  288.             MyExcelProperty myExcelProperty = declaredField.getDeclaredAnnotation(MyExcelProperty.class);
  289.             MyExcelEntity myExcelEntity = declaredField.getDeclaredAnnotation(MyExcelEntity.class);
  290.             MyExcelCollection myExcelCollection = declaredField.getDeclaredAnnotation(MyExcelCollection.class);
  291.             // 构建层级关系,比如:lineConfigs.msgConfigs.msgName
  292.             String fieldName = buildPreNode(preNode, declaredField.getName());
  293.             // @MyExcelProperty注解的字段直接作为输出列
  294.             if (null != myExcelProperty) {
  295.                 ExportParam exportParam = new ExportParam()
  296.                         .setFieldName(fieldName)
  297.                         .setColumnName(myExcelProperty.name())
  298.                         .setOrder(myExcelProperty.index());
  299.                 exportFields.add(exportParam);
  300.             }
  301.             // @MyExcelEntity注解的字段继续遍历
  302.             else if (null != myExcelEntity) {
  303.                 exportFields.addAll(getAllExportField(declaredField.getType(), fieldName));
  304.             }
  305.             // @MyExcelCollection注解的字段继续遍历
  306.             else if (null != myExcelCollection) {
  307.                 boolean isCollection = Collection.class.isAssignableFrom(declaredField.getType());
  308.                 if (!isCollection)
  309.                     continue;
  310.                 ParameterizedType pt = (ParameterizedType) declaredField.getGenericType();
  311.                 Class<?> clz = (Class<?>) pt.getActualTypeArguments()[0];
  312.                 exportFields.addAll(getAllExportField(clz, fieldName));
  313.             }
  314.         }
  315.         return exportFields;
  316.     }
  317.     /**
  318.      * 返回某个字段是否被@MyExccelProperty注解
  319.      *
  320.      * @return
  321.      */
  322.     private boolean isProperty(Field field) {
  323.         return null != field.getDeclaredAnnotation(MyExcelProperty.class) ? true : false;
  324.     }
  325.     /**
  326.      * 返回某个字段是否被@MyExccelEntity注解
  327.      *
  328.      * @return
  329.      */
  330.     private boolean isEntity(Field field) {
  331.         return null != field.getDeclaredAnnotation(MyExcelEntity.class) ? true : false;
  332.     }
  333.     /**
  334.      * 返回某个字段是否被@MyExccelCollection注解
  335.      *
  336.      * @return
  337.      */
  338.     private boolean isCollection(Field field) {
  339.         boolean isCollection = Collection.class.isAssignableFrom(field.getType());
  340.         return isCollection && null != field.getAnnotation(MyExcelCollection.class) ? true : false;
  341.     }
  342.     /**
  343.      * @param preNode   上一层级字段名
  344.      * @param fieldName 当前字段名
  345.      * @return
  346.      */
  347.     private String buildPreNode(String preNode, String fieldName) {
  348.         StringBuffer sb = new StringBuffer();
  349.         return StringUtils.isEmpty(preNode) ? fieldName
  350.                 : sb.append(preNode).append(DELIMITER).append(fieldName).toString();
  351.     }
  352.     /**
  353.      * 返回对象中某个字段的值
  354.      *
  355.      * @return
  356.      */
  357.     private Object getFieldValue(Field field, Object sourceObject) {
  358.         Object fieldValue;
  359.         try {
  360.             // 允许访问private属性
  361.             field.setAccessible(true);
  362.             fieldValue = field.get(sourceObject);
  363.         } catch (IllegalAccessException e) {
  364.             throw new RuntimeException(e);
  365.         }
  366.         return fieldValue;
  367.     }
  368.     /**
  369.      * 单元格样式
  370.      *
  371.      * @return
  372.      */
  373.     public WriteCellStyle[] cellStyleStrategy() {
  374.         WriteCellStyle[] styles = new WriteCellStyle[2];
  375.         WriteFont titleFont = new WriteFont();
  376.         titleFont.setFontName("Arial");
  377.         titleFont.setFontHeightInPoints((short) 12);
  378.         titleFont.setBold(true);
  379.         WriteCellStyle headCellStyle = new WriteCellStyle();
  380.         headCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
  381.         headCellStyle/setHorizontalAlignment(HorzontalAlignment.CENTER);
  382.         headCellStyle.setWriteFOnt(titleFont);
  383.         styles[0] = headCellStyle;
  384.         WriteCellStyle cellStyle = new WriteCellStyle();
  385.         cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
  386.         cellStyle/setHorizontalAlignment(HorzontalAlignment.CENTER);
  387.         styles[1] = cellStyle;
  388.         return styles;
  389.     }
  390. }
复制代码
单元格归并战略

  1. package com.example.excel.excel;
  2. import com.alibaba.excel.metadata.Head;
  3. import com.alibaba.excel.write.merge.AbstractMergeStrategy;
  4. import org.apache.poi.ss.usermodel.Cell;
  5. import org.apache.poi.ss.usermodel.Sheet;
  6. import org.apache.poi.ss.util.CellRangeAddress;
  7. import org.springframework.util.CollectionUtils;
  8. import java.util.List;
  9. public class MergeStrategy extends AbstractMergeStrategy {
  10.     private ExportEntity exportEntity;
  11.     public MergeStrategy(ExportEntity exportEntity) {
  12.         this.exportEntity = exportEntity;
  13.     }
  14.     @Override
  15.     protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
  16.         //mergeMap需要加上head的行数
  17.         String fieldName = head.getHeadNameList().get(0);
  18.         List<Integer[]> mergeRow = exportEntity.getMergeRowMap().get(fieldName);
  19.         if (CollectionUtils.isEmpty(mergeRow)) return;
  20.         int currentColumnIndex = cell.getColumnIndex();
  21.         int currentRowIndex = cell.getRowIndex();
  22.         //表头所占行数
  23.         int headHeight = head.getHeadNameList().size();
  24.         for (int i = 0; i < mergeRow.size(); i++) {
  25.             if (currentRowIndex == mergeRow.get(i)[1] + headHeight - 1) {
  26.                 // 解决单行数据导出时报错:merge region A2 must contains 2 or more cells
  27.                 if(mergeRow.get(i)[1] - mergeRow.get(i)[0] == 1){
  28.                     continue;
  29.                 }
  30.                 sheet.addMergedRegion(new CellRangeAddress(mergeRow.get(i)[0] + headHeight, mergeRow.get(i)[1] + headHeight - 1,
  31.                         currentColumnIndex, currentColumnIndex));
  32.             }
  33.         }
  34.     }
  35. }
复制代码
表头导出处理处罚
  1. ```java
  2. package com.example.excel.excel;
  3. import com.alibaba.excel.metadata.Head;
  4. import com.alibaba.excel.metadata.data.WriteCellData;
  5. import com.alibaba.excel.write.handler.CellWriteHandler;
  6. import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
  7. import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
  8. import org.apache.poi.ss.usermodel.Cell;
  9. import java.util.List;
  10. import java.util.Map;
  11. import java.util.stream.Collectors;
  12. public class HeadHandler implements CellWriteHandler {
  13.     private ExportEntity exportEntity;
  14.     public HeadHandler(ExportEntity exportEntity) {
  15.         this.exportEntity = exportEntity;
  16.     }
  17.     @Override
  18.     public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
  19.                                  List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
  20.         if (!isHead) return;
  21.         List<String> headNameList = head.getHeadNameList();
  22.         Map<String, String> collect = exportEntity.getExportParams().stream().collect(Collectors.toMap(ExportParam::getFieldName, ExportParam::getColumnName));
  23.         cell.setCellValue(collect.get(headNameList.get(0)));
  24.     }
  25. }
复制代码
导出示例

        被导出实体

多层嵌套,且属性中有聚集的类
  1. public class UserConfigEnntity{
  2.     @MyExcelProperty(name = "学生用户名称")
  3.     private String userName;
  4.     @MyExcelCollection(name = "班级配置")
  5.     private List<ClassConfigEntity> classConfigs;
  6. }
  7. public class ClassConfigEntity{
  8.     @MyExcelProperty(name = "班级号")
  9.     private String classNumber;
  10.     @MyExcelCollection(name = "科目配置")
  11.     private List<SubConfigEntity> subConfigs;
  12. }
  13. public class SubConfigEntity{
  14.     @MyExcelProperty(name = "科目名称")
  15.     private String subName;
  16.     @MyExcelCollection(name = "时间配置")
  17.     private List<SubTimeConfigEntity> subTimeConfigs;
  18. }
  19. public class SubTimeConfigEntity{
  20.     @MyExcelProperty(name = "时间")
  21.     private String subTime;
  22.     @MyExcelCollection(name = "地点配置")
  23.     private List<AddConfigEntity> addConfigs;
  24. }
  25. public class RtuConfigEntity{
  26.     @MyExcelProperty(name = "地点")
  27.     private String addName;
  28. }
复制代码
接口调用

  1. @RestController
  2. @ReqeutMapping("/userConfig/userConfig")
  3. public class CompanyConfigController{
  4.     @AutoWired
  5.     private UserConfigService userConfigService;
  6.    
  7.     @PostMappinng("/export")
  8.     public void expooort(HttpServletResponse response){
  9.         List<UserConfigEnntity> list = userConfigService.queryAll();
  10.         new MyExcelUtil().exportData(list, "学生用户配置内容数据", resposne);
  11.     }
  12. }
复制代码
结果展示


回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表