『Java』EasyExcel基础——读

在这里插入图片描述

前言

永远相信美好的事情即将发生


背景

前段时间在爬取网站数据的时候遇到这样一个问题,有一个数据源,因为数据量比较大,因此没有在页面上展示,只提供了一个下载的按钮,现在需要每天将这个下载的Excel数据解析并写入数据库

开始

对于这个需求,其实一开始我是拒绝的,因为前段时间爬取数据的时候一直遵循 接口 >>> Postman >>> 代码 这套逻辑一气呵成

在这里插入图片描述
现在突然冒出个Excel,这套逻辑就完美的出现了瑕疵,当然作为一名合格的 Progrmmer Porgram Progarm

在这里插入图片描述
诶,算了,作为一名合格的菜鸟程序员,吾等安能轻言放弃?于是我开始疯狂的分析页面接口,分析页面的相关JS,在论坛找寻前辈们的足迹,逐步寻找着数据的蛛丝马迹。终于皇天不负有心人,在经过一早上的奋斗后,我终于圆满的放弃了

在这里插入图片描述

最终还是决定老老实实去解析Excel

踩坑

最开始的时候是准备使用POI解析的,但是写着写着发现了一个很严峻的问题,每次下载的Excel表头都可能不一样,打个比方,这一次下载的Excel表头是 a,b,d,而下一次的表头就有可能是c,d,但它们都来自 a,b,c,d 这个总的表头字段列表

在这里插入图片描述
而且Excel的字段还比较多,大概30来个,用POI的话还需要一个一个去判断(可能是因为我太菜了,没想到啥好方法),旁边的大佬看了我的屏幕一样,顿时被我 switch 后面的 30多个 case 震惊的体无完肤,立刻流露出了一副看傻子的眼神

大佬问我为什么不考虑一下 EasyExcel ,我不由的问道:“什么Excel?”,大佬:“EasyExcel ”,我:“Easy什么?”,大佬:“EasyExcel ”,我:“EasyExcel?”,大佬:“Easy什么?”

爬坑

第一步还是导入相应的Pom依赖,建议各位先安装一个 Maven Helper 插件,方便查看项目中所有引入的依赖以及可能会引起冲突的地方
在这里插入图片描述
就是这个,顺便附上自己用的版本,POI建议使用 3.1.7 以上的版本,截至目前没有发现什么问题

在这里插入图片描述

EasyExcel建议使用 2.2.3的版本,截至目前没有发现什么问题,建议不要使用 1.x 的版本,需要特别注意的是 EasyExcel 和 POI 之间的版本对应关系比较玄学,目前也没发现什么规律,现在用的这一套目前是没有什么问题的
在这里插入图片描述
引入依赖后就要开始开(zhao)发(chao)了

在这里插入图片描述
首先是实体类的设置,实体类字段中最核心的设置只有两个:@ExcelIgnore和@ExcelProperty(“xxx”),前者表示实体类的该字段 不是 由Excel中的某个字段解析而来,而后者则相反,表示该字段由Excel中的 xxx
表头下的数据解析而来

/**
 * @description:示例代码
 * @author: King
 * @date: 2020/6/25 16:20
 */
@Data
public class DemoEntity {
    
    @ExcelIgnore
    private int id;

    @ExcelProperty("姓名")
    private String name;

    @ExcelProperty("年龄")
    private int age;
}

其次是EasyExcel中最为核心的部分,监听器类,以在下有限的知识储备去理解,这个监听器已经封装好了完整的Excel解析过程,用户只需要新建一个类去继承 AnalysisEventListener ,重写其中的invoke()方法便可自动解析,这里贴上 EasyExcel 的官方使用手册

/**
 * @description:EasyExcel EasyExcel监听器
 * @author: King
 * @date: 2020/6/24 10:05
 */
public class ExcelDataListener extends AnalysisEventListener {
    /**
     * 存储最终解析的数据,用于最终的入库操作
     */
    List<T> list = new ArrayList<>();

	/**
     * 这里写你的业务Dao,切记EasyExcel无法通过 @AutoWired 注入 Dao,强制注入会报空指针
     */
    private TestDAO testDAO;
    public ExcelDataListener () {
        testDAO= new TestDAO();
    }
    /**
     * 解析Excel的核心方法
     * @param o
     * @param analysisContext
     */
    @Override
    public void invoke(Object obj, AnalysisContext analysisContext) {
    /**
     *在此处已完成了Excel的解析,obj可以理解为由每一行数据所生成的一个实体类对象,该对象中的属性值已由Excel中的字段映射完成,可通过打印obj进行校验
     */
     // System.out.println((实体类)obj);
     list.add((实体类)obj)
    }
	/**
     * 解析完Excel的后续操作,一般用于最后的执行入库操作
     * @param o
     * @param analysisContext
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    // 用户在 dao 中自定义的 save 方法
	 testDAO.save(list);
    }

这样就已经完成Excel的解析工作,那么现在就剩下最后一步操作了
在这里插入图片描述

/**
 * 定义InputStream流对象,该对象可由本地Excel文件读取,也可由下载接口返回的流数据转化而来
 * 1.若为本地文件,则可用new FileInputStream(文件路径)转化
 * 2.若为下载接口返回的流数据,则可用response.getEntity().getContent()方法转化
 **/
InputStream in = null;
// 若为接口返回的流数据
in = response.getEntity().getContent();
// 若为本地文件
in = new FileInputStream(文件路径);

ExcelReader excelReader = null;
try {
    excelReader = EasyExcel.read(in, 实体类.class, new ExcelDataListener()).build();
    ReadSheet readSheet = EasyExcel.readSheet(0).build();
    excelReader.read(readSheet);
} finally {
    if (excelReader != null) {
        excelReader.finish();
    }

至此一次完整的 Excel 解析过程貌似就完成了

在这里插入图片描述

那么如果实体类的部分属性值不是来自于Excel解析,需要在业务层去设置,那该如何处理呢

在这里插入图片描述

对解析器进行小小的处理即可

/**
 * @description:EasyExcel EasyExcel监听器
 * @author: King
 * @date: 2020/6/24 10:05
 */
public class ExcelDataListener extends AnalysisEventListener {
    /**
     * 存储最终解析的数据,用于最终的入库操作
     */
    List<T> list = new ArrayList<>();
	/**
     * 这里写你的业务Dao,切记EasyExcel无法通过 @AutoWired 注入 Dao,强制注入会报空指针
     */
    private TestDAO testDAO;
    public ExcelDataListener () {
        testDAO= new TestDAO();
    }
    
	// 假设gender字段是在业务层中设置
	public static String gender;
	// 添加设置参数的方法,因为静态方法会先于构造函数执行,因此可以用于在创建对象前获取业务层中的数据
	public static void setParam(Map<String, String> map) {
        gender = map.get("gender");
    }
	
    /**
     * 解析Excel的核心方法
     * @param o
     * @param analysisContext
     */
    @Override
    public void invoke(Object obj, AnalysisContext analysisContext) {
    /**
     *在此处将获取的数据写入实体类对象
     */
     XxxEntity entity = new XxxEntity;
     entity.setGender(gender);
     // System.out.println((实体类)obj);
     list.add((实体类)obj)
    }
	/**
     * 解析完Excel的后续操作,一般用于最后的执行入库操作
     * @param o
     * @param analysisContext
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    // 用户在 dao 中自定义的 save 方法
	 testDao.save(list);
    }

相应的业务层也要进行修改

InputStream in = null;
// 若为接口返回的流数据
in = response.getEntity().getContent();
// 若为本地文件
in = new FileInputStream(文件路径);

ExcelReader excelReader = null;
try {
    Map<String,String> param = new HashMap<>();
    param.put("gender","18");
   
    ExcelDataListener excelDataListener = new ExcelDataListener();
    setParam(param);

    excelReader = EasyExcel.read(dataFinal, SycmFullProductRankingEntity.class, excelDataListener).build();
} finally {
    if (excelReader != null) {
        excelReader.finish();
    }

这样就算完成了一次完整的Excel解析

在这里插入图片描述

特别注意

如果解析后的实体类对象所有属性值均为null,可能是因为Excel的表头不是在第一行,因此需要手动设置表头所在的行数,将EasyExcel.readSheet(0).build() 修改为 EasyExcel.readSheet(0).headRowNumber(表头所在行数).build() 即可

总结

EasyExcel的上手难度相比POI来说比较低,代码量比较少,对于新手比较友好,它的功能也远远不止Excel读取这一简单操作,后续我也将会持续对EasyExcel进行学习。

受制于本人的水平,如果大佬们在博文中发现有什么错误或需要改进的地方,也希望大佬们能及时留言,万分感谢!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

3价Fe离子

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

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

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

打赏作者

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

抵扣说明:

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

余额充值