文章目录

  • 前言
  • 如何利用EasyExcel解析Excel
    • 1. 首先要定义一个对象
    • 2. 创建监听器
    • 3. 解析excel
  • 完结撒花 ???
  • 如何解决?
  • 后话

前言

大家好啊,我是皮皮虾~,最近接的个需求中有个小功能是要上传用户id或email的excel,解析返回出正常的用户数和异常的用户数(简单来说就是能查到用户信息的数量和不能查到的数量)。

擦,我寻思这不得涉及到流的操作,这可是我的弱项啊~

当然来,正经人谁直接手写,当然要拥抱开源啦,这不就遇到了阿里的EasyExcel


如何利用EasyExcel解析Excel

1. 首先要定义一个对象

根据EasyExcel的思想,excel的每一行都认为是一个对象,每一列可以认为是一个字段

那么对应到Java中,我们就可以建一个实体类,来对应我们需要解析的Excel。

实习类中的字段注意要加上@ExcelProperty注解

@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserData {@ExcelProperty(index = 0)private Long uid;@ExcelProperty(index = 1)private String email;}

@ExcelProperty注解,可以设置如下四个字段的值,一般情况下,我们需要设置 index 代表这个字段是对应的第几列(从0开始),或者设置 value 代表列名称,也就是通过列名称来匹配

**要注意的是,在官方文档中也提示了我们,不要同时使用index和value,如果excel没有设置标题或者标题重复可能导致解析不尽人意~ **


2. 创建监听器

创建一个监听器类,可以选择继承AnalysisEventListener类或者实现ReadListener接口

那么这两个有什么区别嘞?

其实区别不大,AnalysisEventListener实现了ReadListener的四个方法,主要的话还是在于对于表头数据的读取,通过重写invokeHead方法,帮我们手动将表头数据转换了一下,这样如果我们需要读取表头数据的话,直接继承AnalysisEventListener,实现invokeHeadMap即可,不然如果是依然实现ReadListener,我们还需要手动ConverterUtils.convertToStringMap转换

@EqualsAndHashCode(callSuper = true)
@Slf4j
@Data
@AllArgsConstructor
public class UserDataListener extends AnalysisEventListener<UserData> {/*** uid集合*/private List<Long> uidList;/*** 邮箱集合*/private List<String> emailList;/*** 有效用户数量*/private Integer validUserNum;/*** 无效用户数量*/private Integer invalidUserNum;/*** 类型(0:uid,1:email)*/private Integer type;public UserDataListener(Integer type) {this.type = type;if (type.equals(0)) {uidList = new ArrayList<>();return;}emailList = new ArrayList<>();}@Overridepublic void invoke(UserData data, AnalysisContext context) {if (type.equals(0)) {uidList.add(data.getUid());return;}emailList.add(data.getEmail());}@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {// 解析完成之后调用该方法 /*** rpc批量查询用户信息,通过type来区分是通过uidList查询还是emailList查询* ps:批量查询中,如果用户uid或者email不存在,最终返回的结果里则不包含该用户信息* 所以,rpc用户集合数量 <= uidList.size() or emailList.size()* 通过这个来计算validUserNum 和 invalidUserNum*/}@Overridepublic void onException(Exception exception, AnalysisContext context) {throw new RuntimeException("解析user excel异常", exception);}}

3. 解析excel

获取前端传过来的excel文件和上传类型,进行基本的参数校验之后,进行excel的解析

要注意的是监听器不能被Spring管理,每次都要去new一个新的对象

@Override
public UserUploadVO uploadFile(MultipartFile file, Integer type) throws Exception {if (file == null || type == null) {throw new RuntimeException("Param error");}UserUploadVO userUploadVO = new UserUploadVO();String fileName = file.getOriginalFilename();if (StringUtils.isEmpty(fileName)) {return userUploadVO;}String fileXlsx = fileName.substring(fileName.length() - 5);String fileXls = fileName.substring(fileName.length() - 4);if (!".xlsx".equals(fileXlsx) && !".xls".equals(fileXls)) {return userUploadVO;}UserDataListener userDataListener = new UserDataListener(type);// 解析excelEasyExcel.read(file.getInputStream(), UserData.class, userDataListener).sheet().doRead();// 设置有效用户数和无效用户数userUploadVO.setInvalidUserNum(userDataListener.getInvalidUserNum());userUploadVO.setValidUserNum(userDataListener.getValidUserNum());return userUploadVO;
}

由于计算有效用户数和无效用户数是口述了下逻辑,这边就不给小伙伴们去展示结果啦,有兴趣的小伙伴们可以自己试试


完结撒花 ???

本来写到这,皮皮虾已经自测通过了,觉得没啥问题了,但我突然又去嘴贱的问了下产品姐姐

皮皮虾:产品姐姐,那上传的时候,如果是传uid的excel都从第一列第二行开始,传email的excel都从第二列第二行开始可以不?

产品姐姐:为啥要这样嘞?都从第一列第二行开始不好嘛,我觉得统一一点比较好,不然上传的时候有问题,大家都以为是bug。

前面已经跟大家提过了,EasyExcel每一行都认为是一个对象,我们在字段上添加@ExcelProperty(index = 0)注解时,已经表明了这个字段是第几列的数据…,现在都搞到第一列,本质上还一个是String一个是Long

不过想想,人家产品说的也有道理,于是我礼貌的回复了下:好的啊~


如何解决?

看者眼前的聊天框,我陷入的沉思…,艹,大不了我写两套代码,能实现需求就行

一段狂敲代码过后,原本的一个实体类一个监听器,变成了两个实体类两个监听器,解析exel逻辑里也充满了if-else…

测试过后也没发现有啥问题,十分的nice

虽然功能实现了,但是看着眼前屎山般的代码,我恨不得抽自己两巴掌,这写的什么玩意

【日常需求】一次使用EasyExcel而引发的问题与思考~相关推荐

  1. Cobot专长:了解您的日常需求

    专长:了解您的日常需求 合作机器人和末端执行器联手提供Cobot价格合理的灵活解决方案.尽管机器人技术引领着自动化的快速增长,但我们将协作机器人视为机器人技术的民主化.它们消除了机器人通常需要的成本和 ...

  2. linux 服务器 日常命令 日常需求

    linux 服务器 日常命令 日常需求 文件管理 文本筛选-grep 截取字段-awk 对文件内容修改-sed 查找 下载文件 Http请求 上传 下载 压缩 解压 排序去重-sort.uniq 数值 ...

  3. 一次洗脚引发的线程池思考

    一次洗脚引发的线程池思考,文末有惊喜 上周末和好朋友大凯子约好周末去洗脚放松一下,毕竟忙了一周了,又加了几天班,身心疲惫,好的身体是革命的本钱,男人可得好好爱惜自己的身体,不能倒在革命的道路上,于是第 ...

  4. C/C++ 由int (*p)[5]与int *p[5]引发的学习与思考

    由int (*p)[5]与int *p[5]引发的学习与思考 最近在大一上复习指针这部分时,有个C指针的特例一直困扰着我.我查阅了许多课本,也看了CSDN上许多大佬的理解.自我感觉受益匪浅,现记录下自 ...

  5. 轩逸酷我音乐显示服务器错误,第14代轩逸车机系统体验:基本满足日常需求 随车流量模糊不清...

    [资讯-牛车网] 上一篇,牛车实验室为大家介绍了第14代轩逸搭载的日产智联系统.整体来说,这套智联系统的功能较为单一,用户体验亟待提升.智联系统略显鸡肋,那么与车主交流更为密切的车机系统使用体验如何呢 ...

  6. 史上最简单的springcloud微服务入门实例,满足企业日常需求,开箱即用,工资翻倍不是梦...

    在传统的IT行业软件大多都是各种独立系统的堆砌,这些系统的问题总结来说就是扩展性差,可靠性不高,维护成本高.到后面引入了SOA服务化,但是,由于 SOA 早期均使用了总线模式,这种总线模式是与某种技术 ...

  7. NTA告警引发的dll劫持思考(溯源)

    目录 溯源 DLL DLL Hijacking Vulnerability(DLL劫持漏洞) DLL劫持攻击 转发式劫持 DLL劫持防御 某天在客户局点巡检时,NTA设备发现了CS的告警:定位了被入侵 ...

  8. C++11中的时间库std::chrono(引发关于时间的思考)

    文章目录 前言 chrono 的概况 chrono 的核心内容 duration clock system_clock steady_clock time point 关于时间的思考 时间函数思考 总 ...

  9. 公理设计:由奇怪海战引发的软件设计思考

    前几天看到了一个博客,推荐了<公理设计>一书,还有其相关的文档以及视频.简单了解了一下,增深了一些对软件设计的理解,特此也推荐给大家. 公理设计理论将设计建立在科学公理.定理和推论的基础上 ...

最新文章

  1. J. Cheminform. | DrugEx v2:多重药理学中基于pareto的多目标强化学习的药物分子从头设计...
  2. 测试页打印失败0x0000045a_激光打印机就该选这样的,联想领像L100DW评测
  3. java excel 复杂表头_中国式复杂报表开发教程(4)—类Excel复杂表头报表
  4. 模板设计模式,简单Java代码实现
  5. linux deb文件安装_如何在 Ubuntu 上安装 VirtualBox | Linux 中国
  6. 为MFC中的ListBox添加水平滚动条
  7. C# 接受MQTT服务器推送的消息
  8. 重读经典:《Momentum Contrast for Unsupervised Visual Representation Learning》
  9. mysql数据库连接锁住_锁mysql方法
  10. 不可求的电脑上必备软件,你也许听过
  11. WAMP显示错误“MSVCR100.dll”缺少安装时
  12. linux HZ 值_Linux操作系统中进程的操作命令(ps,kill,keep)
  13. 【CDOJ1330】柱爷与远古法阵(高斯消元+卡精度+概率dp?)
  14. vue 日期多选插件
  15. Error querying database. Cause: java.sql.SQLException: ORA-01008: 并非所有变量都已绑定
  16. JSP——编写一个简单的JSP页面,显示英文字母表
  17. 这么黄的教程,我看了2小时就关了!
  18. 柴夥說算法(4)--再說樹
  19. 前端埋点数据收集及上报方案
  20. STM32 串口 FIFO

热门文章

  1. 运行moveit报错
  2. yolov5原理到实现
  3. 联邦学习的威胁模型和攻防现状
  4. Python读取本地html文件内容存csv
  5. HTML仿QQ音乐页面附源码(无框架)
  6. 移动互联网时代 移动生活的碎片化解决方案
  7. PLC数据采集网关有哪些作用,PLC数据采集网关如何正确进行使用
  8. Linux 强制破解root密码 是root密码哦
  9. 【科普】“植物神经功能紊乱”如何诊断和治疗呢?
  10. 江苏省计算机等级考试理论试题,2015江苏省计算机等级考试试题 二级ACCESS理论考试试题及答案...