easy excel, 读映射

综述

        本篇介绍读映射,分为两类映射。

        概念映射:Easy excel框架与excel文件之间的映射关系

  1. ExcelReaderBuilder,ReadWorkBook 对应Excel文件
  2. ExcelReaderSheetBuilder, ReadSheet,对应sheet页
  3. Cell对应单元格, CellExtra对应附加信息,例如超链接,注释,标注等
  4. API分析

        实体映射:excel数据与实体类之间的映射关系。

  1. 类层级,无对应,一对一,一对多个实体,一对同一实体集合。
  2. 字段层级
  3. 值层级

      概念映射

        默认情况下,一般一次读取只读取一个Excel文件。

        一个Excel文件拥有多个sheet页,与它对应的对象为ReadWorkBook。

        一个Sheet页拥有多个单元格,与它对应的对象为ReadSheet。

        一个单元格拥有数据内容和附加信息,与它对应的对象为Cell接口。

        附加信息,例如标注,注释,超链接等等,与它对应的对象为CellExtra,CellExtraTypeEnum包含附加信息的类型。

        Easy Excel使用Builder来构建彼此之间的关系,EasyExcel调用read,返回ExcelReaderBuilder对象,它自动注入ReadWorkBook对象,调用sheet方法,返回ExcelReaderSheetBuilder,调用doRead时,每个单元格的内容对应ReadCell,若有附加信息,对应CellExtra。 

2.1 ReadWorkBook

        ReadWorkBook没有操作,它的属性由两部分组成

        第一部分,它自身的属性。

        第二部分,表单的公共属性,可以单独设置sheet页的属性,统一设置更方便。

2.1.1 自身属性

        使用EasyExcel.read方法,它返回ExcelReaderBuilder对象,使用它设置属性

        Excel文件相关

// 对应excelType属性,CSV, XLSX,XLS
readerBuilder.excelType(ExcelTypeEnum.XLSX);
// 对应inputStream,file属性, 三种参数类型,filePath, File对象,InputStream对象
String filePath ="F:\\Learn\\LearnEasyExcel\\carInfo.xlsx";
readerBuilder.file(filePath);
// 对应charset属性
readerBuilder.charset(Charset.defaultCharset());
// 密码,对应password属性
readerBuilder.password("xx");

        读取行为

// 忽略空白行
readerBuilder.ignoreEmptyRow(true);
// 对应extraReadSet, 有超链接,注释,标注三种
readerBuilder.extraRead(CellExtraTypeEnum.HYPERLINK);
// 返回的数据类型,用String接就可以,不然会内部进行类型转换,报错就没有后续操作了。
readerBuilder.readDefaultReturn(ReadDefaultReturnEnum.String);
// 对应autoCloseStream
readerBuilder.autoCloseStream(true);
// 读取缓存,超出5M时使用缓存,缓存对象类型需要相关的缓存框架支持
readerBuilder.readCache(new MapCache());

        杂项

// 对应mandatoryUseInputStream属性
readerBuilder.mandatoryUseInputStream(false);
// 缓存的选择器
readerBuilder.readCacheSelector(new SimpleReadCacheSelector());
// 对应xlsxSAXParserFactoryName
readerBuilder.xlsxSAXParserFactoryName("");
// 对应useDefaultListener
readerBuilder.useDefaultListener(true);

2.1.2 Sheet公共属性

        获取Sheet表单

// 只有一个sheet页
readerBuilder.sheet();
// 指定某个sheet页,位置
readerBuilder.sheet(0);
// 指定某个sheet页,名称
readerBuilder.sheet("sheet_name");
// 二者的结合
readerBuilder.sheet(0, "sheet_name");

        标题

// 带标题
sheetBuilder.head(Car.class);
// 指定标题占的行数
sheetBuilder.headRowNumber(1);

        转换器和监听器

// 注册类型转换器
sheetBuilder.registerConverter();
// 注册监听器
sheetBuilder.registerReadListener();

        杂项

// 是否对数据进行trim
sheetBuilder.autoTrim(true);
// 时间保存的是数字,默认开始时间为1990年,设置该值,开始时间为1904年
sheetBuilder.use1904windowing(false);
// 是否使用科学计数法
sheetBuilder.useScientificFormat(true);

2.2 ReadSheet

        通过sheetNo,名称获取sheet, 在ExcelReaderBuilder统一为sheet方法,ExcelReaderSheetBuilder使用的sheetNo,sheetName。

// sheet位置,从0开始
sheetBuilder.sheetNo(0);
// sheet名称
sheetBuilder.sheetName("sheet_name");

2.3 API分析 

        官网提供的读有四种写法。以第三种写法为例。EasyExcel.read(filename,class, listener).sheet().doRead()。它由三部分组成,

        第一部分, read,设置workBook的属性,注册监听器等等。

        第二部分,sheet, 获取某个sheet页。

        第三部分,读取,两种方式doRead,或者doReadSync。

        所有写法的组成结构都是相似的。

        第一种,pageReadListener提供了分页功能,感觉没必要。EasyExcel.read(filename, class, pageReadListener).sheet().doRead();

        第二种,匿名内部类的方式,通常不合适,阅读性较差。EasyExcel.read(filename, class, innerListener).sheet().doRead();

        第三种,最常用的方式。EasyExcel.read(filename, class, listener).sheet().doRead();

        第四种,抽离sheet页,指定某个sheet页,没必要,直接sheet(number)即可。

ExcelReader reader = EasyExcel.read(filename, class, listener).doRead();
// 第几个sheet页。
ReadSheet readSheet = EasyExcel.readSheet(index).build(); 
reader.read(readSheet);

实体映射

        实体映射包含三个层级。

        类层级,一条数据对应1到N个实体对象。

        字段层级,一个字段对应一到N个单元格。

        字段值层级,字段值的校验,转换,格式化。

3.1 类层级

        无具体的实体类,只有数据,实体类变为了Map,每一行的数据放入到该Map中, Integer为列的顺序值,String为单元格的内容。

        一条记录对一个实体,最简单,最常见。指定标题对应的Class即可。sheetBuilder.head(Car.class);

        一条记录对应N个实体。思路如下

        第一步,使用1对1的关系,使用All接收。

        第二步,通过BeanUtils拷贝同名属性,将All对象分裂为多个。

// 定义ExcelDTO
public class TestExcelDTO{
    // 隶属于Test类
    @ExcelProperty(index = 0)
    private String id;
    // 隶属于TestExt类
    @ExcelProperty(index = 1)
    private String extProp;
}
// Test类
public class Test{
    private String id;
}
// TestExt类
public class TestExt{
    private String extProp;
}

// 解析完成之后,调用copyProperties方法,Apache common下的BeanUtils不会拷贝同名但类型不同的属性。
BeanUtils.copyProperties(test, testExcelDTO);
BeanUtils.copyProperties(testExt, testExcelDTO);

        一条记录对应一个实体的集合。通常是复杂表格,需要设置headRowNumber,思路如下:

        第一步,自定义Group注解

        第二步,使用1对1的关系,在该对象中使用Group注解,将其分组。

        第三步,解析该对象,将拥有相同Group的字段存放在JSONObject中,

        第四步,将这些JSONObject放入JSONArray中,将JSONArray转换为List

// 定义Group注解
public @interface Group{
    String value() default "";
}

// 定义ExcelDTO
public class TestExcelDTO{
    // 第一组
    @ExcelProperty(index = 0)
    @Group("one")
    private String idOne;
    // 第二组
    @ExcelProperty(index = 0)
    @Group("two")
    private String idTwo;
}

// 第三步,转换为Map<String, JSONObject>, key为组名称, value为该组中的每个对象,此处"one":{"id":"1"}; "two":{"id":"2"}
// 第四步,将这些对象都放入JSONObject中
ListIterator<JSONObject> listIterator = jsonArray.listIterator();
while(listIterator.hasNext()){
    // 转换为对象
    JSONObject current = iterator.next();
    Test test = current.toJavaObject(Test.class);
    // 后续保存test对象操作
}

3.2 字段层级

        通常一列对应一个字段,字段映射有两种方式。

        标题名称,在@ExcelProperty添加value属性。

        列的顺序,在@ExcelProperty添加index属性。从0开始。

        可以包含和排除某个字段,有两种策略,

  1. 默认不包含所有字段,只对添加@ExcelProperty的生效,需要在类上添加@ExcelIgnoreUnannotated。
  2. 默认包含所有字段,排除某个字段,需要在字段上添加@ExcelIgnore。

3.3 值层级

        单元格的内容,转换为字段的值。需要进行校验,类型转换,格式化。

        单元格的附加内容,转换为CellExtra对象,可以获取该对象的属性转换为字段的属性。例如超链接信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蜗牛旅行1899

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值