Java实现Excel指定列过滤特定值时遇数字格式异常问题
解决Excel过滤时的NumberFormatException问题
问题原因
你遇到的NumberFormatException是因为:
- 原代码仅判断单元格类型为
CELL_TYPE_STRING,但Excel中部分单元格可能实际存储类型为数字/日期,但显示为文本,POI会识别为NUMERIC类型; - 当代码尝试对
NUMERIC类型单元格调用getRichStringCellValue()时,会直接抛出该异常,因为该方法仅适用于字符串类型单元格。
另外原代码还存在两个潜在问题:
findRow方法参数为HSSFSheet,但调用时传入的是XSSFSheet,会导致编译错误;- 使用无泛型的原始
List,代码规范性差,易引发类型转换问题。
解决方案
修改思路:
- 使用POI通用接口(
Workbook/Sheet/Row)替代具体实现类,兼容不同Excel格式,避免类型不匹配; - 新增工具方法统一处理所有单元格类型,将单元格内容转为字符串后再进行比较;
- 处理公式单元格,先计算实际值再转换;
- 使用泛型集合,规范代码逻辑。
修改后的完整代码
import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.FileInputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.List; public class ExcelFilter { public static void main(String[] args) throws Exception { String fileName = "filepath"; String cellContent = "Automation"; int targetCol = 0; // 需要提取数据的目标列索引 // 使用try-with-resources自动关闭资源,避免泄漏 try (InputStream input = new FileInputStream(fileName); Workbook wb = new XSSFWorkbook(input)) { Sheet sheet = wb.getSheetAt(0); List<String> filteredResults = findMatchingRows(sheet, cellContent, targetCol); if (!filteredResults.isEmpty()) { for (String result : filteredResults) { System.out.println(result); } } } } private static List<String> findMatchingRows(Sheet sheet, String targetContent, int targetCol) { List<String> results = new ArrayList<>(); FormulaEvaluator evaluator = sheet.getWorkbook().getCreationHelper().createFormulaEvaluator(); for (Row row : sheet) { for (Cell cell : row) { String cellValue = getCellStringValue(cell, evaluator); // 匹配目标内容时,提取目标列的单元格值 if (cellValue.equals(targetContent)) { Row targetRow = sheet.getRow(row.getRowNum()); if (targetRow != null) { Cell targetCell = targetRow.getCell(targetCol); results.add(getCellStringValue(targetCell, evaluator)); } } } } return results; } // 统一处理所有单元格类型,转为字符串 private static String getCellStringValue(Cell cell, FormulaEvaluator evaluator) { if (cell == null) { return ""; } // 先处理公式单元格,计算实际值 if (cell.getCellType() == CellType.FORMULA) { Cell evaluatedCell = evaluator.evaluateInCell(cell); return getCellStringValue(evaluatedCell, evaluator); } switch (cell.getCellType()) { case STRING: return cell.getRichStringCellValue().getString().trim(); case NUMERIC: if (DateUtil.isCellDateFormatted(cell)) { return cell.getDateCellValue().toString(); } else { // 处理数字,避免科学计数法 double numValue = cell.getNumericCellValue(); return numValue == (long) numValue ? String.valueOf((long) numValue) : String.valueOf(numValue); } case BOOLEAN: return String.valueOf(cell.getBooleanCellValue()).trim(); case BLANK: return ""; default: return ""; } } }
关键修改说明
- 通用接口替换:用
Workbook/Sheet替代XSSFWorkbook/XSSFSheet,同时兼容.xls和.xlsx格式,解决类型不匹配问题; - 单元格统一转换:
getCellStringValue方法覆盖所有单元格类型(字符串、数字、日期、公式、布尔值),将内容转为字符串后再比较,彻底避免类型相关异常; - 资源自动管理:使用try-with-resources语法,自动关闭输入流和Workbook,无需手动处理资源释放;
- 泛型集合:使用
List<String>存储结果,代码更规范,避免后续输出时的类型转换问题。
内容的提问来源于stack exchange,提问作者Pooja
相关产品推荐
相关产品推荐

