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

如何使用Apache POI的SXSSFWorkbook更新指定单元格且不修改同行其他数据

问题原因与解决方法

两个错误版本的问题说明

  • 第一版错误:
    你创建SXSSFWorkbook后,仍然操作原始XSSFWorkbook的Sheet对象wb.getSheetAt(0),调用createRow(0)会直接覆盖原有第0行的所有数据,所以同一行其他单元格内容全部丢失。
  • 第二版错误:
    SXSSFWorkbook是流式处理类,默认会将超出你设置的窗口大小(你设置的100行)的行自动刷入磁盘,已经写入磁盘的行无法再修改。你调用createRow(0)时第0行已经被刷入磁盘,因此抛出IllegalArgumentException异常。且不管行有没有被刷盘,直接调用createRow都会覆盖原有行的所有内容,也会导致其他单元格丢失。

正确实现逻辑

要修改已有Excel的指定单元格,遵循以下规则:

  1. 优先用getRow()获取已有行,行不存在时再调用createRow()新建
  2. 优先用getCell()获取已有单元格,单元格不存在时再调用createCell()新建
  3. 如果要修改的行编号小于当前SXSSF的刷盘阈值,可以提前将需要修改的行加载到内存避免被刷盘,或如果修改的行范围很小,直接用XSSFWorkbook处理即可,不需要用SXSSF。

可运行的正确代码

加载已有文件的部分调整后:

final String FILE_NAME = "./sxssf_example.xlsx";
FileInputStream excelInputStream = new FileInputStream(new File(FILE_NAME));
XSSFWorkbook wb = new XSSFWorkbook(excelInputStream);
excelInputStream.close();

修改单元格的部分:

// 如果文件行数小于1万,可直接用XSSF处理,无需引入SXSSF的流式复杂度
SXSSFWorkbook wbss = new SXSSFWorkbook(wb, 100);
Sheet swbss = wbss.getSheetAt(0);

// 先读取已有行,不存在时再新建
Row row0 = swbss.getRow(0);
if (row0 == null) {
    row0 = swbss.createRow(0);
}
// 先读取已有单元格,不存在时再新建
Cell cell = row0.getCell(0);
if (cell == null) {
    cell = row0.createCell(0);
}
cell.setCellValue("jkkjh");

// 输出文件
final String FILE_NAME2 = "./new.xlsx";
FileOutputStream outputStream = new FileOutputStream(FILE_NAME2);
wbss.write(outputStream);
outputStream.close();
wbss.dispose();
wbss.close();
wb.close();

补充说明

如果必须使用SXSSF处理大文件,且需要修改的行号超过你设置的窗口大小,建议将窗口参数调大到大于你需要修改的最大行号,避免目标行被提前刷入磁盘无法修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 10:27:02