0
点赞
收藏
分享

微信扫一扫

基于Poi的自编导入工具类--4.2版更新记录

juneyale 2022-01-28 阅读 171

前情回顾:https://blog.csdn.net/weixin_44718708/article/details/121683066

目录

一、提要

二、场景需求

三、新增功能说明

1. @DynamicRank

2. 重复性检测

         3. @Transform

四、优化说明

1. @ExcelNumberFormat

2. 起始标志

3. 提示信息列序号

五、GitHub地址


一、提要

GetExcelUtil4.2导入工具随实际工作应用场景需求变化更新优化的一次记录:

1. 增加@DynamicRank注解功能,支持获取动态表头及对应栏位。目前仅支持动态表头在固定表头之后的情况。

2. 增加支持重复性检测。

3. 增加@Transform注解功能,支持字段值的转换。

4. 优化:
     (1)注解数值格式(@ExcelNumberFormat)时,字段遇空值自动转化0
     (2)设置起始标志的情况下,校准位置改为以标题栏为准(取数据行前推一行)
     (3)异常信息提示的数字列序号校准为对应字母序号

二、场景需求

我们第四版工具仅支持实体类接收数据。

如图,A-I是固定栏位,后面红框里面的日期是根据实际到料信息编写的到料日期和到料数量,非固定栏位。

A-I列的数据可以定义相应个数、类型实体类字段进行获取,I列之后的动态栏位无法在同一个实体类内部定义获取。按原有4.1版本,直接使用List<String>获取动态表头,再根据动态表头List的长度使用List<Double>遍历获取表头对应列下的数据,在根据顺序将固定列数据、动态表头数据和表头列下数据组装起来即可。

按前面4.1版本的方法,代码量有点多,而且产生了二次遍历。于是新增了4.2版本,增加了获取动态栏位功能。

三、新增功能说明

1. @DynamicRank

/**
 * excel取值时,获取动态表头及本行(/列)对应表头栏位
 * 1. 注解作用于List类型字段
 * 2. titleRank表示表头所在行(/列),必填(横向表格代表行序,纵向表格表示列序)
 * 3. 从当前一直获取到最后一个表头及对应数据栏位
 * 4. 作用于实体类的最后一个字段,该字段后的其他字段将不会赋值
 * 5. enableDuplicateCheck复性检查:
 *      (1)依赖于实体类的equals方法的实现
 *      (2)会一定程度影响取值效率(看数据量),非必要不开启
 */
@Target(value = ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DynamicRank {
    int titleRank();
    boolean enableDuplicateCheck() default false;
}

@DynamicRank注解用于获取固定栏位之后的动态栏位,兼容横向和纵向表格。该注解作用于实体类中List类型的字段上,使用该注解的字段将认为是实体类的最后一个赋值字段。为确保成功获取动态栏位的值,务必保证用于取值的字段类型为List<DTO>。

@DynamicRank包含两个参数,titleRank和enableDuplicateCheck:

(1)titleRank为数字类型,表示表头所在栏(行/列,数字序号)。被@DynamicRank注解的字段将默认获取动态表头加表头对应栏位值,需要正确提供表头所在栏。被注解List<DTO>中DTO通常只包含两个字段,表头和栏位值。在给该DTO内字段赋值时,将忽略@DynamicRank注解。

(2)enableDuplicateCheck为boolean类型,表示是否开启数据重复性检测。值为true时,如果当前获取的DTO数据与其余已获取的DTO重复时,将抛出DataDuplicationException异常。判断重复规则将在后面说明。

接收Excel数据实体:

@Data
public class Test1DTO {
    ... ...
    @DynamicRank(titleRank = 2, enableDuplicateCheck = true)
    private List<Test2DTO> dataList;
    ... ...
}

接收动态栏位实体:

@Data
public class Test2DTO {
    @ExcelDateFormat(message = "日期格式必须为yyyy/MM/dd!")
    private String arriveDate;

    @ExcelNumberFormat(format = "#", message = "数量必须为正整数!")
    private Integer arriveQty;

    // 根据业务需要自定义equals
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof Test2DTO) {
            Test2DTO another = (Test2DTO) obj;
            return this.arriveDate.equals(another.getArriveDate());
        }
        return false;
    }
}

2. 重复性检测

4.1版本的取值方法是这样的:

 4.2版本是这样的:

 对比可以发现4.2版本增加了一个boolean类型参数:

加了一个默认不进行重复性检测的方法:

根据业务需要,对equals方法的重写(@Override是可以省略的,但建议保留,规范,防止拼写错误):

@Data
public class Test1DTO {
    @NotNull(message = "A不能为空!")
    private String a;
    @NotNull(message = "B不能为空!")
    private String b;
    @NotNull(message = "C不能为空!")
    private String c;
    @NotNull(message = "D不能为空!")
    private String d;
    @NotNull(message = "E不能为空!")
    private String e;
    @NotNull(message = "F不能为空!")
    private String f;
    @ValueLimit(limit = {"value1", "value2"}, message = "G只能为value1、value2")
    @Transform(expressions = {"value1 -> 1", "value2 -> 2"})
    private Integer g;
    private String h;
    private Integer i;
    @DynamicRank(titleRank = 2, enableDuplicateCheck = true)
    private List<Test2DTO> dataList;

    // 根据业务需要自定义equals
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof Test1DTO) {
            Test1DTO another = (Test1DTO) obj;
            return this.a.equals(another.getA())
                    && this.b.equals(another.getB())
                    && this.c.equals(another.getC())
                    && this.d.equals(another.getD())
                    && this.e.equals(another.getE())
                    && this.f.equals(another.getF())
                    && this.g.equals(another.getG());
        }
        return false;
    }
}

 补充一点,由图可以看出,4.2版本将方法中的栏位数量参数cellNum拿掉了,取值个数以实体类字段数为准,所以在定DTO字段时,需明确需要获取的栏位。

3. @Transform

为满足栏位获取的值转换的需求,4.2版本新增了@Transform注解功能:

/**
 * excel取值时,指定值变化成另一个值
 * 表达式:a->b
 */
@Target(value = ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Transform {
    String[] expressions();
}

@Transform的使用示例:

@Data
public class Test1DTO {
    ... ...
    @ValueLimit(limit = {"value1", "value2"}, message = "G只能为value1、value2")
    @Transform(expressions = {"value1 -> 1", "value2 -> 2"})
    private Integer g;
    ... ...
}

四、优化说明

1. @ExcelNumberFormat

@ExcelNumberFormat原先遇空值时抛出异常,改为遇到空的情况直接赋值0,优化用户体验。

2. 起始标志

起始标志读取位置从数据起始栏改为表头栏(读取数据起始栏),防止用户往模板插入数据时覆盖起始标志。

原先:

4.2版本:

3. 提示信息列序号

原本提示信息类似下面:

以数字提示列序,实际到Excel文档中,寻找第55列有点不友好,现将所有与列序有关的提示,序号对应到Excel中的字母列序。如下:

五、GitHub地址

https://github.com/BadGuy-Darren/MyExcelImportTool.git/4.2/

未打包成jar依赖包,打包教程网上有,很简单的。

举报

相关推荐

0 条评论