excel外部数据导入篇(玩转Excel数据导入)

1. 概览

在日常开发中,想必都遇到过批处理的需求,简单来说就是要求上传一个 Excel 文件,从 Excel 中读取数据,然后进行业务处理。对此,你怎么做呢?

使用 poi 一行行的读取数据,然后进行类型转换,最后调用业务方法。非常不错,恭喜你完成了这项工作。但,到此为止了吗?

1.1. 背景

经常会遇到这种情况,上线了一个需求,业务觉得不错,只是一条条录入效率太低,随后提出能不能搞一个 Excel 批量处理?当然,我们可以直接撸码,顺便加个小班,一气呵成。

简单回想一下,你有多久不处理手工的类型转换?

比如 Spring MVC 框架中,我们直接使用 JavaBean 来接收 request 请求的数据,那有没有一种方式可以从 Excel 中读取出 JavaBean 呢?

excel外部数据导入篇(玩转Excel数据导入)(1)

Excel 数据转换

1.2. 目标

按照标准操作流程,框架需要支持:

  1. 从 Class 中读取信息生成 Excel 模板,该模板需要对部分数据进行保护,不允许用户修改;
  2. 用户获取 Excel 模板后,按要求完成相关信息填写,然后将 Excel 转换为 JavaBean 对象,快速完成业务操作;
  3. 前面两步需要支持嵌套 Bean,无需将关联对象的属性进行展开;
2. 快速入门2.1. 添加 starter 及相关依赖

在 Spring boot 项目的 pom 中增加如下依赖:

<dependency> <groupId>com.geekhalo.lego</groupId> <artifactId>lego-starter-excelasbean</artifactId> <version>0.1.1</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> </dependency>

2.2. 注入 ExcelAsBeanService 服务

在代码中直接注入 ExcelAsBeanService 对象,具体如下:

//注入excelAsBeanService //由ExcelAsBeanAutoConfiguration完成ExcelAsBeanService的注册 @Autowired privateExcelAsBeanServiceexcelAsBeanService;

2.3. 创建 Excel 模板

核心代码如下:

/** *创建Excel模板 *@paramworkbook *@paramsheetName *@paramdataCls *@param<D> */ default<D>voidwritTemplateToSheet(HSSFWorkbookworkbook,StringsheetName,Class<D>dataCls){ writTemplateToSheet(workbook.createSheet(sheetName),dataCls); } /** *创建Excel模板 *@paramsheet待写入的sheet *@paramdataCls待写入数据 *@param<D> */ <D>voidwritTemplateToSheet(HSSFSheetsheet,Class<D>dataCls);

该方法,从 class 中读取信息,并将其写入到 Excel 模板。

2.4. 从 Excel 中读取并转换为 JavaBean

核心代码如下

/** *从Sheet中读取数据 *@paramsheet待读取数据的Sheet *@paramdataCls待读取数据的类型 *@param<D> */ default<D>List<D>readFromSheet(HSSFSheetsheet,Class<D>dataCls){ List<D>result=Lists.newArrayList(); readFromSheet(sheet,dataCls,d->result.add(d)); returnresult; } /** *从Sheet中读取数据 *@paramsheet待读取数据的Sheet *@paramdataCls待读取数据的类型 *@paramconsumer回调器,完成数据解析后,直接调用回调器 *@param<D> */ <D>voidreadFromSheet(HSSFSheetsheet,Class<D>dataCls,Consumer<D>consumer);

该方法,从 Sheet 中读取信息,并将其转换为 JavaBean;

2.5. 普通 bean 示例

首先,我们创建 JavaBean,并添加相关注解,具体如下:

@Data publicclassCreateUserFromV1implementsCreateUserFrom{ @HSSFTemplateHeader(title="姓名") privateStringname; @HSSFTemplateHeader(title="出生日期") privateDatebirthAt; @HSSFTemplateHeader(title="年龄") privateIntegerage; }

其中,@HSSFTemplateHeader 中的 title 为展示信息。

调用 writTemplateToSheet 方法,获取 Excel 如下:

excel外部数据导入篇(玩转Excel数据导入)(2)

简单Bean模板

如图可见,Excel 中有 姓名(name),出生日期(birthAt) 和 年龄(age) 三列,当试图对 Header 进行修改时,弹出提示信息“受保护区域,不允许操作”。

拿到模板后,在Excel中填入信息如下:

excel外部数据导入篇(玩转Excel数据导入)(3)

简单Bean输入数据

将该 Excel 上传服务器,调用 readFromSheet 方法,获取最终 Bean 如下:

excel外部数据导入篇(玩转Excel数据导入)(4)

简单Bean解析结果

2.6. 嵌套 bean 示例

首先,创建一个关联类,如下:

@Data publicclassAddressForm{ @HSSFTemplateHeader(title="省") privateStringl1; @HSSFTemplateHeader(title="市") privateStringl2; @HSSFTemplateHeader(title="区") privateStringl3; @HSSFTemplateHeader(title="详细地址") privateStringl4; }

关联对象没有什么特别之处,只是增加了 @HSSFTemplateHeader 注解。

新建 Bean 如下:

@Data publicclassCreateUserFromV2implementsCreateUserFrom{ @HSSFTemplateHeader(title="姓名") privateStringname; @HSSFTemplateHeader(title="出生日期") privateDatebirthAt; @HSSFTemplateHeader(title="年龄") privateIntegerage; @HSSFEmbedded privateAddressFormaddressForm; }

也没有特殊之处,只是在 关联对象上增加了 @HSSFEmbedded 注解。

导出模板,查看效果:

excel外部数据导入篇(玩转Excel数据导入)(5)

嵌套Bean模板

如图所示,Excel 中新增 省、市、区、详细地址几列,用于数据输入。

同样,再拿到模板后,在Excel中填入信息如下:

excel外部数据导入篇(玩转Excel数据导入)(6)

嵌套Bean数据

将该 Excel 上传服务器进行处理,获取最终 Bean 如下:

excel外部数据导入篇(玩转Excel数据导入)(7)

嵌套Bean结果

3. 设计&扩展3.1. 核心设计

整体设计如下:

excel外部数据导入篇(玩转Excel数据导入)(8)

整体结构

  1. Class 通过解析后获得一个 HSSFSheetReader,用于负责所有的读操作;
  2. 每个 HSSFSheetReader 提供 write template 和 read data 两组核心功能;
  3. HSSFRowToBeanWriter 通过 ColumnToBeanPropertyWriter 完成每一列到Bean属性的映射;
  4. write 模板核心流程如下:
  5. 为 Header Row 设置默认样式;
  6. 从 HSSFRowToBeanWriter 获取解析后的 title 信息,并写入 Cell
  7. 设置Header样式为保护模式,不允许任意修改;
  8. reader data 流程如下:
  9. 从 Header 中获取 path 和 Index 的映射;
  10. 基于 ColumnToBeanPropertyWriter,从 Cell 中读取数据,并写入到 Bean 的属性;
  11. 回调消费函数,处理转换好的 Bean 对象;
3.2. 功能扩展

excel外部数据导入篇(玩转Excel数据导入)(9)

读取链设计

核心执行流程如下:

  1. HSSFCellReader 从 Cell 中读取数据;
  2. BeanPropertyWriter 将数据写入到 JavaBean 的属性;

装配流程如下:

  1. String 以托管 bean 的方式,提供 CellReaderFactory 和 BeanPropertyWriterFactory 实现;
  2. 这些实现会注入到 HSSFCellReaderFactories 和 BeanPropertyWriterFactories,由 Factories 对其进行统一管理;
  3. DefaultBeanPropertyWriterChainFactory 从 Factories 中获取合适的 HSSFCellReader 和 BeanPropertyWriter,将其封装为 BeanPropertyWriterChain;
4. 项目信息

项目仓库地址:https://gitee.com/litao851025/lego

项目文档地址:https://gitee.com/litao851025/lego/wikis/support/ExcelAsBean--数据导入

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页