使用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;
        }


    }
}
相关推荐
骑着蜗牛撵大象3272 分钟前
飞牛fnOS部署Damselfly:Compose编排、照片目录与7100固定访问
java·docker·rpc·dubbo·fnos·照片管理·damselfly
金銀銅鐵44 分钟前
[Java] 用 CLI 展示 EnumSet 增减元素时的内部变化(下)
java·后端·ai编程
Nuanyt1 小时前
Hot 100 刷题笔记 · 数组与哈希专题(3 题)
java·笔记·算法·leetcode·哈希算法·1024程序员节
xieliyu.1 小时前
【JavaEE进阶】Spring Boot 日志:从 System.out 到 @Slf4j,6 个级别 + 4 类配置一篇讲透
java·spring boot·spring·java-ee·springboot·logback·slf4j
IT_Octopus2 小时前
Apollo 配置中心入门:一所“小学校“读懂 Portal、Meta Server、Config Service
java·后端·spring
cfm_29142 小时前
偏向锁的Epoch优化机制
java
CRMEB系统商城2 小时前
家电零售的供应商协同与物流提效
java·开发语言·人工智能·小程序·1024程序员节
jason.zeng@15022072 小时前
Nginx 配置详解(静态 HTML、下载目录、API 反向代理三套场景)
java·vue.js·1024程序员节
鬼手点金2 小时前
从 API 消息到模型 Token:Chat Template
java·前端·javascript·数据库·人工智能·深度学习·1024程序员节
Shadow(⊙o⊙)2 小时前
LangChain 自定义工具全解析:从 @tool 到 bind_tools 的完整调用链路
java·服务器·前端·1024程序员节