首页 >excel操作 > 内容

EasyExcel(一)导入excel的分析监听器

2023年2月14日 22:04

EasyExcel(一)导入excel的分析监听器

关于easyExcel的基本用法我就不在多说了,有需要的可以自己点击该链接去学习基本的使用,主要对这里面经常用到的一些监听器和拦截器讲一下

一、准备工作

这是我用的easyexcel版本

<dependency>    <groupId>com.alibaba</groupId>    <artifactId>easyexcel</artifactId>    <version>2.2.6</version></dependency>

二、讲解AnalysisEventListener< T>

  1. 监听器在有哪些方法
public abstract class AnalysisEventListener<T> implements ReadListener<T> {    // 这是监听器的构造方法,一般我们可以通过构造方法传入一些我们需要在解析excel时使用的数据    public AnalysisEventListener() {}    // 调用invokeHeadMap来获取表头数据    public void invokeHead(Map<Integer, CellData> headMap, AnalysisContext context) {        this.invokeHeadMap(ConverterUtils.convertToStringMap(headMap, context), context);    }// 获取表头数据    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {}// 读取条额外信息:批注、超链接、合并单元格信息等    public void extra(CellExtra extra, AnalysisContext context) {}// 在转换异常 获取其他异常下会调用本接口。抛出异常则停止读取。如果这里不抛出异常则 继续读取下一行。    public void onException(Exception exception, AnalysisContext context) throws Exception {throw exception;}    public boolean hasNext(AnalysisContext context) {return true;}}

​ 其中可以看到AnalysisEventListener 实现了 ReadListener

​ 然后看到ReadListener后 发现其中还有两个方法是AnalysisEventListener没有实现的,而且这两个方法还是很重要的

public interface ReadListener<T> extends Listener {    void onException(Exception var1, AnalysisContext var2) throws Exception;    void invokeHead(Map<Integer, CellData> var1, AnalysisContext var2);// 一行行读取表格内容    void invoke(T var1, AnalysisContext var2);    void extra(CellExtra var1, AnalysisContext var2);// 读取完成后的操作    void doAfterAllAnalysed(AnalysisContext var1);    boolean hasNext(AnalysisContext var1);}
  1. 实现监听器
// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去public class DemoDataListener extends AnalysisEventListener<DemoData> {    private static final Logger LOGGER = LoggerFactory.getLogger(DemoDataListener.class);    //每隔5条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收    private static final int BATCH_COUNT = 5;    List<DemoData> list = new ArrayList<DemoData>();    //假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。    private DemoDAO demoDAO;    public DemoDataListener() {        // 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数        demoDAO = new DemoDAO();    }    //如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来    public DemoDataListener(DemoDAO demoDAO) {        this.demoDAO = demoDAO;    }    // 这个每一条数据解析都会来调用    @Override    public void invoke(DemoData data, AnalysisContext context) {        list.add(data);        // 在这里可以做一些其他的操作  就考自己去拓展了        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM        if (list.size() >= BATCH_COUNT) {            saveData();            // 存储完成清理 list            list.clear();        }    }    // 所有数据解析完成了 都会来调用    @Override    public void doAfterAllAnalysed(AnalysisContext context) {        // 这里也要保存数据,确保最后遗留的数据也存储到数据库        // 当然也可以有很多其他操作 比如有些需要触发其他的 可以在这里调用        saveData();    }        // 加上存储数据库    private void saveData() {        demoDAO.save(list);    }    // 读取条额外信息:批注、超链接、合并单元格信息等    @Override    public void extra(CellExtra extra, AnalysisContext context) {        LOGGER.info("读取到了一条额外信息:{}", JSON.toJSONString(extra));        switch (extra.getType()) {            case COMMENT:                LOGGER.info("额外信息是批注,在rowIndex:{},columnIndex;{},内容是:{}", extra.getRowIndex(), extra.getColumnIndex(),                    extra.getText());                break;            case HYPERLINK:                if ("Sheet1!A1".equals(extra.getText())) {                    LOGGER.info("额外信息是超链接,在rowIndex:{},columnIndex;{},内容是:{}", extra.getRowIndex(),                        extra.getColumnIndex(), extra.getText());                } else if ("Sheet2!A1".equals(extra.getText())) {                    LOGGER.info(                        "额外信息是超链接,而且覆盖了一个区间,在firstRowIndex:{},firstColumnIndex;{},lastRowIndex:{},lastColumnIndex:{},"                            + "内容是:{}",                        extra.getFirstRowIndex(), extra.getFirstColumnIndex(), extra.getLastRowIndex(),                        extra.getLastColumnIndex(), extra.getText());                } else {                    Assert.fail("Unknown hyperlink!");                }                break;            case MERGE:                LOGGER.info(                    "额外信息是超链接,而且覆盖了一个区间,在firstRowIndex:{},firstColumnIndex;{},lastRowIndex:{},lastColumnIndex:{}",                    extra.getFirstRowIndex(), extra.getFirstColumnIndex(), extra.getLastRowIndex(),                    extra.getLastColumnIndex());                break;            default:        }    }        //在转换异常 获取其他异常下会调用本接口。抛出异常则停止读取。如果这里不抛出异常则 继续读取下一行。    @Override    public void onException(Exception exception, AnalysisContext context) {        // 如果是某一个单元格的转换异常 能获取到具体行号        // 如果要获取头的信息 配合invokeHeadMap使用        if (exception instanceof ExcelDataConvertException) {            ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception;            LOGGER.error("第{}行,第{}列解析异常", excelDataConvertException.getRowIndex(),                excelDataConvertException.getColumnIndex());        }    }}
// 在读的时候只需要new DemoDataListener 监听器传入就行了 EasyExcel.read(fileName, DemoData.class, new DemoDataListener())    // 需要读取批注 默认不读取    .extraRead(CellExtraTypeEnum.COMMENT)    // 需要读取超链接 默认不读取    .extraRead(CellExtraTypeEnum.HYPERLINK)    // 需要读取合并单元格信息 默认不读取    .extraRead(CellExtraTypeEnum.MERGE).sheet().doRead();

​ 简单描述一下这个的执行流程,最开始我们会传入DemoDataListener监听器,然后会每次解析一行的数据,解析完成无异常的情况下调用invoke方法,如果在该行出现异常就会调用onException方法,并且该行的数据会发生丢失。extra方法会在所有行都解析完后才回调用。并且需要在使用read的时候指定 不然是不会生效的。
--------------最后感谢大家的阅读,愿大家技术越来越流弊!--------------

在这里插入图片描述

--------------也希望大家给我点支持,谢谢各位大佬了!!!--------------


参考文章:https://blog.csdn.net/Zack_tzh/article/details/107952599

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时候联系我们修改或删除,在此表示感谢。

特别提醒:

1、请用户自行保存原始数据,为确保安全网站使用完即被永久销毁,如何人将无法再次获取。

2、如果上次文件较大或者涉及到复杂运算的数据,可能需要一定的时间,请耐心等待一会。

3、请按照用户协议文明上网,如果发现用户存在恶意行为,包括但不限于发布不合适言论妄图

     获取用户隐私信息等行为,网站将根据掌握的情况对用户进行限制部分行为、永久封号等处罚。

4、如果文件下载失败可能是弹出窗口被浏览器拦截,点击允许弹出即可,一般在网址栏位置设置

5、欢迎将网站推荐给其他人,网站持续更新更多功能敬请期待,收藏网站高效办公不迷路。

      



登录后回复

共有0条评论