使用EasyExcel 导出复杂的合并单元格

引入pom.xml

java 复制代码
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.1.1</version>
</dependency>
java 复制代码
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.merge.AbstractMergeStrategy;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.HashMap;
import java.util.Map;

public class CustomMergeStrategy extends AbstractMergeStrategy {
    private final int[] mergeColumns;  // 需要合并的列索引
    private final int startRow;        // 开始合并的行号
    private Map<Integer, MergeRange> lastValueMap = new HashMap<>();

    public CustomMergeStrategy(int[] mergeColumns, int startRow) {
        this.mergeColumns = mergeColumns;
        this.startRow = startRow;
    }

    @Override
    protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
        int currentRow = cell.getRowIndex();
        if (currentRow <= startRow) return;

        for (int col : mergeColumns) {
            if (cell.getColumnIndex() == col) {
                String currentValue = cell.getStringCellValue();
                MergeRange lastRange = lastValueMap.get(col);

                if (lastRange != null && lastRange.value.equals(currentValue)) {
                    // 合并到上一个范围
                    sheet.addMergedRegion(new CellRangeAddress(
                            lastRange.startRow, currentRow, col, col
                    ));
                    lastValueMap.put(col, new MergeRange(
                            lastRange.startRow, currentValue
                    ));
                } else {
                    // 新值范围开始
                    lastValueMap.put(col, new MergeRange(
                            currentRow, currentValue
                    ));
                }
                break;
            }
        }
    }

    private static class MergeRange {
        int startRow;
        String value;

        MergeRange(int startRow, String value) {
            this.startRow = startRow;
            this.value = value;
        }
    }
}

完成列头合并

复制代码
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;

public class ComplexHeadStrategy implements CellWriteHandler {

    public void afterCellDispose(WriteSheetHolder writeSheetHolder,
                                 WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) {

        if (head.getColumnIndex() == 0 || head.getColumnIndex() == 4) { // 第一列和第五列
            Sheet sheet = writeSheetHolder.getSheet();
            if (cell.getRowIndex() == 0) { // 首行
                // 合并"引导车误差分析"标题
                sheet.addMergedRegion(new CellRangeAddress(
                        0, 0, 0, 1 // 合并前两列
                ));
                sheet.addMergedRegion(new CellRangeAddress(
                        0, 0, 4, 5 // 合并最后两列
                ));
            }
        }
    }
}

Demo实现

复制代码
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import lombok.Data;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;

import java.util.ArrayList;
import java.util.List;

public class MergeCellExportDemo {
    public static void main(String[] args) {
        List<FlightData> dataList = new ArrayList<>();
        dataList.add(new FlightData("0.12", "0.5", "B-1234", "A01", "0.08", "0.3"));
        dataList.add(new FlightData("0.15", "0.6", "B-5678", "B02", "0.09", "0.4"));

        // 自定义合并策略(合并机号列)
        CustomMergeStrategy mergeStrategy = new CustomMergeStrategy(
                new int[]{2, 3}, 1 // 合并第3、4列(机号/机位)
        );


        // 设置表头样式
        WriteCellStyle headStyle = new WriteCellStyle();
        headStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        WriteCellStyle contentStyle = new WriteCellStyle();
        contentStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        HorizontalCellStyleStrategy styleStrategy =
                new HorizontalCellStyleStrategy(headStyle, contentStyle);

        EasyExcel.write("flight_report.xlsx")
                .head(FlightData.class)
                .registerWriteHandler(new ComplexHeadStrategy()) // 复杂表头处理
                .registerWriteHandler(mergeStrategy)
                .registerWriteHandler(styleStrategy)
                .sheet("航班数据")
                .doWrite(dataList);
    }

    // 数据模型类(对应图片中的列)
    @Data
    static class FlightData {
        @ExcelProperty({"引导车开始", "开始_分析误差"})
        private String startAnalysisError;

        @ExcelProperty({"引导车开始", "开始_终端误差(s)"})
        private String startTerminalError;

        @ExcelProperty("机号")
        private String flightNumber;

        @ExcelProperty("机位")
        private String gate;

        @ExcelProperty({"引导车结束", "结束_分析误差"})
        private String endAnalysisError;

        @ExcelProperty({"引导车结束", "结束_终端误差(s)"})
        private String endTerminalError;


        public FlightData(String startAnalysisError, String startTerminalError, String flightNumber,
                          String gate, String endAnalysisError, String endTerminalError) {
            this.startAnalysisError=startAnalysisError;
            this.startTerminalError=startTerminalError;
            this.flightNumber=flightNumber;
            this.gate=gate;
            this.endAnalysisError=endAnalysisError;
            this.endTerminalError=endTerminalError;
        }


    }
}
相关推荐
李慕婉学姐3 小时前
【开题答辩过程】以《基于JAVA的校园即时配送系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·开发语言·数据库
奋进的芋圆5 小时前
Java 延时任务实现方案详解(适用于 Spring Boot 3)
java·spring boot·redis·rabbitmq
sxlishaobin5 小时前
设计模式之桥接模式
java·设计模式·桥接模式
model20055 小时前
alibaba linux3 系统盘网站迁移数据盘
java·服务器·前端
荒诞硬汉5 小时前
JavaBean相关补充
java·开发语言
提笔忘字的帝国5 小时前
【教程】macOS 如何完全卸载 Java 开发环境
java·开发语言·macos
2501_941882486 小时前
从灰度发布到流量切分的互联网工程语法控制与多语言实现实践思路随笔分享
java·开发语言
華勳全栈6 小时前
两天开发完成智能体平台
java·spring·go
alonewolf_996 小时前
Spring MVC重点功能底层源码深度解析
java·spring·mvc
沛沛老爹6 小时前
Java泛型擦除:原理、实践与应对策略
java·开发语言·人工智能·企业开发·发展趋势·技术原理