Apache POI读取Excel报NullPointerException:sheet为null问题求助
问题分析与解决方案
核心问题拆解
- 依赖版本冲突:混用POI 5.2.2核心包与4.1.0的
poi-ooxml-schemas,版本不兼容会导致工作簿初始化失败,直接返回null。 - 异常处理缺失:代码捕获异常仅打印堆栈,后续仍执行
workbook.getSheet(sheetName),workbook为null时直接触发空指针。 - 工作表匹配问题:传入的
sheetName与Excel内工作表名称(大小写敏感)不一致时,getSheet()返回null,后续调用sheet.getLastRowNum()报错。 - 路径可靠性不足:硬编码路径或相对路径可能因环境差异导致文件找不到,进而工作簿初始化失败。
分步修复方案
1. 统一POI依赖版本
删除poi-ooxml-schemas 4.1.0,POI 5.x版本无需单独引入该包,poi-ooxml已包含所需schemas。
Maven依赖示例:
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>5.2.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.2.2</version> </dependency>
Gradle依赖示例:
implementation 'org.apache.poi:poi:5.2.2' implementation 'org.apache.poi:poi-ooxml:5.2.2'
2. 完善空值校验与异常处理
在使用workbook和sheet前必须做非空校验,同时改进异常处理逻辑,避免静默失败:
public static Object[][] getTestDataFromExcel(String sheetName) { // 用相对路径结合项目根目录,适配不同环境 File excelFile = new File(System.getProperty("user.dir") + "/src/main/java/com/seleniumHybridFrameworkProject/qa/testdata/seleniumHybridFrameworkProjectTestData.xlsx"); // 先校验文件是否存在 if (!excelFile.exists()) { throw new RuntimeException("Excel文件不存在:" + excelFile.getAbsolutePath()); } XSSFWorkbook workbook = null; // 用try-with-resources自动关闭输入流,避免资源泄漏 try (FileInputStream fisExcel = new FileInputStream(excelFile)) { workbook = new XSSFWorkbook(fisExcel); } catch (IOException e) { throw new RuntimeException("加载Excel文件失败", e); // 抛出异常终止执行,避免后续空指针 } // 校验工作簿初始化结果 if (workbook == null) { throw new RuntimeException("无法初始化Excel工作簿"); } XSSFSheet sheet = workbook.getSheet(sheetName); // 校验工作表是否存在,同时打印所有工作表名称辅助排查 if (sheet == null) { System.out.println("Excel中存在的工作表:"); for (int i = 0; i < workbook.getNumberOfSheets(); i++) { System.out.println("- " + workbook.getSheetName(i)); } throw new RuntimeException("指定的工作表不存在:" + sheetName); } int rows = sheet.getLastRowNum(); if (rows < 0) { throw new RuntimeException("工作表" + sheetName + "中无数据行"); } XSSFRow headerRow = sheet.getRow(0); if (headerRow == null) { throw new RuntimeException("工作表" + sheetName + "表头行不存在"); } int cols = headerRow.getLastCellNum(); Object[][] data1 = new Object[rows][cols]; for (int i = 0; i < rows; i++) { XSSFRow row = sheet.getRow(i + 1); if (row == null) { // 跳过空行 continue; } for (int j = 0; j < cols; j++) { XSSFCell cell = row.getCell(j); if (cell == null) { // 空单元格设为空字符串 data1[i][j] = ""; continue; } CellType cellType = cell.getCellType(); switch (cellType) { case STRING: data1[i][j] = cell.getStringCellValue(); break; case NUMERIC: // 区分数值与日期类型 if (DateUtil.isCellDateFormatted(cell)) { data1[i][j] = cell.getDateCellValue(); } else { data1[i][j] = Integer.toString((int) cell.getNumericCellValue()); } break; case BOOLEAN: data1[i][j] = cell.getBooleanCellValue(); break; default: data1[i][j] = ""; } } } // 关闭工作簿释放资源 try { workbook.close(); } catch (IOException e) { e.printStackTrace(); } return data1; }
3. 验证路径与工作表名称
- 打印文件绝对路径确认:通过
System.out.println(excelFile.getAbsolutePath())输出实际路径,手动检查文件是否存在。 - 核对工作表名称:
getSheet()方法大小写敏感,例如传入"Sheet1"但Excel内是"sheet1"会返回null,可通过代码中打印的工作表列表排查。
额外优化建议
- 将Excel文件移至
src/main/resources目录,通过类加载器获取资源,彻底避免路径硬编码:
InputStream is = YourClassName.class.getClassLoader().getResourceAsStream("testdata/seleniumHybridFrameworkProjectTestData.xlsx"); workbook = new XSSFWorkbook(is);
- 始终用
try-with-resources管理流和工作簿,防止资源泄漏。
内容的提问来源于stack exchange,提问作者Abhishek Giri
相关产品推荐
相关产品推荐

