首页 > 其他分享 >EasyExcel低版本中数据行中包含空数据会跳过导致数据对应不上的问题解析

EasyExcel低版本中数据行中包含空数据会跳过导致数据对应不上的问题解析

时间:2022-11-13 08:22:13浏览次数:79  
标签:低版本 EasyExcel analysisContext readSheet void reader 数据 public

文章摘自:https://blog.csdn.net/caijwjava/article/details/100855361

实战

1、导入一个相关依赖即可

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

2、读取(上传)Excel文件,使用上非常的简单,只要几行代码。

public class EasyExcelDemo {

public static void main(String[] args) {
String path = "E:\\tmp\\demo.xlsx";
// 自定义读取每一行数据的事件监听
ReadListen readListen = new ReadListen();
// 开始读取Excel数据
ExcelReader reader = EasyExcel.read(path, readListen).build();
// 读取第一个sheet,readSheet默认是读取第一个,可以自定义
ReadSheet readSheet = EasyExcel.readSheet().build();
// 开始读取数据
reader.read(readSheet);
// 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的
reader.finish();
}

}

3、自定义ReadListen,主要是为了装数据,方便获取和使用,具体怎么调到这个方法的,以及出现的问题点在哪,往下走。。。

public class ReadListen<T> extends AnalysisEventListener<T> {

private List<T> sheetData = new ArrayList<>(10);

@Override
public void invoke(T t, AnalysisContext analysisContext) {
sheetData.add(t);
System.out.println(t);
}

@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
// Excel数据解析完成后,想要实现的业务逻辑
System.out.println("excel data resolve finish!!!");
}
}

4、开始源码分析,easyexcel怎么读取数据,以及问题点分析解决!
4.1 当调用reader.read(readSheet);时,进入

public ExcelReader read(ReadSheet readSheet) {
checkFinished();
// 开始进入解析sheet
excelAnalyser.analysis(readSheet);
return this;
}

我们只要分析excelAnalyser.analysis(readSheet);,进入继续

analysisContext.currentSheet(excelExecutor, readSheet);
try {
// 真正解析sheet表格的地方
excelExecutor.execute();
} catch (ExcelAnalysisStopException e) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Custom stop!");
}
}
// 这个是在sheet表格解析完成后回调的方法,参考前面自定义的ReadListen
analysisContext.readSheetHolder().notifyAfterAllAnalysed(analysisContext);

点击进入

@Override
public void execute() {
parseXmlSource(sheetMap.get(analysisContext.readSheetHolder().getSheetNo()),
// 这个就是我们真正关心的地方,每行解析完成后会执行的操作
new XlsxRowHandler(analysisContext, stylesTable));
}

点击进入,继续

public XlsxRowHandler(AnalysisContext analysisContext, StylesTable stylesTable) {
// 这个是每个单元格执行的一些操作,包括回调之类的
this.cellHandlers = XlsxHandlerFactory.buildCellHandlers(analysisContext, stylesTable);
// ...
}

点击进去,这时我们会注意到notifyEndOneRow,这个正是需要关注的点,继续

@Override
public void endHandle(String name) {
analysisContext.readSheetHolder()
// 这个就是每一行表格数据解析完成后会触发的回调
.notifyEndOneRow(new EachRowAnalysisFinishEvent(rowResultHandler.getCurRowContent()), analysisContext);
rowResultHandler.clearResult();
}

点击继续,看看里面做了什么操作。。。

@Override
public void notifyEndOneRow(AnalysisFinishEvent event, AnalysisContext analysisContext) {
// ...to do something

if (rowIndex >= headRowNumber) {
// Now is data
for (ReadListener readListener : analysisContext.currentReadHolder().readListenerList()) {
try {
// 真正触发回调的地方,这里会有多个监听,包括我们前面自定义的ReadListen
readListener.invoke(readRowHolder.getCurrentRowAnalysisResult(), analysisContext);
// ...

现在慢慢的明朗了整个读取流程,在debug之后,看看每个Listenner之后,找到一个ModelBuildEventListener,这个就是Excel数据转换的Listenner,也就是前面说到的会导致Excel表格列数据为空的时候,导致位置发生变化的地方,具体看看这里做了什么?

private Object buildStringList(Map<Integer, CellData> cellDataMap, ReadHolder currentReadHolder,
AnalysisContext context) {
// 这里是为了兼容一些旧的代码,做了一个映射,是返回list还是map
if (context.readWorkbookHolder().getDefaultReturnMap()) {
// ...省略不需要关心的代码
return map;
} else {
List<String> list = new ArrayList<String>();
for (Map.Entry<Integer, CellData> entry : cellDataMap.entrySet()) {
// ...省略不需要关心的代码
return list;
}
}

在进入context.readWorkbookHolder().getDefaultReturnMap())的时候,在新的版本中默认是true,这样返回map的时候就不会出现前面说的列数据对不上的问题。下面看看返回Map和List有什么区别。

使用List返回的数据示例:

使用Map返回的数据示例:

通过对比,我们就很快可以发现使用List缺少了序号而导致无法把数据对应上,而使用Map的时候,key就是序号,value是我们需要的单元格数据。
那么,这个开关在哪里呢?细心的应该看到了,如果你也存在这个问题,又不想升级版本等,可以使用一个开关设置成Map再转换成自己需要的List集合即可。或者说不想用Map,那么都可以自己设置。

public static void main(String[] args) {
// ...省略
ReadSheet readSheet = EasyExcel.readSheet().build();
// 具体的设置开关,新的的版本中默认true
reader.analysisContext().readWorkbookHolder().setDefaultReturnMap(true);
// 开始读取数据
reader.read(readSheet);
// 这里千万别忘记关闭,读的时候会创建临时文件,到时磁盘会崩的
reader.finish();
}

在前面的代码中,添加一句reader.analysisContext().readWorkbookHolder().setDefaultReturnMap(true);,注意这里默认就是true,可以设置为false,返回的数据就是list了。

标签:低版本,EasyExcel,analysisContext,readSheet,void,reader,数据,public
From: https://www.cnblogs.com/lingyejun/p/16885362.html

相关文章

  • MongoDB导入导出备份数据
    需要提前安装mongodb-database-tools参考:centos离线安装mongodb-database-tools导出数据常用的导出有两种:mongodump和mongoexport,两种方式的区别:1、mongodump导出的文件......
  • 第一百零八篇:最常用的基本数据类型(Number,String类型)
    好家伙, 1.Number类型从名称中我们可以得出,这是一个存放数值的类型,不同的数值类型相应地也有不同的数值字面量格式number类型可以储存不同进制的数(不常用就是了)......
  • C语言数据类型转型没有搞明白的点。
    程序员面试宝典第30页,请专家指导下,感谢!1#include<stdio.h>2#defineproduct(x)((x)*(x))3intmain(intargc,char**argv){4printf("Hello,World!\n......
  • 【数据结构-图】图的定义
    目录1邻接矩阵2邻接表3带权无向图4带权有向图1邻接矩阵#defineMAX50typedefcharVertexType;typedefintEdgeType;typedefstruct{VertexTypeVex[MA......
  • easyexcel 2.2.6 新版本以列表的形式读取 Excel
    使用步骤:注:讲述使用EasyExcel的读取Excel数据列表的案例,项目基于springboot+maven模式。1、引入EasyExcel依赖包,文章以easyexcel2.2.6为基础。<dependenc......
  • Redis几种数据结构的存储方式
    一、使用stringRedisTemplate向redis中存储List数据取出privateStringRedisTemplatestringRedisTemplate;这里的RedisConstants.CACHE_SHOP_TYPE是"cache:shop-ty......
  • Django更换数据库和迁移数据方案
    前言双十一光顾着买东西都没怎么写文章,现在笔记里还有十几篇半成品文章没写完…今天来分享一下Django项目切换数据库和迁移数据的方案,网络上找到的文章方法不一,且使......
  • ffmpeg一些笔记: 代码调试数据
    1.AAC,MP3他的解码数据格式不支持,程序中给的是这个AV_SAMPLE_FMT_FLTP, Screen-Cpature-Recoder的codec-id为AV_CODEC_RAW_VIDEO,virtual-audio-capturer的codec-id为AV_......
  • Spring 事务(测试)--在这个笔记中记录的是没有添加事务,数据库返回的效果。
    第5章Spring事务(测试)--在这个笔记中记录的是没有添加事务,数据库返回的效果。1.首先搞两张表,商品表和订单表举例:购买商品trans_sale项目本例要实现购买商品,模拟用......
  • 谈一谈响应式数据
    响应式数据是某个数据发生变化时,页面依赖这个数据的位置会自动更新视图;响应式数据的原理:vue在初始化vue实例时,会遍历data数据,通过Object.defineProperty给每......