Pre Merge pull request !738 from chengliejian/excel合并策略优化

This commit is contained in:
chengliejian 2025-08-07 08:13:19 +00:00 committed by Gitee
commit 5a3f21c219
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F

View File

@ -3,6 +3,8 @@ package org.dromara.common.excel.core;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.idev.excel.annotation.ExcelIgnore;
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
import cn.idev.excel.annotation.ExcelProperty; import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.metadata.Head; import cn.idev.excel.metadata.Head;
import cn.idev.excel.write.handler.WorkbookWriteHandler; import cn.idev.excel.write.handler.WorkbookWriteHandler;
@ -70,30 +72,46 @@ public class CellMergeStrategy extends AbstractMergeStrategy implements Workbook
if (CollUtil.isEmpty(list)) { if (CollUtil.isEmpty(list)) {
return cellList; return cellList;
} }
Field[] fields = ReflectUtils.getFields(list.get(0).getClass(), field -> !"serialVersionUID".equals(field.getName())); Class<?> clazz = list.get(0).getClass();
Field[] fields = ReflectUtils.getFields(clazz, field -> !"serialVersionUID".equals(field.getName()));
boolean ignoreUnannotated = clazz.isAnnotationPresent(ExcelIgnoreUnannotated.class);
// 有注解的字段 // 有注解的字段
List<Field> mergeFields = new ArrayList<>(); List<Field> mergeFields = new ArrayList<>();
List<Integer> mergeFieldsIndex = new ArrayList<>(); List<Integer> mergeFieldsIndex = new ArrayList<>();
for (int i = 0; i < fields.length; i++) { // 实际 Excel 列索引忽略被 @ExcelIgnore 的字段
Field field = fields[i]; int excelColIndex = 0;
for (Field field : fields) {
if (field.isAnnotationPresent(ExcelIgnore.class)) {
// 忽略不导出的字段
continue;
}
if (ignoreUnannotated && !field.isAnnotationPresent(ExcelProperty.class)) {
// 忽略未注解字段根据 @ExcelIgnoreUnannotated
continue;
}
if (field.isAnnotationPresent(CellMerge.class)) { if (field.isAnnotationPresent(CellMerge.class)) {
CellMerge cm = field.getAnnotation(CellMerge.class); CellMerge cm = field.getAnnotation(CellMerge.class);
mergeFields.add(field); mergeFields.add(field);
mergeFieldsIndex.add(cm.index() == -1 ? i : cm.index()); // CellMerge.index() 被设置了使用它否则用当前实际 Excel 列索引
mergeFieldsIndex.add(cm.index() == -1 ? excelColIndex : cm.index());
if (hasTitle) { if (hasTitle) {
ExcelProperty property = field.getAnnotation(ExcelProperty.class); ExcelProperty property = field.getAnnotation(ExcelProperty.class);
rowIndex = Math.max(rowIndex, property.value().length); rowIndex = Math.max(rowIndex, property.value().length);
} }
} }
// 每处理一个未忽略的字段实际 Excel 列索引 +1
excelColIndex++;
} }
Map<Field, RepeatCell> map = new HashMap<>(); Map<Field, RepeatCell> map = new HashMap<>();
// 生成两两合并单元格 // 生成两两合并单元格
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
Object rowObj = list.get(i);
for (int j = 0; j < mergeFields.size(); j++) { for (int j = 0; j < mergeFields.size(); j++) {
Field field = mergeFields.get(j); Field field = mergeFields.get(j);
Object val = ReflectUtils.invokeGetter(list.get(i), field.getName()); Object val = ReflectUtils.invokeGetter(rowObj, field.getName());
int colNum = mergeFieldsIndex.get(j); int colNum = mergeFieldsIndex.get(j);
if (!map.containsKey(field)) { if (!map.containsKey(field)) {