使用Apache POI通过正则匹配获取对应右侧单元格的值
用Apache POI实现Excel标签匹配取值(Python转Java)
我来帮你梳理下如何用Apache POI实现你要的功能——完全对应你原Python代码的逻辑,同时适配Excel单元格的各种类型问题。
首先明确你的核心需求:不依赖固定单元格位置,遍历Excel的行,检查每行E列(也就是每行的第一个单元格)的标签文本(忽略大小写),匹配到目标标签后,获取右侧F列(该行第二个单元格)的值赋值给对应变量。
先纠正下你伪代码里的小问题
你的伪代码里有两处小疏漏:
Iterator<Cell> = row.cellIterator();缺少变量名,应该是Iterator<Cell> cellIterator = row.cellIterator();- Apache POI的
Cell类没有直接的matches()方法,需要先把单元格值转成字符串再做匹配
完整实现思路与代码
下面是可直接运行的Java代码,包含了单元格类型处理、空值防护、模糊匹配等关键细节:
import org.apache.poi.ss.usermodel.*; import java.io.FileInputStream; import java.io.IOException; public class ExcelLabelExtractor { public static void main(String[] args) { String excelPath = "your-excel-file.xlsx"; // 替换成你的文件路径 String invoiceNumber = null; String issueDate = null; Double amountDue = null; try (FileInputStream inputStream = new FileInputStream(excelPath); Workbook workbook = WorkbookFactory.create(inputStream)) { // 处理第一个工作表,你可以根据需要改成指定名称的sheet:workbook.getSheet("Sheet1") Sheet sheet = workbook.getSheetAt(0); Iterator<Row> rowIterator = sheet.iterator(); while (rowIterator.hasNext()) { Row currentRow = rowIterator.next(); // 跳过没有足够单元格的空行,避免索引越界 if (currentRow.getPhysicalNumberOfCells() < 2) { continue; } // 获取E列的标签单元格(索引0),空单元格转为空白处理 Cell labelCell = currentRow.getCell(0, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); String labelText = getCellContentAsString(labelCell).trim().toLowerCase(); // 匹配标签,获取右侧F列(索引1)的值 if (labelText.contains("invoice number")) { invoiceNumber = getCellContentAsString(currentRow.getCell(1, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK)); } else if (labelText.contains("issue date")) { issueDate = getCellContentAsString(currentRow.getCell(1, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK)); } else if (labelText.contains("amount due")) { // 金额可能是数字类型,单独处理避免转字符串时的精度问题 Cell valueCell = currentRow.getCell(1, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK); if (valueCell.getCellType() == CellType.NUMERIC) { amountDue = valueCell.getNumericCellValue(); } else { // 兼容文本格式的金额 amountDue = Double.parseDouble(getCellContentAsString(valueCell)); } } } // 打印结果测试 System.out.println("Invoice Number: " + invoiceNumber); System.out.println("Issue Date: " + issueDate); System.out.println("Amount Due: " + amountDue); } catch (IOException e) { e.printStackTrace(); } } /** * 统一处理不同类型的单元格,转为字符串返回 * 支持文本、数字、日期、公式等类型 */ private static String getCellContentAsString(Cell cell) { if (cell == null) { return ""; } switch (cell.getCellType()) { case STRING: return cell.getStringCellValue(); case NUMERIC: if (DateUtil.isCellDateFormatted(cell)) { // 日期类型用DataFormatter转成Excel显示的格式 DataFormatter formatter = new DataFormatter(); return formatter.formatCellValue(cell); } else { // 数字类型直接转字符串,避免科学计数法 return String.valueOf(cell.getNumericCellValue()); } case BOOLEAN: return String.valueOf(cell.getBooleanCellValue()); case FORMULA: // 公式单元格计算出结果再处理 FormulaEvaluator evaluator = cell.getSheet().getWorkbook().getCreationHelper().createFormulaEvaluator(); return getCellContentAsString(evaluator.evaluateInCell(cell)); default: return ""; } } }
关键细节说明
- 空值与异常防护:使用
Row.MissingCellPolicy.CREATE_NULL_AS_BLANK把空单元格转为空白,避免空指针异常;同时跳过单元格数量不足的行,防止索引越界。 - 标签匹配逻辑:用
toLowerCase()统一转小写后再用contains()匹配,和你原Python代码的lower().find()逻辑完全一致;如果需要更严格的正则匹配(比如允许标签间有多个空格),可以改成labelText.matches(".*invoice\\s+number.*")。 - 多类型单元格处理:封装了
getCellContentAsString()方法,统一处理文本、数字、日期、公式等各种单元格类型,避免取值错误。 - 金额特殊处理:因为金额可能是数字类型,单独处理可以避免转字符串时出现精度问题,同时兼容文本格式的金额。
依赖配置(Maven为例)
确保你的项目引入了Apache POI的最新稳定版依赖:
<dependencies> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>5.2.5</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.2.5</version> </dependency> </dependencies>
内容的提问来源于stack exchange,提问作者OnlyDean
相关产品推荐
相关产品推荐

