原文链接:EasyExcel导出多列相同合并处理以及单列相同合并处理_easyexcel怎么实现多个列分别合并-CSDN博客
我对自定义多列相同合并策略处理类进行了一些修改,原文进行多行合并的时候会导致报错(上一行已合并的问题),所以处理了一下重新添加合并单元的逻辑,代码如下:
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
/**
* @ClassName:ExcelMergeCustomerCellHandler @Description:easyexcel合并策略处理类,多列相同合并策略 @Version:1.0 @Date:2023/9/7
* 09:36:52
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ExcelCellByMultiHandler implements CellWriteHandler {
/** 用第几行开始合并 ,默认为1,因为第0行是标题,EasyExcel 的默认也是 */
private int mergeRowIndex = 1;
/** 参与合并的列,起始列位置,默认为0 */
private int mergeColumnStart = 0;
/** 参与合并的列,最后一列的位置,默认为4 */
private int mergeColumnEnd = 4;
/*
* 在对单元格的所有操作完成后调用
*/
@Override
public void afterCellDispose(
WriteSheetHolder writeSheetHolder,
WriteTableHolder writeTableHolder,
List<WriteCellData<?>> list,
Cell cell,
Head head,
Integer integer,
Boolean aBoolean) {
// 当前行
int curRowIndex = cell.getRowIndex();
// 当前列
int curColIndex = cell.getColumnIndex();
if (curRowIndex > mergeRowIndex && curColIndex >= mergeColumnStart) {
// 读取到mergeColumnEnd ,开始调用合并方法
if (curColIndex == mergeColumnEnd) {
mergeWithPrevRow(writeSheetHolder, cell, curRowIndex);
}
}
}
/**
* @Description: 合并比较多列值是否相同 @Date: 2023/9/8 16:31 @Param writeSheetHolder: 通过此对象获取sheet等信息 @Param
* cell: 当前单元格 @Param curRowIndex: 当前行
*
* @return: void
*/
private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex) {
StringBuilder curString = new StringBuilder();
StringBuilder preString = new StringBuilder();
for (int i = mergeColumnStart; i <= mergeColumnEnd; i++) {
Cell curCell = cell.getSheet().getRow(curRowIndex).getCell(i);
Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(i);
// 根据单元格类型获取单元格的值
Object curData =
curCell.getCellType() == CellType.STRING
? curCell.getStringCellValue()
: curCell.getNumericCellValue();
Object preData =
preCell.getCellType() == CellType.STRING
? preCell.getStringCellValue()
: preCell.getNumericCellValue();
curString.append(curData);
preString.append(preData);
}
// 比较当前行的单元格与上一行是否相同,相同合并当前单元格与上一行
if (curString.toString().equals(preString.toString())) {
Sheet sheet = writeSheetHolder.getSheet();
// 获取合并信息
boolean isMerged = false;
// 下标
for (int j = 0; j <= mergeColumnEnd; j++) {
List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();
for (int i = 0; i < mergeRegions.size(); i++) {
CellRangeAddress cellRangeAddr = mergeRegions.get(i);
// 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元
if (cellRangeAddr.isInRange(curRowIndex - 1, j)) {
sheet.removeMergedRegion(i);
cellRangeAddr.setLastRow(curRowIndex);
sheet.addMergedRegion(cellRangeAddr);
isMerged = true;
break;
}
}
}
if (!isMerged) {
for (int i = 0; i <= mergeColumnEnd; i++) {
CellRangeAddress cellRangeAddress =
new CellRangeAddress(curRowIndex - 1, curRowIndex, i, i);
sheet.addMergedRegion(cellRangeAddress);
}
}
}
}
}
上面的三个参数根据实际导出情况自行调整