如何用Java Apache POI高效迭代Excel行并映射数据至Java模型
优化Excel行迭代与Java模型映射方案
核心实现思路
- 建立表头与模型属性的映射关系,摒弃硬编码单元格坐标的方式,提升代码可维护性
- 迭代Excel数据行(跳过表头行),逐行将单元格数据转换并填充到
Customer模型 - 封装通用的单元格值转换逻辑,处理空值、不同数据类型兼容问题
步骤1:修正并完善Customer模型
首先修正原模型中的拼写错误,并补充必要的构造器、getter/setter:
public class Customer { private int number; private String customerName; // 修正原拼写错误:CusotmerName -> customerName private String customerLatest; private String customerYear; public Customer() {} // 全参构造器,方便快速实例化 public Customer(int number, String customerName, String customerLatest, String customerYear) { this.number = number; this.customerName = customerName; this.customerLatest = customerLatest; this.customerYear = customerYear; } // 生成getter和setter方法 public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } public String getCustomerName() { return customerName; } public void setCustomerName(String customerName) { this.customerName = customerName; } public String getCustomerLatest() { return customerLatest; } public void setCustomerLatest(String customerLatest) { this.customerLatest = customerLatest; } public String getCustomerYear() { return customerYear; } public void setCustomerYear(String customerYear) { this.customerYear = customerYear; } }
步骤2:实现Excel到模型的映射逻辑
通过POI的行迭代结合表头映射,完成批量数据转换:
import org.apache.poi.ss.usermodel.*; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class ExcelToCustomerMapper { public static List<Customer> convertExcelToCustomers(Sheet sheet) { List<Customer> customerList = new ArrayList<>(); if (sheet == null || sheet.getPhysicalNumberOfRows() <= 1) { return customerList; // 无有效数据行(仅表头或空表) } // 1. 构建表头列名与列索引的映射表 Row headerRow = sheet.getRow(0); Map<String, Integer> headerIndexMap = new HashMap<>(); for (Cell cell : headerRow) { String headerName = cell.getStringCellValue().trim(); headerIndexMap.put(headerName, cell.getColumnIndex()); } // 2. 遍历所有数据行(从第2行开始,索引为1) for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) { Row dataRow = sheet.getRow(rowIndex); if (dataRow == null) { continue; // 跳过空行 } Customer customer = new Customer(); // 填充number字段(假设Excel表头为"编号") Integer numberColIndex = headerIndexMap.get("编号"); if (numberColIndex != null) { Cell numberCell = dataRow.getCell(numberColIndex, MissingCellPolicy.RETURN_BLANK_AS_NULL); if (numberCell != null) { if (numberCell.getCellType() == CellType.NUMERIC) { customer.setNumber((int) numberCell.getNumericCellValue()); } else if (numberCell.getCellType() == CellType.STRING) { // 兼容字符串格式的数字 customer.setNumber(Integer.parseInt(numberCell.getStringCellValue().trim())); } } } // 填充customerName字段(假设Excel表头为"客户名称") Integer nameColIndex = headerIndexMap.get("客户名称"); if (nameColIndex != null) { Cell nameCell = dataRow.getCell(nameColIndex, MissingCellPolicy.RETURN_BLANK_AS_NULL); customer.setCustomerName(getCellStringValue(nameCell)); } // 填充customerLatest字段(假设Excel表头为"最新状态") Integer latestColIndex = headerIndexMap.get("最新状态"); if (latestColIndex != null) { Cell latestCell = dataRow.getCell(latestColIndex, MissingCellPolicy.RETURN_BLANK_AS_NULL); customer.setCustomerLatest(getCellStringValue(latestCell)); } // 填充customerYear字段(假设Excel表头为"年份") Integer yearColIndex = headerIndexMap.get("年份"); if (yearColIndex != null) { Cell yearCell = dataRow.getCell(yearColIndex, MissingCellPolicy.RETURN_BLANK_AS_NULL); customer.setCustomerYear(getCellStringValue(yearCell)); } customerList.add(customer); } return customerList; } // 通用工具方法:将单元格值转换为字符串,统一处理空值和不同数据类型 private static String getCellStringValue(Cell cell) { if (cell == null) { return null; } switch (cell.getCellType()) { case STRING: return cell.getStringCellValue().trim(); case NUMERIC: // 若年份是日期格式,可在此处添加日期转换逻辑 return String.valueOf((int) cell.getNumericCellValue()); case BOOLEAN: return String.valueOf(cell.getBooleanCellValue()); default: return null; } } }
方案优势
- 低耦合:表头列顺序调整时,仅需修改映射的表头名称,无需改动单元格索引相关代码
- 鲁棒性强:处理空行、空单元格,兼容数字/字符串等多种单元格类型
- 可扩展:新增模型字段时,只需添加对应的表头映射和属性赋值逻辑即可
内容的提问来源于stack exchange,提问作者developer new
相关产品推荐
相关产品推荐

