Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: 指定某一列,当相邻单元格内容一致时合并处理 #256

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package cn.idev.excel.write.merge;

import cn.idev.excel.write.handler.RowWriteHandler;
import cn.idev.excel.write.handler.context.RowWriteHandlerContext;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.ArrayDeque;
import java.util.Deque;

/**
* @Description 指定列数据相同时进行单元格合并
* @Author Zhuojianlong
* @Date 2025/3/8
*/
public class DynamicMergeStrategy implements RowWriteHandler {
private final int columnIndex;
private final int columnExtend;
private final int dataSize;
private final Deque<MergeRow> rowStack = new ArrayDeque<>();

public DynamicMergeStrategy(int columnIndex,int dataSize) {
this(columnIndex,1,dataSize);
}
public DynamicMergeStrategy(int columnIndex, int columnExtend,int dataSize) {
if (columnExtend < 1) {
throw new IllegalArgumentException("ColumnExtend must be greater than 1");
}
if (columnIndex < 0) {
throw new IllegalArgumentException("ColumnIndex must be greater than 0");
}
this.columnIndex = columnIndex;
this.columnExtend = columnExtend;
this.dataSize = dataSize;

}
@Override
public void afterRowDispose(RowWriteHandlerContext context) {
if (context.getHead() || context.getRelativeRowIndex() == null) {
return;
}
Row row = context.getRow();
rowStack.push(new MergeRow(row, context.getRelativeRowIndex()));
if(context.getRelativeRowIndex()==(dataSize-1)){
while (!rowStack.isEmpty()){
MergeRow lastRow = rowStack.pop();
while (!rowStack.isEmpty()){
MergeRow prevRow = rowStack.pop();
if(prevRow.getRelativeRowIndex().equals(0)){
CellRangeAddress cellRangeAddress = new CellRangeAddress(prevRow.getRow().getRowNum(),
lastRow.getRow().getRowNum(), columnIndex, columnIndex + columnExtend - 1);
context.getWriteSheetHolder().getSheet().addMergedRegionUnsafe(cellRangeAddress);
}else {
if (!prevRow.getRow().getCell(columnIndex).getStringCellValue().equals(lastRow.getRow().getCell(columnIndex).getStringCellValue())) {
if(lastRow.getRow().getRowNum()!=(prevRow.getRow().getRowNum()+1)){
CellRangeAddress cellRangeAddress = new CellRangeAddress(prevRow.getRow().getRowNum()+1,
lastRow.getRow().getRowNum(), columnIndex, columnIndex + columnExtend - 1);
context.getWriteSheetHolder().getSheet().addMergedRegionUnsafe(cellRangeAddress);
}
rowStack.push(prevRow);
break;
}
}

}

}
}

}

@Data
@AllArgsConstructor
public static class MergeRow{
private Row row;
private Integer relativeRowIndex;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;

import cn.idev.excel.EasyExcel;
import cn.idev.excel.ExcelWriter;
Expand All @@ -18,6 +14,7 @@
import cn.idev.excel.util.ListUtils;
import cn.idev.excel.write.handler.CellWriteHandler;
import cn.idev.excel.write.handler.context.CellWriteHandlerContext;
import cn.idev.excel.write.merge.DynamicMergeStrategy;
import cn.idev.excel.write.merge.LoopMergeStrategy;
import cn.idev.excel.write.style.HorizontalCellStyleStrategy;
import cn.idev.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
Expand Down Expand Up @@ -613,6 +610,60 @@ public void dynamicHeadWrite() {
.doWrite(data());
}

/**
* 动态头,实时生成头写入
* 指定列值相同时合并
*/
@Test
public void customHeadReadAndDynamicMergeStrategy() {
String fileName = TestFileUtil.getPath() + "customHeadRead" + System.currentTimeMillis() + ".xlsx";
List<Map<Integer, String>> maps = yearData();
EasyExcel.write(fileName)
.head(yearHead())
.sheet("模板")
.registerWriteHandler(new DynamicMergeStrategy(0,maps.size()))
.registerWriteHandler(new DynamicMergeStrategy(2,maps.size()))
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.doWrite(maps);
}

public List<List<String>> yearHead() {
List<List<String>> head = new ArrayList<>();
for (int i = 0; i < 12; i++) {
List<String> h = new ArrayList<>();
if(i<3){
h.add("第一季度");
}
if(i>=3&&i<6){
h.add("第二季度");
}
if(i>=6&&i<9){
h.add("第三季度");
}
if(i>=9){
h.add("第四季度");
}
h.add("第" + (i + 1) + "月");
head.add(h);
}
return head;
}
public List<Map<Integer, String>> yearData() {
List<Map<Integer, String>> data = new ArrayList<>();
for (int i = 0; i < 100; i++) {
Map<Integer, String> map = new HashMap<>();
for (int j = 0; j < 12; j++) {
if(i<20){
map.put( j , "第" + (j + 1) + "月"+"前20条数据");
}else {
map.put( j , "第" + (j + 1) + "月");
}

}
data.add(map);
}
return data;
}
/**
* 自动列宽(不太精确)
* <p>
Expand Down