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

Apache POI:getRow()返回null但工作表含非空行的问题排查

问题分析与解决方案

问题原因

你遇到的getRow(0)、getRow(47)返回null的情况,本质是SXSSFWorkbook的流式处理机制导致的:
SXSSF是POI针对大数据量Excel的流式实现,默认会在内存中只保留最近的100行(滑动窗口机制),超出这个范围的行被写入临时磁盘文件,此时调用getRow()获取已刷出内存的行就会返回null。你的Excel有148行,第0-47行正好超出了默认窗口,所以无法直接获取。

另外注意你的代码里存在拼写错误:sheet.getFristRowNum()应该是sheet.getFirstRowNum(),这个错误会导致编译失败,需优先修正。

解决方案

方案1:调整SXSSF窗口大小(适合小数据量)

因为你的Excel只有148行,完全可以把窗口大小设置为大于148的值,让所有行都留在内存中:

// 创建SXSSFWorkbook时指定窗口大小为200,覆盖所有行
SXSSFWorkbook workbook = new SXSSFWorkbook(200);

这样sheet.getRow(sheet.getFirstRowNum())就能正常获取到首行,后续的列宽调整逻辑可以正常执行。

方案2:流式处理时提前跟踪列宽(适合大数据量)

如果后续数据量很大,不想占用过多内存,可以在写入Excel的阶段就跟踪每一列的最大内容宽度,最后统一设置列宽,避免事后读取已刷出内存的行:

// 示例:写入数据时跟踪列宽
Map<Integer, Integer> columnMaxWidth = new HashMap<>();
Row row = sheet.createRow(rowNum);
Cell cell = row.createCell(colIndex);
cell.setCellValue(cellValue);
// 计算当前单元格内容宽度(POI列宽单位为1/256字符宽度)
int width = cellValue.toString().length() * 256;
columnMaxWidth.put(colIndex, Math.max(columnMaxWidth.getOrDefault(colIndex, 0), width));

// 所有数据写入完成后,统一设置列宽
for (Map.Entry<Integer, Integer> entry : columnMaxWidth.entrySet()) {
    int colIndex = entry.getKey();
    if (sheet instanceof SXSSFSheet) {
        ((SXSSFSheet) sheet).trackColumnForAutoSizing(colIndex);
    }
    sheet.setColumnWidth(colIndex, entry.getValue());
}

方案3:读取时禁用行刷出(临时方案)

如果是读取已有的Excel文件,也可以在创建SXSSFWorkbook时禁用行刷出,但不建议大数据量场景使用:

SXSSFWorkbook workbook = new SXSSFWorkbook(XSSFWorkbookFactory.create(new FileInputStream("your-file.xlsx")), Integer.MAX_VALUE);

内容的提问来源于stack exchange,提问作者Radosław Poprawa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 08:43:20