0.基础信息(需要导入的excel表格数据,接收类)
详见2.1文章阿里巴巴 Easyexcel 导入单张sheet (2.1指定字段对应表格列名)
1.ReadListener
package com.example.support.excel.listener;import cn.hutool.json.JSON;import cn.hutool.json.JSONUtil;import com.alibaba.excel.context.AnalysisContext;import com.alibaba.excel.metadata.data.ReadCellData;import com.alibaba.excel.read.listener.ReadListener;import com.alibaba.excel.util.ConverterUtils;import com.example.global.HttpHolder;import com.example.service.ExcelService;import com.example.support.entity.ExcelReadDTO;import lombok.Getter;import lombok.extern.slf4j.Slf4j;import java.util.ArrayList;import java.util.List;import java.util.Map;/** * @author LWB * @Description excel读取的监听器 * 有个很重要的点 ExcelReadListener监听器 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去 * 所以,如果需要传入spring管理的对象,要么按照文档中的说明,直接使用构造器传参进来,要么使用ThreadLocal线程级别的变量工具传参 * 实际应用中,可能会需要传入很多的spring管理的对象,或者其他上下文参数,遇到这种情况,建议使用ThreadLocal来传递参数,简单,便捷,无需重复修改构造器 * 如果是简单的传递个别上下文参数,也可以选用构造器传参的方式 */@Slf4jpublic class ExcelReadHeadListener implements ReadListener<ExcelReadDTO> { private ExcelService excelService; /** * 不适用构造器传入,使用threadLocal工具传入 * 适用于读取监听器中,需要使用多个上下文参数的情况 */ public ExcelReadHeadListener(){ this.excelService = HttpHolder.get("excelService",ExcelService.class); String p1 = HttpHolder.get("p1", String.class); String p2 = HttpHolder.get("p2", String.class); } /** * 构造器中传入spring管理的对象 * 适用于传入较少上下文参数的情况 * @param excelService */ public ExcelReadHeadListener(ExcelService excelService){ this.excelService = excelService; } /** * 每隔N条存储数据库,实际使用中可以1000条或者更多,然后清理cachedDataList ,方便内存回收 * 如果表格数据量很大,成千上万条,可以分批进行入库,数量不多的话,没必要做分配 */ private static final int BATCH_COUNT = 100; /** * 缓存的数据 */ private List<ExcelReadDTO> cachedDataList = new ArrayList<>(BATCH_COUNT); /** 终止读取,提示前端的信息 */ @Getter private String stopMsg; @Override public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) { //headMap:行索引为key ReadCellData对象为val log.info("解析到一条Map<Integer, ReadCellData<?>>类型头数据:{}", JSONUtil.toJsonStr(headMap)); //如果想转成成 Map<Integer,String>,有2种方案: key为列索引,val为标题单元格的string // 方案1: 不要implements ReadListener 而是 extends AnalysisEventListener // 方案2: 调用 ConverterUtils.convertToStringMap(headMap, context) 自动会转换 //本例使用方案2 log.info("解析到一条Map<Integer,String>类型头数据:{}", JSONUtil.toJsonStr(ConverterUtils.convertToStringMap(headMap, context))); } /** * 这个方法,每一条数据解析都会来调用 * @param data * @param context */ @Override public void invoke(ExcelReadDTO data, AnalysisContext context) { log.info("正在读取sheet:[{}]的数据:{}",context.readSheetHolder().getSheetName(), data.toString()); // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM /* if (cachedDataList.size() >= BATCH_COUNT) { //保存 excelService.saveData(); // 存储完成清理 list cachedDataList.clear(); }*/ } /** * 所有数据解析完成了 会来调用 * @param context */ @Override public void doAfterAllAnalysed(AnalysisContext context) { log.info("sheet:[{}]读取完成!",context.readSheetHolder().getSheetName()); //若进行分批处理,在读取完成后,还要检查下 cachedDataList 中是否还有剩余未入库的数据,因为如果没达到缓存最大值,invoke方法不会进行存储 //if(cachedDataList.size() > 0) excelService.saveData(); }}
2 .接口方法
/** * 读取excel的表头数据 * @param excelFile * @return */ @PostMapping("readHead") @SneakyThrows public Ret readHead(MultipartFile excelFile){ ExcelReadHeadListener excelReadListener = new ExcelReadHeadListener(excelService); EasyExcel.read(excelFile.getInputStream(), ExcelReadDTO.class,excelReadListener) .sheet()//指定读取哪个sheet .headRowNumber(2)//指定标题行(需要) .doRead();//执行读取 return Ret.success(); }
3.控制台输出
c.e.s.e.listener.ExcelReadHeadListener : 解析到一条Map<Integer, ReadCellData<?>>类型头数据:{"0":{"type":"STRING","stringValue":"字符串","rowIndex":0,"columnIndex":0},"1":{"type":"STRING","stringValue":"日期","rowIndex":0,"columnIndex":1},"2":{"type":"STRING","stringValue":"小数","rowIndex":0,"columnIndex":2}}c.e.s.e.listener.ExcelReadHeadListener : 解析到一条Map<Integer,String>类型头数据:{"0":"字符串","1":"日期","2":"小数"}c.e.s.e.listener.ExcelReadHeadListener : 解析到一条Map<Integer, ReadCellData<?>>类型头数据:{"0":{"type":"STRING","stringValue":"F1","rowIndex":1,"columnIndex":0},"1":{"type":"STRING","stringValue":"F2","rowIndex":1,"columnIndex":1},"2":{"type":"STRING","stringValue":"F3","rowIndex":1,"columnIndex":2}}c.e.s.e.listener.ExcelReadHeadListener : 解析到一条Map<Integer,String>类型头数据:{"0":"F1","1":"F2","2":"F3"}c.e.s.e.listener.ExcelReadHeadListener : 正在读取sheet:[Sheet1]的数据:ExcelReadDTO(str=33020220220514123x, time=Fri May 13 12:34:56 CST 2022, money=1.23)c.e.s.e.listener.ExcelReadHeadListener : 正在读取sheet:[Sheet1]的数据:ExcelReadDTO(str=330202202205141235, time=Fri May 13 13:34:56 CST 2022, money=1.24)c.e.s.e.listener.ExcelReadHeadListener : 正在读取sheet:[Sheet1]的数据:ExcelReadDTO(str=330202202205141234, time=Fri May 13 14:34:56 CST 2022, money=1.25)c.e.s.e.listener.ExcelReadHeadListener : 正在读取sheet:[Sheet1]的数据:ExcelReadDTO(str=330202202205141235, time=Fri May 13 15:34:56 CST 2022, money=1.26)c.e.s.e.listener.ExcelReadHeadListener : sheet:[Sheet1]读取完成!
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!