Java POI操作Excel报空指针:getRow返回null无法调用getCell方法
问题描述
开展Excel任务自动化开发工作时,程序运行抛出空指针异常,报错信息如下:
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "org.apache.poi.xssf.usermodel.XSSFRow.getCell(int)" because the return value of "org.apache.poi.xssf.usermodel.XSSFSheet.getRow(int)" is null
at com.excel.auto.ExcelAuto.main(ExcelAuto.java:43)
错误原因
报错核心来自Apache POI操作Excel的默认逻辑:
- 工作表中从未被编辑、创建过的空行,调用
XSSFSheet.getRow(int)时不会返回空行对象,直接返回null,代码中直接链式调用getCell()就会触发空指针 - 当前代码遍历行时默认0到最后一行序号之间的每一行都存在,没有考虑表中存在空白行、未初始化行的情况
现有代码还存在两个隐藏问题:
- 即使行存在,行内从未创建过的单元格调用
getCell()也会返回null,直接传入格式化方法、调用样式设置方法同样会触发空指针 - 文件写出逻辑放在了外层行遍历循环内部,每处理一行就重写一次整个文件,运行效率极低,还可能导致文件损坏
修复方法
- 遍历行时先判断行对象是否为null,是空行直接跳过
- 获取单元格时使用POI内置的空单元格处理策略,遇到不存在的单元格自动创建为空白单元格,避免空指针
- 将文件写出逻辑移到所有循环外部,等所有行处理完成后只执行一次写出操作
- 建议使用try-with-resources语法处理流对象,避免资源泄漏
关键修复代码示例:
// 提前存储最后行号,避免循环重复调用方法 int lastRowNum = sheet.getLastRowNum(); DataFormatter df = new DataFormatter(); for (int i = 0; i < lastRowNum + 1; i++) { // 先取行对象,空行直接跳过 XSSFRow rowWPBO = sheet.getRow(i); if (rowWPBO == null) { continue; } // 取单元格时指定空单元格策略,不存在则自动创建空白单元格 Cell cellTitleWPBO = rowWPBO.getCell(9, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); Cell cellAmountWPBO = rowWPBO.getCell(10, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); Cell cellCheckStatusWPBO = rowWPBO.getCell(6, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); for (int j = 0; j < lastRowNum + 1; j++) { XSSFRow rowSaxo = sheet.getRow(j); if (rowSaxo == null) { continue; } Cell cellDescriptionSaxo = rowSaxo.getCell(2, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); Cell cellNetChangeSaxo = rowSaxo.getCell(3, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); Cell cellCheckStatusSaxo = rowSaxo.getCell(5, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); // 以下原有业务判断逻辑无需修改 if (df.formatCellValue(cellCheckStatusSaxo).contains("-")) { // 保留原有交易匹配、样式设置、状态更新逻辑即可 } else { System.out.println("Checked"); } } } // 所有行处理完成后再统一写出文件 try (FileOutputStream outputStream = new FileOutputStream(excelFilePath)) { workbook.write(outputStream); } workbook.close(); inputStream.close(); System.out.println("Done");
注意:使用
Row.MissingCellPolicy需要提前导入org.apache.poi.ss.usermodel.Row包。
内容的提问来源于stack exchange,提问作者Teach Suppors
相关产品推荐
相关产品推荐

