You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java使用Apache POI读取10000个Excel文件并合并为一个主文件

Java批量读取Excel并生成汇总报表方案

我之前处理过类似的批量Excel汇总需求,针对你要处理10000个文件的场景,非常推荐用EasyExcel来实现——它比传统的Apache POI更节省内存,能有效避免大文件场景下的内存溢出问题,适配海量文件的批量处理。下面是完整的落地方案:

一、先准备依赖

如果你用Maven,直接在pom.xml里添加EasyExcel的核心依赖:

<!-- EasyExcel 核心依赖(版本可以选最新稳定版) -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.3.2</version>
</dependency>

二、定义数据实体类

假设所有源Excel的结构是一致的(比如包含姓名、部门、业绩这几个字段),先写一个实体类和Excel列做映射:

import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;

// 用Lombok的@Data简化getter/setter,也可以自己手写
@Data
public class ExcelData {
    @ExcelProperty("姓名") // 对应Excel表头的"姓名"列
    private String name;
    
    @ExcelProperty("部门")
    private String department;
    
    @ExcelProperty("业绩")
    private Double performance;
}

三、编写逐行处理的监听器

EasyExcel采用监听器模式逐行读取数据,不会把整个Excel加载到内存里,这对处理10000个文件至关重要。我们可以在监听器里每积累一批数据就写入汇总表,避免内存积压:

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.ExcelWriter;
import java.util.ArrayList;
import java.util.List;

public class ExcelDataListener extends AnalysisEventListener<ExcelData> {
    // 每攒1000行就写入一次汇总表,这个数值可以根据内存情况调整
    private static final int BATCH_COUNT = 1000;
    private List<ExcelData> dataList = new ArrayList<>(BATCH_COUNT);
    private final ExcelWriter excelWriter;

    // 构造方法传入汇总表的写入器
    public ExcelDataListener(ExcelWriter excelWriter) {
        this.excelWriter = excelWriter;
    }

    // 每读取一行数据就触发这个方法
    @Override
    public void invoke(ExcelData data, AnalysisContext context) {
        dataList.add(data);
        if (dataList.size() >= BATCH_COUNT) {
            writeBatchData();
            dataList.clear(); // 清空列表,释放内存
        }
    }

    // 整个文件读取完成后触发,处理最后一批剩余数据
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        writeBatchData();
    }

    // 批量写入汇总表的方法
    private void writeBatchData() {
        excelWriter.write(dataList, EasyExcel.writerSheet("汇总数据").build());
    }
}

四、主逻辑:遍历源文件夹并生成汇总表

最后写主方法,遍历源文件夹下的所有Excel文件,逐个读取并写入到目标汇总表中:

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class ExcelMerger {
    public static void main(String[] args) {
        // 替换成你的源文件夹路径和目标文件路径
        String sourceDirPath = "/your/source/folder/path";
        String targetFilePath = "/your/target/folder/path/汇总报表.xlsx";

        // 用try-with-resources自动关闭写入器,避免资源泄漏
        try (ExcelWriter excelWriter = EasyExcel.write(new FileOutputStream(targetFilePath), ExcelData.class).build()) {
            File sourceDir = new File(sourceDirPath);
            if (!sourceDir.isDirectory()) {
                System.err.println("错误:源路径不是有效的文件夹!");
                return;
            }

            // 过滤出文件夹下的所有.xlsx/.xls文件
            File[] excelFiles = sourceDir.listFiles((dir, name) -> {
                String lowerName = name.toLowerCase();
                return lowerName.endsWith(".xlsx") || lowerName.endsWith(".xls");
            });

            if (excelFiles == null || excelFiles.length == 0) {
                System.err.println("提示:源文件夹中没有找到Excel文件!");
                return;
            }

            // 遍历所有Excel文件进行处理
            for (File excelFile : excelFiles) {
                System.out.println("正在处理文件:" + excelFile.getName());
                // 读取当前文件,用自定义监听器逐行写入汇总表
                EasyExcel.read(excelFile, ExcelData.class, new ExcelDataListener(excelWriter)).sheet().doRead();
            }

            System.out.println("汇总报表生成完成!文件路径:" + targetFilePath);
        } catch (IOException e) {
            e.printStackTrace();
            System.err.println("生成汇总表时出现异常:" + e.getMessage());
        }
    }
}

五、关键注意事项

  • 内存安全:监听器的批量写入机制能保证即使处理10000个文件,内存也不会爆掉,这是处理海量文件的核心。
  • 异常容错:可以在遍历文件时单独加try-catch,避免单个文件读取失败导致整个流程中断。
  • 性能优化:如果想更快处理,可以用线程池并行读取文件,但要注意:EasyExcel的ExcelWriter不是线程安全的,所以每个线程需要单独处理文件,最后再合并结果(或者用同步块控制写入)。
  • 表头兼容:如果源文件的表头和实体类的@ExcelProperty不匹配,可以用索引(比如@ExcelProperty(index = 0))来对应列,适配不同的表头名称。

内容的提问来源于stack exchange,提问作者user1302909

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:32:43