EasyExcel3.1.1版本上传文件忽略列头大小写

1、背景

项目中使用easyExcel3.1.1版本实现上传下载功能,相关数据DTO以

@ExcelProperty(value = "dealer_gssn_id")

形式规定其每一列的名称,这样的话easyExcel会完全匹配对应的列名,即用户上传文件时,列名写成Dealer_gssn_id,那么对应的DTO不会给对应字段赋值。

现在客户需要实现此项需求,忽略列名大小写,延伸出来以下内容。

2、调研

最开始以为easyExcel有现成的一些方法或者重写类能实现此项功能,但是后来查看源码,发现没办法重写。具体的debug流程不再此细说,主要看一下DefaultAnalysisEventProcessor类:

该类中dealData方法,调用buildHead方法,在该方法中141行使用的equals方法用来比较DTO中value名字与excel上传的列名是否匹配,然而这个类的调用方式是new出来的,这就代表即使我们重写了DefaultAnalysisEventProcessor 类,也没办法执行到我们重写的方法,所以这条路走不通了。

除此之外就只能靠我们自己发散思维去想想该怎么做了。

通过打断点看数据,我们其实能在重写AnalysisEventListener的类中看到invokeHeadMap类中是所有的列头数据,invoke方法中既有列头数据,也有具体的值信息,但是怎么和我们定义的DTO做绑定,这也是个麻烦的事情,可以做,但是想想就比较复杂,可能需要写一大堆的if else,代码也不美观,特别是DTO中字段六七十个,而且不止这一个文件要改,这样做起来麻烦且费时。

那就接着想想其他可能性。

比如在我们上传文件时,在处理数据之前写个公共的util呢?这个util功能会把excel列头拿出来都转化为小写,再重新生成一个MultipartFile文件对象呢?这样,每个上传excel功能我们手动调用一下是不是代码侵入量小一些呢?

所以接下来开始硬刚这部分操作,修修补补,起码能实现上述需求:

这个util可以直接使用,但是每个人场景不同可能需要略微修改,这个util只针对sheet 1中简单的区分列头与数据,比较复杂的excel还需要按实际情况修改:


import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;public class FileUtilsForHeaderLowerCase {public static MultipartFile convertToLowerCase(MultipartFile file) throws Exception {// 临时存储读取到的数据List<List<String>> headerData = new ArrayList<>();List<List<String>> rowData = new ArrayList<>();ExcelTypeEnum excelTypeEnum = null;if (file.getOriginalFilename().toLowerCase().endsWith("csv")) {excelTypeEnum = ExcelTypeEnum.CSV;}else if(file.getOriginalFilename().toLowerCase().endsWith("xlsx")) {excelTypeEnum = ExcelTypeEnum.XLSX;}else if(file.getOriginalFilename().toLowerCase().endsWith("xls")){excelTypeEnum = ExcelTypeEnum.XLS;}// 读取原始文件内容try (InputStream inputStream = file.getInputStream()) {// 使用EasyExcel读取原始文件数据EasyExcel.read(inputStream, new AnalysisEventListener<>() {@Overridepublic void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {// 转换为小写并存储列头List<String> headers = new ArrayList<>();headMap.forEach((k, v) -> headers.add(ObjectUtils.isEmpty(v) ? "" : v.toLowerCase()));headerData.add(headers);}@Overridepublic void invoke(Object data1, AnalysisContext context) {Map<Integer, String> stringData = (Map<Integer, String>) data1;List<String> list = new ArrayList<>();stringData.forEach((key, value) -> list.add(ObjectUtils.isEmpty(value) ? "" : value));rowData.add(list);}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {// 所有数据解析完成后调用此方法,这里不做什么}}).excelType(excelTypeEnum).sheet().doRead();// 创建一个字节数组输出流来存储Excel内容ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();// 使用EasyExcel创建ExcelWritertry (ExcelWriter excelWriter = EasyExcel.write(byteArrayOutputStream).excelType(excelTypeEnum).build()) {// 创建写入的sheet页WriteSheet writeSheet = EasyExcel.writerSheet().build();// 写入表头if (!headerData.isEmpty()) {excelWriter.write(headerData, writeSheet);}// 写入数据if (!rowData.isEmpty()) {excelWriter.write(rowData, writeSheet);}}// 将字节数组输出流转换为输入流InputStream newInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());// 使用转换后的输入流创建一个新的MultipartFilereturn new MockMultipartFile("file",file.getOriginalFilename(),file.getContentType(),newInputStream);}}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/725933.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

利用websocket +定时器简易的实现一个网络聊天室

其实原理非常简单,就是客户端用户通过websoket来连接websocket服务端。然后服务端,收集每个用户发出的消息, 进而将每条用户的消息通过广播的形式推送到每个连接到服务端的客户端。从而实现用户的实时聊天。 // TODO : 我主要是讲一下实现思路。并未完善其功能。 1.后端 依赖 …

Java面试(2)之 多线程

线程池的结构及原理 一, 线程池的参数: corePoolSize: 线程池核心线程大小; 默认情况下这些线程不会被销毁,除非设置了allowCoreThreadTimeOut maximumPoolSize: 线程池最大线程数量 keepAliveTime: 空闲线程存活时间 TimeUnit: 空闲线程存活时间及单位 workQueue: 工作队…

使用数据库实现增删改查

#include<myhead.h>//定义添加数据函数int do_add(sqlite3 *ppDb) {//1.准备sql语句,输入要添加的信息int add_numb; //工号char add_name[20]; //姓名char add_sex[10]; //性别double add_score; //工资printf("请输入要添加的工号:")…

mysql数据库创建与删除

可以使用show databases语句来查看当前所有存在的数据库。 mysql> show databases; Database ---------- information_schema mysql performance_schema sys其中&#xff0c;mysql用来描述用户访问权限。 创建数据库 创建数据库可以使用create database命令。 例如&#…

恢复IDEA误删除的git提交,提交被删除,尝试恢复提交

​​​​​​ dgqDESKTOP-JRQ5NMD MINGW64 /f/IdeaProjects/workspace/spzx-parent ((8bb112e...)) $ git reflog 8bb112e (HEAD, origin/master, master) HEAD{0}: checkout: moving from master to 8bb112e5ac18dfe4bbd64adfd06363e46b609f21 8bb112e (HEAD, origin/master, …

微信小程序开发系列(二十一)·wxml语法·setData()修改数组类型数据(增加、修改、删除)

目录 1. 新增数组元素 方法一&#xff1a;push&#xff08;&#xff09; 方法二&#xff1a;concat() 方法三&#xff1a;ES6中的扩展运算符 ... 2. 修改数组元素 样式一&#xff1a;数字 样式二&#xff1a;元素 3. 删除数组元素 方法一&#xff1a;splice&#x…

vue2源码分析-vue入口文件global-api分析

文章背景 vue项目开发过程中,首先会有一个初始化的流程,以及我们会使用到很多全局的api,如 this.$set this.$delete this.$nextTick,以及初始化方法extend,initUse, initMixin , initExtend, initAssetRegisters 等等那它们是怎么实现,让我们一起来探究下吧 源码目录 global-…

Windows下 OracleXE_21 数据库的下载与安装

Oracle 数据库的下载与安装 数据库安装包下载数据库安装访问数据库进行测试Navicat连接数据库 1. 数据库安装包的下载 1.1 下载地址 Oracle Database Express Edition | Oracle 中国 1.2 点击“下载 Oracle Database XE”按钮&#xff0c;进去到下载页面&#xff08;选择对…

Stable diffusion零基础课程

该课程专为零基础学习者设计&#xff0c;旨在介绍和解释稳定扩散的基本概念。学员将通过简单易懂的方式了解扩散现象、数学模型及其应用&#xff0c;为日后更深入的科学研究和工程应用打下坚实基础。 课程大小&#xff1a;3.8G 课程下载&#xff1a;https://download.csdn.ne…

灵魂指针,教给(一)

欢迎来到白刘的领域 Miracle_86.-CSDN博客 系列专栏 C语言知识 先赞后看&#xff0c;已成习惯 创作不易&#xff0c;多多支持&#xff01; 一、内存和地址 1.1 内存 在介绍知识之前&#xff0c;先来想一个生活中的小栗子&#xff1a; 假如把你放在一个有100间屋子的酒店…

第三讲 汇编初步 课程随手记

一、寄存器 32位CPU通用寄存器如下图所示&#xff1a; 因为教材依照的是32位CPU寄存器&#xff0c;而我安装的是64位寄存器&#xff0c;所以找了一下64位的寄存器的资料 PS&#xff1a;一般来说&#xff0c;Intel处理器字节存储顺序为小端法存储&#xff0c;是指数据的高字节保…

基于Skywalking开发分布式监控(四)一个案例

上一篇我们简单介绍了基于SkyWalking自定义增强的基本架构&#xff0c;即通过把Trace数据导入数据加工模块进行加工&#xff0c;进行持久化&#xff0c;并赋能grafana展示。 现在我们给出一个例子&#xff0c;对于量化交易系统&#xff0c;市场交易订单提交&#xff0c;该订单…

关于springboot一个接口请求后,主动取消后,后端是否还在跑

1、最近在思考一个问题&#xff0c;如果一个springboot的请求的接口比较耗时&#xff0c;中途中断该请求后&#xff0c;则后端服务是否会终止该线程的处理&#xff0c;于是写了一个demo RequestMapping(value "/test", method RequestMethod.GET)public BasicResul…

云消息队列 Confluent 版正式上线!

作者&#xff1a;阿里云消息队列 前言 在 2023 年杭州云栖大会上&#xff0c;Confluent 成为阿里云技术合作伙伴&#xff0c;在此基础上&#xff0c;双方展开了深度合作&#xff0c;并在今天&#xff08;3月1日&#xff09;正式上线“云消息队列 Confluent 版”。 通过将 Co…

android基础学习

从上面的描述就可以知道&#xff0c;每一个Activity组件都有一个对应的ViewRoot对象、View对象以及WindowManager.LayoutParams对象。这三个对象的对应关系是由WindowManagerImpl类来维护的。具体来说&#xff0c;就是由WindowManagerImpl类的成员变量mRoots、mViews和mParams所…

【Apache Camel】基础知识

【Apache Camel】基础知识 Apache Camel是什么Apache Camel基本概念和术语CamelContextEndpointsRoutesRouteBuilderComponentsMessageExchangeProcessorsDomain Specific Language&#xff08;DSL&#xff09; Apache Camel 应用执行步骤Apache Camel 示意图参考 Apache Camel…

学习Java的第一天

一、Java简介 Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的 Java 面向对象程序设计语言和 Java 平台的总称。由 James Gosling和同事们共同研发&#xff0c;并在 1995 年正式推出。 后来 Sun 公司被 Oracle &#xff08;甲骨文&#xff09;公司收购&#xff0c;Jav…

【30 天 JavaScript 挑战】学习笔记

30 天 JavaScript 挑战 专为 JavaScript 初学者设计 掌握必备 JavaScript 技能 前端人&#xff0c;前端魂&#xff0c;刷完 JS 即入门! 题目地址&#xff1a;https://leetcode.cn/studyplan/30-days-of-javascript/ 个人学习笔记&#xff1a;https://github.com/kaimo313/…

CRM系统的操作记录,应该怎样设计?多个独立模块的操作记录不同步,如何解决?

CRM系统的操作记录&#xff0c;应该怎样设计&#xff1f; 设计CRM&#xff08;Customer Relationship Management&#xff0c;客户关系管理&#xff09;系统的操作记录功能时&#xff0c;主要目标是确保所有与客户相关的活动和交互都能够被准确、详细地追踪和记录。以下是一种…

【AAAI2023】基于神经跨度的持续命名实体识别模型

论文标题&#xff1a;A Neural Span-Based Continual Named Entity Recognition Model 论文链接&#xff1a;https://arxiv.org/abs/2302.12200 代码&#xff1a;https://github.com/Qznan/SpanKL inproceedings{zhang2023spankl,title{A Neural Span-Based Continual Named En…