Java复制Excel的多种实现方式及最佳实践
在数据处理和报表生成的场景中,Excel文件的复制操作是常见需求,Java作为企业级开发的主流语言,提供了多种技术方案来实现Excel文件的复制,本文将详细介绍基于Apache POI、EasyExcel、JXL等库的复制方法,并分析不同场景下的适用性与注意事项。

基于Apache POI的Excel复制方案
Apache POI是Java操作Office文档最常用的开源库,支持Excel的读取、写入和格式处理,其复制操作的核心思路是:先读取源Excel文件,再将其内容写入新文件或内存流。
基础复制方法(不含格式)
对于仅需复制数据的场景,可通过HSSFWorkbook(.xls)或XSSFWorkbook(.xlsx)实现:
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public void copyExcelBasic(String sourcePath, String targetPath) throws IOException {
try (Workbook sourceWorkbook = new XSSFWorkbook(sourcePath);
Workbook targetWorkbook = new XSSFWorkbook()) {
Sheet sourceSheet = sourceWorkbook.getSheetAt(0);
Sheet targetSheet = targetWorkbook.createSheet();
for (Row row : sourceSheet) {
Row newRow = targetSheet.createRow(row.getRowNum());
for (Cell cell : row) {
Cell newCell = newRow.createCell(cell.getColumnIndex());
newCell.setCellValue(cell.getStringCellValue());
}
}
try (FileOutputStream fos = new FileOutputStream(targetPath)) {
targetWorkbook.write(fos);
}
}
}
此方法仅复制单元格值,不保留字体、颜色等格式。
保留格式的深度复制
若需完整复制样式,需遍历样式对象并应用到新单元格:

public void copyExcelWithStyle(String sourcePath, String targetPath) throws IOException {
try (Workbook sourceWorkbook = new XSSFWorkbook(sourcePath);
Workbook targetWorkbook = new XSSFWorkbook()) {
Sheet sourceSheet = sourceWorkbook.getSheetAt(0);
Sheet targetSheet = targetWorkbook.createSheet();
CellStyle targetStyle = targetWorkbook.createCellStyle();
for (Row row : sourceSheet) {
Row newRow = targetSheet.createRow(row.getRowNum());
for (Cell cell : row) {
Cell newCell = newRow.createCell(cell.getColumnIndex());
newCell.setCellValue(cell.getStringCellValue());
targetStyle.cloneStyleFrom(cell.getCellStyle());
newCell.setCellStyle(targetStyle);
}
}
// 复制合并单元格
for (int i = 0; i < sourceSheet.getNumMergedRegions(); i++) {
targetSheet.addMergedRegion(sourceSheet.getMergedRegion(i));
}
try (FileOutputStream fos = new FileOutputStream(targetPath)) {
targetWorkbook.write(fos);
}
}
}
此方法可保留单元格样式、合并区域等格式,但需注意内存消耗,大文件建议使用SXSSFWorkbook(流式API)。
基于EasyExcel的高效复制方案
EasyExcel是阿里巴巴开源的轻量级Excel处理库,以低内存著称,适合处理大文件,其复制操作通过监听器模式实现:
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.write.metadata.WriteSheet;
public void copyEasyExcel(String sourcePath, String targetPath) {
// 写入流
try (ExcelWriter excelWriter = EasyExcel.write(targetPath).build()) {
WriteSheet writeSheet = EasyExcel.writerSheet("Sheet1").build();
// 读取并逐行写入
EasyExcel.read(sourcePath).sheet().doRead(new AnalysisEventListener<>() {
@Override
public void invoke(Object data, AnalysisContext context) {
EasyExcel.write(excelWriter, data).sheet().doWrite(Collections.singletonList(data));
}
@Override
public void doAfterAllAnalysed() {}
});
}
}
EasyExcel的优势在于内存优化,但复制复杂格式(如合并单元格、图表)时需额外处理。
基于JXL的旧版Excel支持
JXL仅支持.xls格式,适合处理旧版Excel文件:

import jxl.*;
import jxl.write.*;
public void copyJXL(String sourcePath, String targetPath) throws Exception {
Workbook sourceWorkbook = Workbook.getWorkbook(new File(sourcePath));
WritableWorkbook targetWorkbook = Workbook.createWorkbook(new File(targetPath));
Sheet sourceSheet = sourceWorkbook.getSheet(0);
WritableSheet targetSheet = targetWorkbook.createSheet("Copy", 0);
for (int i = 0; i < sourceSheet.getRows(); i++) {
for (int j = 0; j < sourceSheet.getColumns(); j++) {
Cell cell = sourceSheet.getCell(j, i);
targetSheet.addCell(new Label(j, i, cell.getContents()));
}
}
targetWorkbook.write();
targetWorkbook.close();
sourceWorkbook.close();
}
JXL API简单,但功能有限,不支持.xlsx格式。
不同场景的方案选择
| 场景 | 推荐方案 | 优点 | 缺点 |
|---|---|---|---|
| 小文件(<10MB) | Apache POI | 功能全面,支持格式完整 | 内存占用较高 |
| 大文件(>100MB) | EasyExcel | 低内存,流式处理 | 复杂格式支持有限 |
| 旧版Excel(.xls) | JXL | API简单,兼容性好 | 不支持.xlsx,已停止更新 |
| 需要高级样式操作 | Apache POI + SXSSF | 支持模板复制,大数据量优化 | 代码复杂度高 |
注意事项
- 内存管理:处理大文件时,避免使用
XSSFWorkbook,改用SXSSFWorkbook或EasyExcel。 - 异常处理:文件读写需捕获
IOException,确保资源关闭(try-with-resources)。 - 版本兼容:
.xls和.xlsx的API不同,需根据文件类型选择Workbook实现类。 - 性能优化:批量写入时,减少对象创建,复用CellStyle对象。
Java复制Excel的操作需根据文件大小、格式复杂度及性能需求选择合适的技术方案,Apache POI功能全面但内存消耗大,EasyExcel适合大数据场景,JXL仅适用于旧版文件,开发者需结合实际需求权衡利弊,并注意内存管理和异常处理,以确保复制操作的稳定性和高效性。

















