parent-spring-tools

spring-excel-mapper

轻量级、注解驱动的 Excel 导入/导出映射器(Java JDK 17+)。

概述

spring-excel-mapper 提供注解驱动的 Excel Workbook/Sheet 与 Java POJO 之间的映射,以及将对象导出到 Excel 模板(保留样式)的工具。

核心功能:

快速示例:

@ExcelSheet
@ExcelRow(startRowIndex = 1)
public class StudentExcelModel {
    @ExcelColumn(col = "A", required = true)
    public String name;
}

Workbook wb = WorkbookFactory.create(inputStream);
ImportResult<StudentExcelModel> result = 
    ExcelMapper.parseWorkbookWithResult(wb, StudentExcelModel.class, false);

使用模式和示例,请参见 spring-tools-simples README


架构与设计

核心组件

1. 注解(org.springtools.excel.annotation

在模型类上定义映射元数据:

@ExcelSheet

@ExcelRow

@ExcelSection

@ExcelColumn

2. 映射与 I/O

ExcelMapper — 读取 Excel → Java 对象

主要方法:

ExcelExporter — 写入 Java 对象 → Excel 模板

主要方法:

3. 验证与转换

ExcelValidator

ExcelTypeConverter

4. 工具

ExcelUtils — 底层辅助方法


技术细节

列映射

列映射使用 Excel 列字母(A、B、C、…、Z、AA、AB、…)。ExcelUtils.colLetterToIndex 将字母转换为 POI API 使用的 0 基索引。

行索引

注解使用从 1 开始的”自然”编号(第 1 行 = Excel UI 中的第一行)。调用 POI API 时,代码通常会执行 -1

字段顺序与绑定缓存

ExcelUtils.prepareBindings(Class) 读取 clazz.getDeclaredFields() 并缓存绑定。字段声明顺序当前很重要。考虑在未来版本中为 @ExcelColumn 添加 order() 以实现显式排序。

区段解析

@ExcelSection 使用 sectionKeyword + keywordInCol 来定位数据块。ExcelMapper.parseSheetSection 扫描关键字,然后读取其下方的行,直到 stopKeyword 或 sheet 结束。

错误处理


API 参考

ExcelMapper

// 解析所有 sheet,出错时抛异常
List<T> parseWorkbook(Workbook workbook, Class<T> clazz)

// 解析并收集错误
ImportResult<T> parseWorkbookWithResult(Workbook workbook, Class<T> clazz, boolean failFast)

// 按 sheet 名称解析
Map<String, List<T>> parseWorkbookBySheet(Workbook workbook, Class<T> clazz, boolean includeEmpty)

// 解析基于区段的模型
List<T> parseSheetSection(Sheet sheet, Class<T> clazz)

ExcelExporter

// 填充模板行
void fillTableRows(Sheet sheet, int startRow, List<T> dataList, Class<T> clazz)

// 填充模板中的区段
void fillSection(Sheet sheet, String sectionKeyword, String keywordInCol, 
                 List<T> dataList, Class<T> clazz)

// 克隆 sheet 及样式
Sheet copySheetWithStyles(Sheet sourceSheet, Workbook targetWorkbook, String newSheetName)

ExcelValidator

// 验证单个对象
ValidationResult validate(Object obj, int rowNum, Class<?> clazz)

// 验证列表(检查唯一性约束)
List<ValidationResult> validateList(List<T> list, Class<T> clazz)

ExcelTypeConverter

// 将单元格值转换为目标类型
<T> T convertValue(Object value, Class<T> targetType, String dateFormat)

注意事项与建议

当前限制

  1. 字段顺序: 绑定依赖于 getDeclaredFields() 顺序。为确保跨编译器和重构的稳定性:
    • @ExcelColumn 添加 order() 属性
    • 或明确记录字段声明顺序要求
    • 添加测试以验证确定性映射
  2. 错误类型: 当前使用通用 RuntimeException。考虑添加:
    • 包含 sheet/row/col 上下文的 ExcelParseException
    • 包含收集错误的 ValidationException
  3. 性能: 每次解析都会进行反射。prepareBindings 现在使用缓存,但考虑:
    • 如果绑定被修改,使用防御性副本
    • 为大型数据集进行基准测试

推荐改进

  1. 验证:
    • 添加批量验证模式(在失败前收集所有错误)
    • 支持自定义验证器钩子
    • 为字符串添加正则表达式模式验证(已支持 regex 属性)
  2. 导出:
    • 添加公式保留选项
    • 支持条件格式复制
    • 添加行高/列宽保留
  3. 测试:
    • 为公式、合并单元格添加集成测试
    • 测试边缘情况:空行、skipRowByBlankunique 约束
    • 测试枚举转换、数值范围、日期格式
  4. 文档:
    • 为所有公共方法添加 JavaDoc
    • 在 README 中添加更多内联示例

使用示例

参见 spring-tools-simples README 了解:

相关文档