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

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的时候指定 不然是不会生效的。
--------------最后感谢大家的阅读,愿大家技术越来越流弊!--------------

在这里插入图片描述

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

  • 29
    点赞
  • 108
    收藏
    觉得还不错? 一键收藏
  • 31
    评论
对于复杂的Excel文件,你可以使用EasyExcel导入数据。EasyExcel是一个基于Java的开源库,可以用来读取、写入和处理Excel文件。 下面是一个示例代码,演示如何使用EasyExcel导入复杂的Excel文件: ```java // 导入相关的包 import com.alibaba.excel.EasyExcel; import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; // 创建一个数据模型类,用于存储导入的数据 public class ExcelData { private String column1; private String column2; // ... 其他列 // 省略getter和setter方法 } // 创建一个监听器类,用于处理导入的数据 public class ExcelListener extends AnalysisEventListener<ExcelData> { @Override public void invoke(ExcelData data, AnalysisContext context) { // 在这里处理每一行的数据 System.out.println("读取到数据:" + data.getColumn1() + ", " + data.getColumn2()); // ... 处理其他列 } @Override public void doAfterAllAnalysed(AnalysisContext context) { // 当所有数据都解析完成后,执行此方法 } } // 主程序 public class Main { public static void main(String[] args) { String filePath = "path/to/your/excel/file.xlsx"; // 使用EasyExcel进行导入 EasyExcel.read(filePath, ExcelData.class, new ExcelListener()).sheet().doRead(); } } ``` 在上面的示例中,你需要自己定义一个数据模型类(ExcelData),用来存储导入的数据。然后创建一个监听器类(ExcelListener),通过继承AnalysisEventListener来处理每一行的数据。最后,在主程序中使用EasyExcel的read方法来读取Excel文件并进行导入,你只需要将文件路径替换成你实际的Excel文件路径即可。 希望能帮到你!如果有更多问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 31
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值