使用POI读取Excel时cellIterator.hasNext()遇空单元格返回false如何解决
问题原因
Apache POI 中Row.cellIterator()默认仅会迭代已被初始化(包含值、格式等属性)的单元格,完全未创建的空单元格不会被纳入迭代范围,因此会出现空单元格无法触发迭代的问题。
实现方案
不要使用单元格迭代器,改为根据固定列数手动遍历列索引,同时指定空单元格的处理策略即可:
- 先读取表头行的总列数作为遍历的统一列数基准,避免不同行有效列数不一致
- 使用
Row.getCell(int index, Row.MissingCellPolicy)重载方法获取单元格,通过MissingCellPolicy.CREATE_NULL_AS_BLANK策略将未初始化的空单元格自动转为空白单元格返回
修改后的完整代码
import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.DateUtil; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.BufferedInputStream; import java.io.InputStream; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Iterator; import java.util.List; // 业务代码部分 InputStream inputStream = new BufferedInputStream(multipartFile.getInputStream()); XSSFWorkbook myWorkBook = new XSSFWorkbook(inputStream); List<String> cellList = new ArrayList<>(); XSSFSheet mySheet = myWorkBook.getSheetAt(0); // 先获取表头总列数,作为统一遍历列数 int totalColumn = mySheet.getRow(0).getLastCellNum(); Iterator<Row> rowIterator = mySheet.iterator(); rowIterator.next(); // 跳过表头 while (rowIterator.hasNext()) { Row row = rowIterator.next(); cellList.clear(); // 遍历所有列,而非用迭代器 for (int i = 0; i < totalColumn; i++) { // 空单元格自动创建为BLANK类型,不会返回null Cell cell = row.getCell(i, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); // 通用方法处理不同类型的单元格值,避免类型转换报错 cellList.add(getCellValue(cell)); } } // 通用单元格值读取方法 private String getCellValue(Cell cell) { if (cell == null) { return ""; } switch (cell.getCellType()) { case STRING: return cell.getStringCellValue().trim(); 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 BLANK: return ""; case FORMULA: return cell.getCellFormula(); default: return ""; } }
注意事项
- 如果不需要全局统一列数,也可以每行单独取
row.getLastCellNum()作为当前行的遍历上限,可根据业务需求选择 - 不要直接调用
getStringCellValue(),否则数字、日期、布尔类型的单元格会抛出类型转换异常
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

