Spring MVC环境下Apache POI读取Excel仅能获取首行,请求解决
Apache POI读取Excel仅能获取首行问题排查
问题描述
使用Apache POI编写Excel读取代码,以IntelliJ IDEA为开发环境,运行后仅能读取Excel首行内容,无法读取后续行数据,需排查原因实现完整读取。
Maven依赖
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.11.0</version> </dependency> <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>
代码实现
package com.ferreteria.ferreteria; import java.io.File; import java.io.FileInputStream; import java.util.Iterator; import org.apache.poi.ss.usermodel.*; public class ExcelService { public static void leer() { String nombreArchivo = "Libro1.xlsx"; String rutaArchivo = "C:\\Users\\54261\\Downloads\\" + nombreArchivo; try (FileInputStream file = new FileInputStream(new File(rutaArchivo))) { // 读取Excel文件 Workbook worbook = WorkbookFactory.create(file); // 获取要读取的工作表 Sheet sheet = worbook.getSheetAt(0); // 获取工作表的所有行迭代器 Iterator<Row> rowIterator = sheet.rowIterator(); Row row; // 遍历每一行直到末尾 while (rowIterator.hasNext()) { row = rowIterator.next(); // 获取当前行的单元格迭代器 Iterator<Cell> cellIterator = row.cellIterator(); Cell cell; // 遍历每个单元格 while (cellIterator.hasNext()) { // 获取单元格并打印内容 cell = cellIterator.next(); System.out.print(cell.getStringCellValue()+" | "); } System.out.println(); } } catch (Exception e) { e.getMessage(); } } }
数据与运行情况
- Excel数据:包含首行表头(如ID、Nombre、Precio等)及多条业务数据,后续行存在数字类型单元格。
- 运行结果:控制台仅输出首行内容,后续行无任何输出。
问题原因与解决方案
核心原因
- 异常处理缺失:代码捕获异常后仅调用
e.getMessage(),未打印完整堆栈,后续行读取时若抛出异常(如非字符串类型单元格调用getStringCellValue()),会直接终止循环且无报错提示。 - 单元格类型未兼容处理:后续行存在数字类型单元格,直接调用
getStringCellValue()会触发IllegalStateException,导致循环中断。
修复方案
1. 完善异常处理
将catch块中的e.getMessage()替换为e.printStackTrace(),便于定位异常:
catch (Exception e) { e.printStackTrace(); }
2. 兼容不同单元格类型
添加工具方法处理不同类型的单元格值,避免类型转换异常:
private static String getCellValue(Cell cell) { if (cell == null) { return ""; } return switch (cell.getCellType()) { case STRING -> cell.getStringCellValue(); case NUMERIC -> DateUtil.isCellDateFormatted(cell) ? cell.getDateCellValue().toString() : String.valueOf(cell.getNumericCellValue()); case BOOLEAN -> String.valueOf(cell.getBooleanCellValue()); case FORMULA -> cell.getCellFormula(); default -> ""; }; }
然后将原代码中的cell.getStringCellValue()替换为getCellValue(cell)。
3. 改用更可靠的行遍历方式
替换迭代器遍历为索引遍历,避免迭代器可能存在的遗漏问题:
// 遍历所有行(从首行到最后一行) for (int rowIdx = sheet.getFirstRowNum(); rowIdx <= sheet.getLastRowNum(); rowIdx++) { Row row = sheet.getRow(rowIdx); if (row == null) { System.out.println(); continue; } // 遍历当前行的所有单元格 for (int cellIdx = row.getFirstCellNum(); cellIdx < row.getLastCellNum(); cellIdx++) { Cell cell = row.getCell(cellIdx); System.out.print(getCellValue(cell) + " | "); } System.out.println(); }
修复后的完整代码:
package com.ferreteria.ferreteria; import java.io.File; import java.io.FileInputStream; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.usermodel.DateUtil; public class ExcelService { public static void leer() { String nombreArchivo = "Libro1.xlsx"; String rutaArchivo = "C:\\Users\\54261\\Downloads\\" + nombreArchivo; try (FileInputStream file = new FileInputStream(new File(rutaArchivo))) { Workbook workbook = WorkbookFactory.create(file); Sheet sheet = workbook.getSheetAt(0); // 遍历所有行 for (int rowIdx = sheet.getFirstRowNum(); rowIdx <= sheet.getLastRowNum(); rowIdx++) { Row row = sheet.getRow(rowIdx); if (row == null) { System.out.println(); continue; } // 遍历当前行单元格 for (int cellIdx = row.getFirstCellNum(); cellIdx < row.getLastCellNum(); cellIdx++) { Cell cell = row.getCell(cellIdx); System.out.print(getCellValue(cell) + " | "); } System.out.println(); } } catch (Exception e) { e.printStackTrace(); } } private static String getCellValue(Cell cell) { if (cell == null) { return ""; } return switch (cell.getCellType()) { case STRING -> cell.getStringCellValue(); case NUMERIC -> DateUtil.isCellDateFormatted(cell) ? cell.getDateCellValue().toString() : String.valueOf(cell.getNumericCellValue()); case BOOLEAN -> String.valueOf(cell.getBooleanCellValue()); case FORMULA -> cell.getCellFormula(); default -> ""; }; } }
内容的提问来源于stack exchange,提问作者FrancoRuiz48
相关产品推荐
相关产品推荐

