EasyExcel合并单元格实战技巧分享

2025-04发布7次浏览

在实际开发中,Excel文件的处理是常见的需求之一。EasyExcel作为阿里巴巴开源的一个轻量级Excel读写工具,因其高效、易用而备受开发者青睐。本文将分享如何使用EasyExcel实现单元格合并这一常见需求,并深入解析其实现原理及注意事项。


一、EasyExcel简介

EasyExcel是基于Apache POI封装的一个高效Excel处理库,专注于简化Excel的读写操作。相比传统的POI库,它提供了更简洁的API和更高的性能,尤其适合大数据量场景下的Excel处理。

核心特性:

  1. 简单易用:通过注解即可完成复杂的数据映射。
  2. 高性能:支持分页读取,避免内存溢出问题。
  3. 扩展性强:允许开发者自定义样式和逻辑。

二、合并单元格的基本原理

在Excel中,单元格合并是指将多个单元格视为一个整体进行显示。从技术角度看,合并单元格实际上是设置了一个区域范围(CellRangeAddress),并指定该区域内的所有单元格共享同一个内容。

合并单元格的关键点:

  1. 确定合并区域:需要明确起始行号、结束行号、起始列号和结束列号。
  2. 设置样式:为合并后的单元格设置统一的样式,如字体、边框等。
  3. 数据一致性:确保合并单元格中的内容与数据模型一致。

三、实战技巧:使用EasyExcel合并单元格

以下是一个完整的代码示例,展示如何在EasyExcel中实现单元格合并。

1. 引入依赖

首先,在项目中引入EasyExcel的Maven依赖:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.0.5</version>
</dependency>

2. 定义数据模型

创建一个简单的数据模型类,用于表示Excel中的每一行数据。

public class DemoData {
    @ExcelProperty("姓名")
    private String name;

    @ExcelProperty("年龄")
    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

3. 自定义监听器

为了实现单元格合并,我们需要重写EasyExcel的监听器,在写入数据时动态调整单元格的合并逻辑。

public class MergeWriteListener extends AnalysisEventListener<DemoData> {
    private List<DemoData> cachedDataList = new ArrayList<>();

    @Override
    public void invoke(DemoData data, AnalysisContext context) {
        cachedDataList.add(data);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // 在这里可以对缓存的数据进行额外处理
    }

    public List<DemoData> getCachedDataList() {
        return cachedDataList;
    }
}

4. 实现单元格合并逻辑

在写入Excel时,通过Sheet对象的mergeStrategy方法指定合并策略。

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.handler.WriteHandler;
import org.apache.poi.ss.usermodel.*;

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

public class EasyExcelMergeExample {

    public static void main(String[] args) {
        String fileName = "merged_example.xlsx";
        List<DemoData> data = getData();

        EasyExcel.write(fileName, DemoData.class)
                .registerWriteHandler(new MergeWriteHandler())
                .sheet("Sheet1")
                .doWrite(data);
    }

    private static List<DemoData> getData() {
        List<DemoData> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            DemoData data = new DemoData();
            data.setName(i % 2 == 0 ? "张三" : "李四");
            data.setAge(20 + i);
            list.add(data);
        }
        return list;
    }
}

class MergeWriteHandler implements WriteHandler {

    @Override
    public void sheet(int sheetNo, Sheet sheet) {
        // 可以在这里设置工作表级别的属性
    }

    @Override
    public void row(int rowNum, Row row) {
        if (rowNum == 0) return; // 忽略表头

        Workbook workbook = row.getSheet().getWorkbook();
        Sheet sheet = row.getSheet();

        // 示例:合并第1列(A列)中相同值的单元格
        int lastRow = rowNum - 1;
        Cell currentCell = row.getCell(0);
        String currentValue = currentCell.getStringCellValue();

        if (lastRow > 0) {
            Row previousRow = sheet.getRow(lastRow);
            Cell previousCell = previousRow.getCell(0);
            String previousValue = previousCell.getStringCellValue();

            if (currentValue.equals(previousValue)) {
                // 找到连续相同的值,进行合并
                CellRangeAddress cra = new CellRangeAddress(lastRow, rowNum, 0, 0);
                sheet.addMergedRegion(cra);
            }
        }
    }
}

四、代码解析

  1. 数据模型:通过@ExcelProperty注解将Java对象的字段映射到Excel列。
  2. 监听器MergeWriteListener负责缓存数据,便于后续处理。
  3. 合并逻辑:在MergeWriteHandler中实现具体的合并规则,例如按列值判断是否需要合并。
  4. 动态调整:通过CellRangeAddress定义合并区域,并将其添加到工作表中。

五、注意事项

  1. 性能优化:对于大数据量场景,建议分批写入数据,避免一次性加载过多数据导致内存溢出。
  2. 样式兼容性:合并单元格后,样式可能会受到影响,需手动调整。
  3. 边界条件:处理首行、尾行等特殊位置时,需特别注意逻辑正确性。

六、总结

通过上述示例,我们展示了如何使用EasyExcel实现单元格合并。这一功能不仅提升了Excel文件的可读性,还满足了实际业务中的多样化需求。结合EasyExcel的高效性和灵活性,开发者可以轻松应对复杂的Excel处理任务。