From 098d3347a0df808908aab8c554cd7c4febc5e6d9 Mon Sep 17 00:00:00 2001 From: 疯狂的狮子Li <15040126243@163.com> Date: 星期一, 26 八月 2024 11:43:59 +0800 Subject: [PATCH] !577 发布 5.2.2 正式版 安全性提升 Merge pull request !577 from 疯狂的狮子Li/dev --- ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/CellMergeStrategy.java | 213 ++++++++++++++++++++++++++++++++--------------------- 1 files changed, 128 insertions(+), 85 deletions(-) diff --git a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/CellMergeStrategy.java b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/CellMergeStrategy.java index a409372..7c7721c 100644 --- a/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/CellMergeStrategy.java +++ b/ruoyi-common/ruoyi-common-excel/src/main/java/org/dromara/common/excel/core/CellMergeStrategy.java @@ -1,114 +1,157 @@ package org.dromara.common.excel.core; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ReflectUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.write.handler.WorkbookWriteHandler; +import com.alibaba.excel.write.handler.context.WorkbookWriteHandlerContext; import com.alibaba.excel.write.merge.AbstractMergeStrategy; -import org.dromara.common.excel.annotation.CellMerge; import lombok.AllArgsConstructor; import lombok.Data; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.CollectionUtils; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.util.CellRangeAddress; +import org.dromara.common.core.utils.reflect.ReflectUtils; +import org.dromara.common.excel.annotation.CellMerge; import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * 鍒楀�奸噸澶嶅悎骞剁瓥鐣� * * @author Lion Li */ -@AllArgsConstructor @Slf4j -public class CellMergeStrategy extends AbstractMergeStrategy { +public class CellMergeStrategy extends AbstractMergeStrategy implements WorkbookWriteHandler { - private List<?> list; - private boolean hasTitle; + private final List<CellRangeAddress> cellList; + private final boolean hasTitle; + private int rowIndex; - @Override - protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) { - List<CellRangeAddress> cellList = handle(list, hasTitle); - // judge the list is not null - if (CollectionUtils.isNotEmpty(cellList)) { - // the judge is necessary - if (cell.getRowIndex() == 1 && cell.getColumnIndex() == 0) { - for (CellRangeAddress item : cellList) { - sheet.addMergedRegion(item); - } - } - } - } + public CellMergeStrategy(List<?> list, boolean hasTitle) { + this.hasTitle = hasTitle; + // 琛屽悎骞跺紑濮嬩笅鏍� + this.rowIndex = hasTitle ? 1 : 0; + this.cellList = handle(list, hasTitle); + } - @SneakyThrows - private static List<CellRangeAddress> handle(List<?> list, boolean hasTitle) { - List<CellRangeAddress> cellList = new ArrayList<>(); - if (CollectionUtils.isEmpty(list)) { - return cellList; - } - Class<?> clazz = list.get(0).getClass(); - Field[] fields = clazz.getDeclaredFields(); - // 鏈夋敞瑙g殑瀛楁 - List<Field> mergeFields = new ArrayList<>(); - List<Integer> mergeFieldsIndex = new ArrayList<>(); - for (int i = 0; i < fields.length; i++) { - Field field = fields[i]; - if (field.isAnnotationPresent(CellMerge.class)) { - CellMerge cm = field.getAnnotation(CellMerge.class); - mergeFields.add(field); - mergeFieldsIndex.add(cm.index() == -1 ? i : cm.index()); - } - } - // 琛屽悎骞跺紑濮嬩笅鏍� - int rowIndex = hasTitle ? 1 : 0; - Map<Field, RepeatCell> map = new HashMap<>(); - // 鐢熸垚涓や袱鍚堝苟鍗曞厓鏍� - for (int i = 0; i < list.size(); i++) { - for (int j = 0; j < mergeFields.size(); j++) { - Field field = mergeFields.get(j); - String name = field.getName(); - String methodName = "get" + name.substring(0, 1).toUpperCase() + name.substring(1); - Method readMethod = clazz.getMethod(methodName); - Object val = readMethod.invoke(list.get(i)); + @Override + protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) { + //鍗曞厓鏍煎啓鍏ヤ簡,閬嶅巻鍚堝苟鍖哄煙,濡傛灉璇ell鍦ㄥ尯鍩熷唴,浣嗛潪棣栬,鍒欐竻绌� + final int rowIndex = cell.getRowIndex(); + if (CollUtil.isNotEmpty(cellList)){ + for (CellRangeAddress cellAddresses : cellList) { + final int firstRow = cellAddresses.getFirstRow(); + if (cellAddresses.isInRange(cell) && rowIndex != firstRow){ + cell.setBlank(); + } + } + } + } - int colNum = mergeFieldsIndex.get(j); - if (!map.containsKey(field)) { - map.put(field, new RepeatCell(val, i)); - } else { - RepeatCell repeatCell = map.get(field); - Object cellValue = repeatCell.getValue(); - if (cellValue == null || "".equals(cellValue)) { - // 绌哄�艰烦杩囦笉鍚堝苟 - continue; - } - if (!cellValue.equals(val)) { - if (i - repeatCell.getCurrent() > 1) { - cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex - 1, colNum, colNum)); - } - map.put(field, new RepeatCell(val, i)); - } else if (i == list.size() - 1) { - if (i > repeatCell.getCurrent()) { - cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex, colNum, colNum)); - } - } - } - } - } - return cellList; - } + @Override + public void afterWorkbookDispose(final WorkbookWriteHandlerContext context) { + //褰撳墠琛ㄦ牸鍐欏畬鍚庯紝缁熶竴鍐欏叆 + if (CollUtil.isNotEmpty(cellList)){ + for (CellRangeAddress item : cellList) { + context.getWriteContext().writeSheetHolder().getSheet().addMergedRegion(item); + } + } + } - @Data - @AllArgsConstructor - static class RepeatCell { + @SneakyThrows + private List<CellRangeAddress> handle(List<?> list, boolean hasTitle) { + List<CellRangeAddress> cellList = new ArrayList<>(); + if (CollUtil.isEmpty(list)) { + return cellList; + } + Field[] fields = ReflectUtils.getFields(list.get(0).getClass(), field -> !"serialVersionUID".equals(field.getName())); - private Object value; + // 鏈夋敞瑙g殑瀛楁 + List<Field> mergeFields = new ArrayList<>(); + List<Integer> mergeFieldsIndex = new ArrayList<>(); + for (int i = 0; i < fields.length; i++) { + Field field = fields[i]; + if (field.isAnnotationPresent(CellMerge.class)) { + CellMerge cm = field.getAnnotation(CellMerge.class); + mergeFields.add(field); + mergeFieldsIndex.add(cm.index() == -1 ? i : cm.index()); + if (hasTitle) { + ExcelProperty property = field.getAnnotation(ExcelProperty.class); + rowIndex = Math.max(rowIndex, property.value().length); + } + } + } - private int current; + Map<Field, RepeatCell> map = new HashMap<>(); + // 鐢熸垚涓や袱鍚堝苟鍗曞厓鏍� + for (int i = 0; i < list.size(); i++) { + for (int j = 0; j < mergeFields.size(); j++) { + Field field = mergeFields.get(j); + Object val = ReflectUtils.invokeGetter(list.get(i), field.getName()); - } + int colNum = mergeFieldsIndex.get(j); + if (!map.containsKey(field)) { + map.put(field, new RepeatCell(val, i)); + } else { + RepeatCell repeatCell = map.get(field); + Object cellValue = repeatCell.getValue(); + if (cellValue == null || "".equals(cellValue)) { + // 绌哄�艰烦杩囦笉鍚堝苟 + continue; + } + + if (!cellValue.equals(val)) { + if ((i - repeatCell.getCurrent() > 1)) { + cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex - 1, colNum, colNum)); + } + map.put(field, new RepeatCell(val, i)); + } else if (i == list.size() - 1) { + if (i > repeatCell.getCurrent() && isMerge(list, i, field)) { + cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex, colNum, colNum)); + } + } else if (!isMerge(list, i, field)) { + if ((i - repeatCell.getCurrent() > 1)) { + cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex - 1, colNum, colNum)); + } + map.put(field, new RepeatCell(val, i)); + } + } + } + } + return cellList; + } + + private boolean isMerge(List<?> list, int i, Field field) { + boolean isMerge = true; + CellMerge cm = field.getAnnotation(CellMerge.class); + final String[] mergeBy = cm.mergeBy(); + if (StrUtil.isAllNotBlank(mergeBy)) { + //姣斿褰撳墠list(i)鍜宭ist(i - 1)鐨勫悇涓睘鎬у�间竴涓�姣斿 濡傛灉鍏ㄤ负鐪� 鍒欎负鐪� + for (String fieldName : mergeBy) { + final Object valCurrent = ReflectUtil.getFieldValue(list.get(i), fieldName); + final Object valPre = ReflectUtil.getFieldValue(list.get(i - 1), fieldName); + if (!Objects.equals(valPre, valCurrent)) { + //渚濊禆瀛楁濡傛湁浠讳竴涓嶇瓑鍊�,鍒欐爣璁颁负涓嶅彲鍚堝苟 + isMerge = false; + } + } + } + return isMerge; + } + + @Data + @AllArgsConstructor + static class RepeatCell { + + private Object value; + + private int current; + + } } -- Gitblit v1.9.3