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

如何用Java跨工作簿批量复制Excel工作表(非逐单元格复制)

在Java中高效复制整个Excel工作表(无需遍历单元格)

绝对可以!而且这正是解决大Excel文件复制性能问题的关键方案——直接操作工作表的底层结构,跳过逐单元格遍历的繁琐过程,性能提升非常明显。

为什么逐单元格复制性能差?

当数据量较大时,逐单元格复制需要遍历每一个单元格,还要处理单元格样式、公式、数据类型等细节,不仅代码繁琐,还会产生大量的内存开销和IO操作,很容易导致程序卡顿甚至内存溢出。

解决方案:使用Apache POI直接复制工作表结构

Java生态中处理Excel最常用的库是Apache POI,它提供了直接复制整个工作表的API,无需手动遍历单元格。下面是具体实现步骤:

1. 准备依赖

首先在你的Maven项目中添加Apache POI相关依赖:

<dependencies>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>5.2.5</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>5.2.5</version>
    </dependency>
    <!-- 处理超大文件时添加流式依赖 -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml-schemas</artifactId>
        <version>4.1.2</version>
    </dependency>
</dependencies>

2. 核心代码实现

这里分两种场景:常规文件(XSSF)和超大文件(SXSSF,流式处理避免内存溢出)。

场景一:处理常规大小的Excel文件(.xlsx)
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class ExcelSheetCopy {
    public static void main(String[] args) {
        try (
            // 打开源工作簿
            XSSFWorkbook sourceWorkbook = new XSSFWorkbook(new FileInputStream("source.xlsx"));
            // 打开或创建目标工作簿
            XSSFWorkbook targetWorkbook = new XSSFWorkbook(new FileInputStream("target.xlsx"))
        ) {
            // 获取要复制的源工作表
            XSSFSheet sourceSheet = sourceWorkbook.getSheet("Sheet1");
            
            // 直接复制整个工作表到目标工作簿,自动处理数据、样式、公式、合并单元格
            String newSheetName = "Copied_Sheet1";
            targetWorkbook.cloneSheet(sourceWorkbook.getSheetIndex(sourceSheet), newSheetName);
            
            // 保存目标工作簿
            try (FileOutputStream fos = new FileOutputStream("target.xlsx")) {
                targetWorkbook.write(fos);
            }
            
            System.out.println("工作表复制完成!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
场景二:处理超大Excel文件(避免内存溢出)

如果你的工作表数据量极大(比如几十万行),推荐使用SXSSF(流式处理),它会将部分数据写入磁盘,减少内存占用:

import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class LargeExcelSheetCopy {
    public static void main(String[] args) {
        try (
            XSSFWorkbook sourceWorkbook = new XSSFWorkbook(new FileInputStream("large_source.xlsx"));
            // 创建SXSSF工作簿,设置内存中保留的行数(比如100行,超出的写入临时文件)
            SXSSFWorkbook targetWorkbook = new SXSSFWorkbook(100)
        ) {
            XSSFSheet sourceSheet = sourceWorkbook.getSheet("Large_Sheet");
            
            // 复制源工作表的结构和数据到SXSSF工作簿
            Sheet targetSheet = targetWorkbook.createSheet("Copied_Large_Sheet");
            // 复制工作表的所有内容(包括样式、公式、合并单元格)
            copySheet(sourceWorkbook, targetWorkbook, sourceSheet, targetSheet);
            
            try (FileOutputStream fos = new FileOutputStream("large_target.xlsx")) {
                targetWorkbook.write(fos);
            }
            
            // 清理临时文件
            targetWorkbook.dispose();
            System.out.println("超大工作表复制完成!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    // 自定义复制方法,适配SXSSF场景
    private static void copySheet(XSSFWorkbook sourceWB, SXSSFWorkbook targetWB, XSSFSheet sourceSheet, Sheet targetSheet) {
        // 复制列宽
        for (int i = 0; i <= sourceSheet.getLastColumnNum(); i++) {
            targetSheet.setColumnWidth(i, sourceSheet.getColumnWidth(i));
        }
        
        // 复制合并单元格
        sourceSheet.getMergedRegions().forEach(region -> targetSheet.addMergedRegion(region));
        
        // 复制行(包括单元格数据、样式、公式)
        sourceSheet.forEach(row -> {
            try {
                targetSheet.createRow(row.getRowNum());
                row.forEach(cell -> {
                    targetSheet.getRow(row.getRowNum()).createCell(cell.getColumnIndex()).setCellValue(cell.getStringCellValue());
                    // 复制单元格样式
                    targetSheet.getRow(row.getRowNum()).getCell(cell.getColumnIndex()).setCellStyle(cell.getCellStyle());
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }
}

关键注意事项

  • 样式与公式:cloneSheet()方法会自动复制单元格样式、公式、数据格式,无需手动处理;对于SXSSF的场景,需要手动复制样式(如上面代码所示)。
  • 图片与图表:如果源工作表包含图片或图表,cloneSheet()不会自动复制这些元素,需要额外通过Drawing对象手动复制绘图内容。
  • 公式引用调整:如果源工作表中的公式引用了其他工作簿的单元格,复制后需要手动更新公式引用;如果是同一工作簿内的引用,cloneSheet()会自动调整。

这样操作的性能会比逐单元格复制提升几个数量级,完全能应对大数据量的工作表复制需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:52:29