|
|
|
@ -1,8 +1,12 @@
|
|
|
|
|
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 lombok.AllArgsConstructor;
|
|
|
|
|
import lombok.Data;
|
|
|
|
@ -15,10 +19,7 @@ import org.dromara.common.core.utils.reflect.ReflectUtils;
|
|
|
|
|
import org.dromara.common.excel.annotation.CellMerge;
|
|
|
|
|
|
|
|
|
|
import java.lang.reflect.Field;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 列值重复合并策略
|
|
|
|
@ -26,7 +27,7 @@ import java.util.Map;
|
|
|
|
|
* @author Lion Li
|
|
|
|
|
*/
|
|
|
|
|
@Slf4j
|
|
|
|
|
public class CellMergeStrategy extends AbstractMergeStrategy {
|
|
|
|
|
public class CellMergeStrategy extends AbstractMergeStrategy implements WorkbookWriteHandler {
|
|
|
|
|
|
|
|
|
|
private final List<CellRangeAddress> cellList;
|
|
|
|
|
private final boolean hasTitle;
|
|
|
|
@ -41,17 +42,28 @@ public class CellMergeStrategy extends AbstractMergeStrategy {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
|
|
|
|
|
// judge the list is not null
|
|
|
|
|
if (CollUtil.isNotEmpty(cellList)) {
|
|
|
|
|
// the judge is necessary
|
|
|
|
|
if (cell.getRowIndex() == rowIndex && cell.getColumnIndex() == 0) {
|
|
|
|
|
for (CellRangeAddress item : cellList) {
|
|
|
|
|
sheet.addMergedRegion(item);
|
|
|
|
|
//单元格写入了,遍历合并区域,如果该Cell在区域内,但非首行,则清空
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void afterWorkbookDispose(final WorkbookWriteHandlerContext context) {
|
|
|
|
|
//当前表格写完后,统一写入
|
|
|
|
|
if (CollUtil.isNotEmpty(cellList)){
|
|
|
|
|
for (CellRangeAddress item : cellList) {
|
|
|
|
|
context.getWriteContext().writeSheetHolder().getSheet().addMergedRegion(item);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@SneakyThrows
|
|
|
|
|
private List<CellRangeAddress> handle(List<?> list, boolean hasTitle) {
|
|
|
|
|
List<CellRangeAddress> cellList = new ArrayList<>();
|
|
|
|
@ -93,35 +105,15 @@ public class CellMergeStrategy extends AbstractMergeStrategy {
|
|
|
|
|
// 空值跳过不合并
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!cellValue.equals(val)) {
|
|
|
|
|
if (i - repeatCell.getCurrent() > 1) {
|
|
|
|
|
if ((i - repeatCell.getCurrent() > 1) && isMerge(list, i, field)) {
|
|
|
|
|
cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex - 1, colNum, colNum));
|
|
|
|
|
}
|
|
|
|
|
map.put(field, new RepeatCell(val, i));
|
|
|
|
|
} else if (j == 0) {
|
|
|
|
|
if (i == list.size() - 1) {
|
|
|
|
|
if (i > repeatCell.getCurrent()) {
|
|
|
|
|
cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex, colNum, colNum));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 判断前面的是否合并了
|
|
|
|
|
RepeatCell firstCell = map.get(mergeFields.get(0));
|
|
|
|
|
if (repeatCell.getCurrent() != firstCell.getCurrent()) {
|
|
|
|
|
if (i == list.size() - 1) {
|
|
|
|
|
if (i > repeatCell.getCurrent()) {
|
|
|
|
|
cellList.add(new CellRangeAddress(repeatCell.getCurrent() + rowIndex, i + rowIndex, colNum, colNum));
|
|
|
|
|
}
|
|
|
|
|
} else if (repeatCell.getCurrent() < firstCell.getCurrent()) {
|
|
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
} 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));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -130,6 +122,24 @@ public class CellMergeStrategy extends AbstractMergeStrategy {
|
|
|
|
|
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)和list(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 {
|
|
|
|
|