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

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

文章摘自: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));
}

点击进入,继续


         

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

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

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

@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了。



目录
相关文章
|
3天前
|
自然语言处理 数据可视化 数据挖掘
带你飞上云端,轻松解析数据——gopup库详细解析--包含安装库教程
本文介绍了Python库gopup,它是一个用于轻松爬取互联网数据的工具,简化了数据收集和处理的过程。文章提供了gopup的安装教程,特别强调了安装时需注意setuptools版本,并给出了PyCharm和命令行两种安装方法。gopup库能获取包括指数、百度和谷歌数据等多种类型的数据。文中还展示了如何使用gopup获取微博指数和豆瓣新片榜数据,并通过代码示例呈现数据和图表。此外,文章提醒了使用时的风险和部分接口的失效情况,并提供了库文档链接以供深入学习。gopup库适用于数据可视化和数据分析,是进行文本挖掘和自然语言处理项目的理想工具。
带你飞上云端,轻松解析数据——gopup库详细解析--包含安装库教程
|
3天前
|
存储 JSON 数据处理
从JSON数据到Pandas DataFrame:如何解析出所需字段
从JSON数据到Pandas DataFrame:如何解析出所需字段
14 1
|
3天前
|
存储 缓存 Linux
xenomai内核解析--xenomai与普通linux进程之间通讯XDDP(三)--实时与非实时数据交互
本文介绍了Xenomai中的XDDP(Xenomai Distributed Data Protocol)通信机制,XDDP用于实时和非实时进程之间的数据交换。XDDP在Xenomai内核中涉及的数据结构和管理方式,以及创建XDDP通道后的实时端和非实时端连接过程。
22 0
xenomai内核解析--xenomai与普通linux进程之间通讯XDDP(三)--实时与非实时数据交互
|
3天前
|
XML 存储 开发框架
c#教你网站数据轻松解析抓取,HtmlAgilityPack解析的奇妙之处
c#教你网站数据轻松解析抓取,HtmlAgilityPack解析的奇妙之处
11 0
|
3天前
|
JSON 安全 前端开发
解析FormData格式数据:Python实践指南
解析FormData格式数据:Python实践指南
17 1
|
3天前
|
数据采集 存储 大数据
Python爬虫:数据获取与解析的艺术
本文介绍了Python爬虫在大数据时代的作用,重点讲解了Python爬虫基础、常用库及实战案例。Python因其简洁语法和丰富库支持成为爬虫开发的优选语言。文中提到了requests(发送HTTP请求)、BeautifulSoup(解析HTML)、Scrapy(爬虫框架)、Selenium(处理动态网页)和pandas(数据处理分析)等关键库。实战案例展示了如何爬取电商网站的商品信息,包括确定目标、发送请求、解析内容、存储数据、遍历多页及数据处理。最后,文章强调了遵守网站规则和尊重隐私的重要性。
30 2
|
3天前
|
存储 文件存储 数据库
Flutter的持久化存储:使用SharedPreferences等进行数据存储的技术解析
【4月更文挑战第26天】 Flutter应用持久化存储主要使用SharedPreferences,适合存储简单数据类型。通过shared_preferences插件,可轻松进行数据读写。注意异步操作、数据类型限制和安全性,对于复杂需求,可选择SQLite或文件存储。
|
3天前
|
存储 编译器 C语言
C语言基础知识:数据在内存中的存储解析(整数,浮点数)
C语言基础知识:数据在内存中的存储解析(整数,浮点数)
|
3天前
|
SQL 关系型数据库 API
从API获取数据并将其插入到PostgreSQL数据库:步骤解析
使用Python处理从API获取的数据并插入到PostgreSQL数据库:安装`psycopg2`,建立数据库连接,确保DataFrame与表结构匹配,然后使用`to_sql`方法将数据插入到已存在的表中。注意数据准备、权限设置、性能优化和安全处理。
|
3天前
|
数据采集 XML 数据挖掘
使用Python打造爬虫程序之HTML解析大揭秘:轻松提取网页数据
【4月更文挑战第19天】本文介绍了HTML解析在爬虫技术中的重要性,并通过Python的BeautifulSoup库展示了如何解析和提取数据。文章涵盖了HTML文档结构、使用BeautifulSoup的基本方法,如`find_all()`、选择器(标签、类、ID选择器)以及提取文本、属性和链接。此外,还讨论了遍历和处理嵌套元素的技巧。

推荐镜像

更多