easyexcel-导入(读取)(read)-示例及核心部件
文章目录
- 导入(读取)(read)-示例及核心部件
- 导入(读取)(read)-核心部件
- EasyExcel(EasyExcelFactory) # 入口
- read() # read()方法用于构建workbook(工作簿)对象,new ExcelReaderBuilder()
- doReadAll()
- 这里选`XlsxSaxAnalyser`这个实现类吧
- 然后到这个类`XlsxRowHandler`,这里使用了策略模式,会根据xml不同的标签拿到对应的处理类来进行处理。
- 从上面代码找到`RowTagHandler`这个类,每解析了一行数据后都会进行处理
- 然后看endRow()方法
- 进入到dealData方法中
- 跟踪invoke()方法,选用ModelBuildEventListener这个实现类吧
- 进入到buildUserModel方法中
这块内容有点多,单独拉出来,要不看着太乱。
导入(读取)(read)-示例及核心部件
代码:
EasyExcel.read(file.getInputStream(), UserExcelVo.class, userListener).extraRead(CellExtraTypeEnum.MERGE).sheet(0) // 指定读取哪个sheet.headRowNumber(1) // 指定标题行.doRead(); // 执行读取
导入(读取)(read)-核心部件
以上面代码为例。
EasyExcel(EasyExcelFactory) # 入口
read() # read()方法用于构建workbook(工作簿)对象,new ExcelReaderBuilder()
public class EasyExcelFactory {public static ExcelReaderBuilder read() {return new ExcelReaderBuilder();}
}
public class ExcelReaderBuilder extends AbstractExcelReaderParameterBuilder<ExcelReaderBuilder, ReadWorkbook> {/*** Workbook*/private final ReadWorkbook readWorkbook;public ExcelReaderBuilder() {this.readWorkbook = new ReadWorkbook();}
}
doReadAll()
public class ExcelReaderBuilder extends AbstractExcelReaderParameterBuilder<ExcelReaderBuilder, ReadWorkbook> {public void doReadAll() {try (ExcelReader excelReader = build()) {excelReader.readAll();}}
}
public class ExcelReader implements Closeable {public void readAll() {excelAnalyser.analysis(null, Boolean.TRUE);}
}
public class ExcelAnalyserImpl implements ExcelAnalyser {
@Overridepublic void analysis(List<ReadSheet> readSheetList, Boolean readAll) {try {if (!readAll && CollectionUtils.isEmpty(readSheetList)) {throw new IllegalArgumentException("Specify at least one read sheet.");}analysisContext.readWorkbookHolder().setParameterSheetDataList(readSheetList);analysisContext.readWorkbookHolder().setReadAll(readAll);try {excelReadExecutor.execute();} catch (ExcelAnalysisStopException e) {if (LOGGER.isDebugEnabled()) {LOGGER.debug("Custom stop!");}}} catch (RuntimeException e) {finish();throw e;} catch (Throwable e) {finish();throw new ExcelAnalysisException(e);}}
}
这里选XlsxSaxAnalyser
这个实现类吧
public class XlsxSaxAnalyser implements ExcelReadExecutor {
@Overridepublic void execute() {for (ReadSheet readSheet : sheetList) {readSheet = SheetUtils.match(readSheet, xlsxReadContext);if (readSheet != null) {xlsxReadContext.currentSheet(readSheet);parseXmlSource(sheetMap.get(readSheet.getSheetNo()), new XlsxRowHandler(xlsxReadContext));// Read commentsreadComments(readSheet);// The last sheet is readxlsxReadContext.analysisEventProcessor().endSheet(xlsxReadContext);}}}
}
然后到这个类XlsxRowHandler
,这里使用了策略模式,会根据xml不同的标签拿到对应的处理类来进行处理。
public class XlsxRowHandler extends DefaultHandler {
static {CellFormulaTagHandler cellFormulaTagHandler = new CellFormulaTagHandler();XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_FORMULA_TAG, cellFormulaTagHandler);XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_CELL_FORMULA_TAG, cellFormulaTagHandler);XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.NS2_CELL_FORMULA_TAG, cellFormulaTagHandler);CellInlineStringValueTagHandler cellInlineStringValueTagHandler = new CellInlineStringValueTagHandler();XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_INLINE_STRING_VALUE_TAG, cellInlineStringValueTagHandler);XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_CELL_INLINE_STRING_VALUE_TAG, cellInlineStringValueTagHandler);XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.NS2_CELL_INLINE_STRING_VALUE_TAG, cellInlineStringValueTagHandler);CellTagHandler cellTagHandler = new CellTagHandler();XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_TAG, cellTagHandler);XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_CELL_TAG, cellTagHandler);XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.NS2_CELL_TAG, cellTagHandler);CellValueTagHandler cellValueTagHandler = new CellValueTagHandler();XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.CELL_VALUE_TAG, cellValueTagHandler);XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_CELL_VALUE_TAG, cellValueTagHandler);XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.NS2_CELL_VALUE_TAG, cellValueTagHandler);CountTagHandler countTagHandler = new CountTagHandler();XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.DIMENSION_TAG, countTagHandler);XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_DIMENSION_TAG, countTagHandler);XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.NS2_DIMENSION_TAG, countTagHandler);HyperlinkTagHandler hyperlinkTagHandler = new HyperlinkTagHandler();XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.HYPERLINK_TAG, hyperlinkTagHandler);XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_HYPERLINK_TAG, hyperlinkTagHandler);XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.NS2_HYPERLINK_TAG, hyperlinkTagHandler);MergeCellTagHandler mergeCellTagHandler = new MergeCellTagHandler();XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.MERGE_CELL_TAG, mergeCellTagHandler);XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_MERGE_CELL_TAG, mergeCellTagHandler);XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.NS2_MERGE_CELL_TAG, mergeCellTagHandler);RowTagHandler rowTagHandler = new RowTagHandler();XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.ROW_TAG, rowTagHandler);XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.X_ROW_TAG, rowTagHandler);XLSX_CELL_HANDLER_MAP.put(ExcelXmlConstants.NS2_ROW_TAG, rowTagHandler);}
}
从上面代码找到RowTagHandler
这个类,每解析了一行数据后都会进行处理
public class RowTagHandler extends AbstractXlsxTagHandler {
@Overridepublic void endElement(XlsxReadContext xlsxReadContext, String name) {XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder();RowTypeEnum rowType = MapUtils.isEmpty(xlsxReadSheetHolder.getCellMap()) ? RowTypeEnum.EMPTY : RowTypeEnum.DATA;// It's possible that all of the cells in the row are emptyif (rowType == RowTypeEnum.DATA) {boolean hasData = false;for (Cell cell : xlsxReadSheetHolder.getCellMap().values()) {if (!(cell instanceof ReadCellData)) {hasData = true;break;}ReadCellData<?> readCellData = (ReadCellData<?>)cell;if (readCellData.getType() != CellDataTypeEnum.EMPTY) {hasData = true;break;}}if (!hasData) {rowType = RowTypeEnum.EMPTY;}}xlsxReadContext.readRowHolder(new ReadRowHolder(xlsxReadSheetHolder.getRowIndex(), rowType,xlsxReadSheetHolder.getGlobalConfiguration(), xlsxReadSheetHolder.getCellMap()));xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext);xlsxReadSheetHolder.setColumnIndex(null);xlsxReadSheetHolder.setCellMap(new LinkedHashMap<>());}
}
然后看endRow()方法
public class DefaultAnalysisEventProcessor implements AnalysisEventProcessor {@Overridepublic void endRow(AnalysisContext analysisContext) {if (RowTypeEnum.EMPTY.equals(analysisContext.readRowHolder().getRowType())) {if (LOGGER.isDebugEnabled()) {LOGGER.debug("Empty row!");}if (analysisContext.readWorkbookHolder().getIgnoreEmptyRow()) {return;}}dealData(analysisContext);}
}
进入到dealData方法中
private void dealData(AnalysisContext analysisContext) {ReadRowHolder readRowHolder = analysisContext.readRowHolder();Map<Integer, ReadCellData<?>> cellDataMap = (Map)readRowHolder.getCellMap();readRowHolder.setCurrentRowAnalysisResult(cellDataMap);int rowIndex = readRowHolder.getRowIndex();int currentHeadRowNumber = analysisContext.readSheetHolder().getHeadRowNumber();boolean isData = rowIndex >= currentHeadRowNumber;// Last head columnif (!isData && currentHeadRowNumber == rowIndex + 1) {buildHead(analysisContext, cellDataMap);}// Now is datafor (ReadListener readListener : analysisContext.currentReadHolder().readListenerList()) {try {if (isData) {readListener.invoke(readRowHolder.getCurrentRowAnalysisResult(), analysisContext);} else {readListener.invokeHead(cellDataMap, analysisContext);}} catch (Exception e) {onException(analysisContext, e);break;}if (!readListener.hasNext(analysisContext)) {throw new ExcelAnalysisStopException();}}}
这里可以看到,每解析了一行数据后都会逐个调用监听器的invoke方法(包括easyexcel默认的监听器和我们自定义的监听器)
跟踪invoke()方法,选用ModelBuildEventListener这个实现类吧
进入到ModelBuildEventListener实现类,这个实现类是easyexcel自带的默认的监听器,这个监听器的主要作用是将excel的每行数据封装
public class ModelBuildEventListener implements IgnoreExceptionReadListener<Map<Integer, ReadCellData<?>>> {@Overridepublic void invoke(Map<Integer, ReadCellData<?>> cellDataMap, AnalysisContext context) {ReadSheetHolder readSheetHolder = context.readSheetHolder();if (HeadKindEnum.CLASS.equals(readSheetHolder.excelReadHeadProperty().getHeadKind())) {context.readRowHolder().setCurrentRowAnalysisResult(buildUserModel(cellDataMap, readSheetHolder, context));return;}context.readRowHolder().setCurrentRowAnalysisResult(buildNoModel(cellDataMap, readSheetHolder, context));}
}
进入到buildUserModel方法中
private Object buildUserModel(Map<Integer, ReadCellData<?>> cellDataMap, ReadSheetHolder readSheetHolder,AnalysisContext context) {ExcelReadHeadProperty excelReadHeadProperty = readSheetHolder.excelReadHeadProperty();Object resultModel;try {resultModel = excelReadHeadProperty.getHeadClazz().newInstance();} catch (Exception e) {throw new ExcelDataConvertException(context.readRowHolder().getRowIndex(), 0,new ReadCellData<>(CellDataTypeEnum.EMPTY), null,"Can not instance class: " + excelReadHeadProperty.getHeadClazz().getName(), e);}Map<Integer, Head> headMap = excelReadHeadProperty.getHeadMap();BeanMap dataMap = BeanMapUtils.create(resultModel);for (Map.Entry<Integer, Head> entry : headMap.entrySet()) {Integer index = entry.getKey();Head head = entry.getValue();String fieldName = head.getFieldName();if (!cellDataMap.containsKey(index)) {continue;}ReadCellData<?> cellData = cellDataMap.get(index);Object value = ConverterUtils.convertToJavaObject(cellData, head.getField(),ClassUtils.declaredExcelContentProperty(dataMap, readSheetHolder.excelReadHeadProperty().getHeadClazz(),fieldName, readSheetHolder), readSheetHolder.converterMap(), context,context.readRowHolder().getRowIndex(), index);if (value != null) {dataMap.put(fieldName, value);}}return resultModel;}
可以看到,先是通过反射创建对象,然后根据反射对各个对象赋值。
至此,excel的一行数据就被easyexcel默认的监听器解析成了对应的java对象,然后我们在自定义的监听器中就能拿到这个对象并进行处理了。
相关文章:
easyexcel-导入(读取)(read)-示例及核心部件
文章目录 导入(读取)(read)-示例及核心部件导入(读取)(read)-核心部件EasyExcel(EasyExcelFactory) # 入口read() # read()方法用于构建workbook(工作簿)对象,new ExcelReaderBuilder()doReadAll()这里选XlsxSaxAnalyser这个实现类吧然后到这个类XlsxRowHandler&…...

作业day3
请使用dup2 fgets printf 实现文件拷贝功能、 文件1: 复后文件: #define BUFFER_SIZE 1024 void file_copy(const char* src_file, const char* dest_file) { int src_fd, dest_fd; char buffer[BUFFER_SIZE]; // 打开源文件 src_fd open(s…...
第五节 MATLAB命令
本节的内容将提供常用的一些MATLAB命令。 在之前的篇章中我们已经知道了MATLAB数值计算和数据可视化是一个交互式程序,在它的命令窗口中您可以在MATLAB提示符“>>”下键入命令。 MATLAB管理会话的命令 MATLAB提供管理会话的各种命令。如下表所示:…...
Oracle 普通用户连接hang住处理方法
一、现象说明 $ sqlplus / as sysdbaSQL*Plus: Release 19.0.0.0.0 - Production on Wed Dec 18 16:49:19 2024 Version 19.11.0.0.0Copyright (c) 1982, 2020, Oracle. All rights reserved.Connected to: Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Pro…...

理解C++中的右值引用
右值引用,顾名思义,就是对一个右值进行引用,或者说给右值一个别名。右值引用的规则和左值一用一模一样,都是对一个值或者对象起个别名。 1. 右值引用和左值引用一样,在定义的同时必须立即赋值,如果不立即赋…...
02-机器学习-核心概念
以下是机器学习核心概念的详细梳理。 1. 机器学习三大范式 类型定义典型应用监督学习使用带标签的数据训练模型,预测未知数据的标签。分类(邮件垃圾过滤)、回归(房价预测)无监督学习从无标签的数据中发现隐藏模式或结…...
1.26 实现文件拷贝的功能
使用dup2fgetsprintf实现文件拷贝的功能。 #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <pthread.h> #in…...
ES6+新特性,var、let 和 const 的区别
在 JavaScript 中,var、let 和 const 都用于声明变量,但它们有一些重要的区别,主要体现在 作用域、可变性和提升机制 等方面。 1. 作用域(Scope) var: var 声明的变量是 函数作用域,也就是说,它…...

HarmonyOS简介:HarmonyOS核心技术理念
核心理念 一次开发、多端部署可分可合、自由流转统一生态、原生智能 一次开发、多端部署 可分可合 自由流转 自由流转可分为跨端迁移和多端协同两种情况 统一生态 支持业界主流跨平台开发框架,通过多层次的开放能力提供统一接入标准,实现三方框架快速…...

嵌入式C语言:结构体对齐
目录 一、对齐的原因 1.1. 硬件访问效率 1.2. 内存管理简化 1.3. 编译器优化 1.4. 代码示例 二、对齐规则 2.1. 基本数据类型对齐 2.2. 结构体成员对齐 2.3. 结构体整体对齐 2.4. 代码示例 三、对齐控制 3.1. 使用 #pragma pack 3.2. 使用 __attribute__((packed)…...

【Rust自学】15.5. Rc<T>:引用计数智能指针与共享所有权
喜欢的话别忘了点赞、收藏加关注哦(加关注即可阅读全文),对接下来的教程有兴趣的可以关注专栏。谢谢喵!(・ω・) 15.5.1. 什么是Rc<T> 所有权在大部分情况下都是清晰的。对于一个给定的值࿰…...

谈谈RTMP|RTSP播放器视频view垂直|水平反转和旋转设计
技术背景 我们在做RTMP|RTSP播放器的时候,有这样的技术诉求,有的摄像头出来的数据是有角度偏差的,比如“装倒了”,或者,图像存在上下或者左右反转,这时候,就需要播放器能做响应的处理ÿ…...

decison tree 决策树
熵 信息增益 信息增益描述的是在分叉过程中获得的熵减,信息增益即熵减。 熵减可以用来决定什么时候停止分叉,当熵减很小的时候你只是在不必要的增加树的深度,并且冒着过拟合的风险 决策树训练(构建)过程 离散值特征处理:One-Hot…...
GO语言 链表(单向链表
链表的前提 GO语言的链表类似于C语言的链表,它通过结构体和结构体指针实现。 结构体 GO语言定义结构体如下 type user struct {name stringage intnext *user } 结构体指针 结构体指针就是指向结构体的指针,我们在链表中会用到结构体指针实现链…...

Java:初识Java
初识Java 一.Java语言概述 1. Java是什么 Java是一种优秀的程序设计语言,它具有令人赏心悦目的语法和易于理解的语义。 不仅如此,Java还是一个有一系列计算机软件和规范形成的技术体系,这个技术体系提供了完整的用于软件开发和跨平台部署的…...

Spring WebSocket 与 STOMP 协议结合实现私聊私信功能
目录 后端pom.xmlConfig配置类Controller类DTO 前端安装相关依赖websocketService.js接口javascripthtmlCSS 效果展示简单测试连接: 报错解决方法1、vue3 使用SockJS报错 ReferenceError: global is not defined 功能补充拓展1. 安全性和身份验证2. 异常处理3. 消息…...

从0到1:C++ 开启游戏开发奇幻之旅(一)
目录 为什么选择 C 进行游戏开发 性能卓越 内存管理精细 跨平台兼容性强 搭建 C 游戏开发环境 集成开发环境(IDE) Visual Studio CLion 图形库 SDL(Simple DirectMedia Layer) SFML(Simple and Fast Multim…...

基于Flask的哔哩哔哩综合指数UP榜单数据分析系统的设计与实现
【Flask】基于Flask的哔哩哔哩综合指数UP榜单数据分析系统的设计与实现(完整系统源码开发笔记详细部署教程)✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 该系统旨在通过大数据分析和数据挖掘技术,结合Flask轻量级We…...

在php中怎么打开OpenSSL
(点击即可进入聊天助手) 背景 在使用php做一些项目时,有用到用户邮箱注册等,需要开启openssl的能力 在php系统中openssl默认是关闭状态的,在一些低版本php系统中,有的甚至需要在服务器终端后台,手动安装 要打开OpenSSL扩展,需要进行以下步骤 …...
oracle 分区表介绍
oracle 分区表介绍 Oracle 分区表是一个非常强大的数据库功能,可以将一个大的表分割成多个更小、更易管理的块(分区)。这种分区结构在处理大规模数据时非常有用,因为它能改善性能、简化维护和管理,并支持高效的数据存取…...

UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...

Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...

自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...

网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...