EasyExcel导入excel的分析监听器

相关依赖(pom):

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

AnalysisEventListener<T>:

public abstract class AnalysisEventListener<T> implements ReadListener<T> {
    // 这是监听器的构造方法,一般我们可以通过构造方法传入一些我们需要在解析excel时使用的数据
    //(在这里,AnalysisEventListener<T>实现ReadListener<T>)
    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;}
}

相关常用方法:

// 有个很重要的点 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);
    }

Excel表中存在额外信息时

    // 读取条额外信息:批注、超链接、合并单元格信息等
    @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());
        }
    }
}

代码来源:EasyExcel(一)导入excel的分析监听器_Zack_tzh的博客-CSDN博客_easyexcel监听器

个人Demo:

public class DemoDateListener extends AnalysisEventListener<Demo>{
      private ststic final Logger LOGGER = LoggerFactory.getLogger(DemoDateListener.class);

      private static final BATCH_COUNT = 1;
      Demo demo = new Demo();
      int count = 0;
      boolean headFlag = false;//表头标识
      boolean headFlag1 = false;//表头标识
      boolean headFlag2 = false;//数字标识

      private DemoService demoService;
      public DemoListener(DemoService demoservice){
        this.demoService=demoService
      }
      public void invoke(Demo data, AnalysisContext context) {

        System.out.println(JSON.toJSONString(data));
        if (data.getTest() != null) {
            if (data.getTest().equals("实验对象"))
                headFlag = true;
        }
        if (headFlag && headFlag1) {
            demo = data;
            demo.setExcelType("2");
            insertData();
        }
        if (data.getTest() != null) {
            if (data.getTest().equals("实验对象") || data.getTest().equals("实验对象"))
                headFlag1 = true;
        }
    }
       public void doAfterAllAnalysed(AnalysisContext context) {
        LOGGER.info("所有数据解析完成!");
       }
      private void insertData() {
    }
}

按照需求不同,建立对应的listener。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容