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

使用POI读取Excel存入二维数组丢失最后一行的解决方法咨询

解决POI读取Excel缺失最后一行的问题

问题根源

Apache POI的getLastRowNum()方法返回的是最后一行的索引值(从0开始计数),而非总行数。比如表格有3行数据,行索引为0、1、2,getLastRowNum()会返回2。如果直接用这个值作为数组长度和循环上限,循环只会执行r < 2(即遍历0、1行),自然漏掉最后一行。

除了+1之外的优化方案

方案1:使用行迭代器遍历(推荐)

POI提供了行迭代器,无需手动处理行号,既能避免索引计算错误,还能灵活处理空行:

String filePath = "C:\\testXL.xlsx";
FileInputStream fis = new FileInputStream(filePath);
XSSFWorkbook wb = new XSSFWorkbook(fis);
XSSFSheet ws = wb.getSheet("Sheet1");

// 先确认首行存在再获取列数
XSSFRow headerRow = ws.getRow(0);
if (headerRow == null) {
    // 处理空表格情况
    fis.close();
    wb.close();
    return;
}
int cols = headerRow.getLastCellNum();

// 用List存储数据,无需提前确定总行数
List<String[]> rowList = new ArrayList<>();

// 遍历所有有效行
Iterator<Row> rowIterator = ws.iterator();
while (rowIterator.hasNext()) {
    XSSFRow currentRow = (XSSFRow) rowIterator.next();
    String[] rowData = new String[cols];
    
    for (int c = 0; c < cols; c++) {
        Cell cell = currentRow.getCell(c);
        // 处理空单元格,避免空指针
        rowData[c] = cell != null ? cell.toString() : "";
        System.out.print(rowData[c] + "\t");
    }
    
    rowList.add(rowData);
    System.out.println();
}

// 按需转为二维数组
String[][] rowCol = rowList.toArray(new String[0][]);

// 记得关闭资源
fis.close();
wb.close();

这个方案的优势:

  • 完全规避行索引计算错误,自动遍历所有有效行
  • 用List动态存储,无需提前预估总行数
  • 可轻松过滤或保留空行(根据业务需求调整)

方案2:调整循环边界(保留数组方式)

如果坚持用数组+索引循环,除了给getLastRowNum()加1,还可以直接修改循环条件,逻辑更清晰:

String filePath = "C:\\testXL.xlsx";
FileInputStream fis = new FileInputStream(filePath);
XSSFWorkbook wb = new XSSFWorkbook(fis);
XSSFSheet ws = wb.getSheet("Sheet1");

XSSFRow headerRow = ws.getRow(0);
if (headerRow == null) {
    fis.close();
    wb.close();
    return;
}
int cols = headerRow.getLastCellNum();
int lastRowIndex = ws.getLastRowNum();
// 总行数 = 最后一行索引 + 1
String[][] rowCol = new String[lastRowIndex + 1][cols];

// 循环条件改为 r <= lastRowIndex,覆盖所有行索引
for (int r = 0; r <= lastRowIndex; r++){
    XSSFRow currentRow = ws.getRow(r);
    // 处理空行,避免空指针
    if (currentRow == null) {
        rowCol[r] = new String[cols];
        continue;
    }
    
    for (int c = 0; c < cols; c++){
        Cell cell = currentRow.getCell(c);
        rowCol[r][c] = cell != null ? cell.toString() : "";
        System.out.print(rowCol[r][c] + "\t");
    }
    System.out.println();
}

fis.close();
wb.close();

这里额外优化了空行和空单元格的判断,避免运行时抛出NullPointerException。

额外优化建议

直接调用cell.toString()可能导致非字符串类型单元格的结果不符合预期(比如日期会显示为数字或乱码字符串),可以根据单元格类型做格式化处理:

private String getCellValue(Cell cell) {
    if (cell == null) return "";
    switch (cell.getCellType()) {
        case STRING:
            return cell.getStringCellValue();
        case NUMERIC:
            if (DateUtil.isCellDateFormatted(cell)) {
                return new SimpleDateFormat("yyyy-MM-dd").format(cell.getDateCellValue());
            } else {
                return String.valueOf(cell.getNumericCellValue());
            }
        case BOOLEAN:
            return String.valueOf(cell.getBooleanCellValue());
        case FORMULA:
            return cell.getCellFormula();
        default:
            return "";
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 11:30:49