You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 02:17:18