Skip to content

EasyExcel 根据指定列的 Key 合并单元格

🏷️ EasyExcel

根据 EasyExcel 官网 的文档,EasyExcel 默认只提供了每隔指定行数合并单元格的功能,如果是不固定的行数,就需要实现自定义的合并逻辑了。

下面的策略实现了根据指定列的值,如果这一列的值和前一行一致则合并指定的列。

java
import com.alibaba.excel.write.handler.RowWriteHandler;
import com.alibaba.excel.write.handler.context.RowWriteHandlerContext;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.List;
import java.util.Objects;

/**
 * Key 合并策略
 *
 * @author 佳佳
 */
public class KeyMergeStrategy implements RowWriteHandler {

    /**
     * Key 的列下标(从 0 开始)
     */
    private final int keyColumnIndex;
    /**
     * 需合并的列下标数组(从 0 开始)
     */
    private final List<Integer> mergeColumnIndexList;

    /**
     * 合并 Key
     */
    private String mergeKey = null;
    /**
     * 合并起始行下标
     */
    private int mergeStartRowIndex;

    /**
     * @param keyColumnIndex       Key 的列下标
     * @param mergeColumnIndexList 需合并的列下标数组
     */
    public KeyMergeStrategy(int keyColumnIndex, List<Integer> mergeColumnIndexList) {
        this.keyColumnIndex = keyColumnIndex;
        this.mergeColumnIndexList = mergeColumnIndexList;
    }

    @Override
    public void afterRowDispose(RowWriteHandlerContext context) {
        if (context.getHead() || context.getRelativeRowIndex() == null) {
            return;
        }

        if (context.getRelativeRowIndex() == 0) {
            this.mergeKey = context.getRow().getCell(this.keyColumnIndex).getStringCellValue();
            this.mergeStartRowIndex = context.getRowIndex();
            return;
        }

        String currentKey = context.getRow().getCell(this.keyColumnIndex).getStringCellValue();
        if (!Objects.equals(currentKey, this.mergeKey)) {
            this.mergeKey = currentKey;
            this.mergeStartRowIndex = context.getRowIndex();
            return;
        }

        for (Integer columnIndex : mergeColumnIndexList) {
            CellRangeAddress cellRangeAddress = new CellRangeAddress(
                    mergeStartRowIndex,
                    context.getRowIndex(),
                    columnIndex,
                    columnIndex);
            context.getWriteSheetHolder().getSheet().addMergedRegionUnsafe(cellRangeAddress);
        }
    }
}

Maven 依赖:

xml
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.1.1</version>
</dependency>

调用方法:

java
EasyExcel.write(response.getOutputStream(), OrderDownloadData.class)
        .registerWriteHandler(new KeyMergeStrategy(0, Arrays.asList(0, 2)))
        .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
        .sheet("模板")
        .doWrite(downloadDataList);