EasyExcel复杂excel导入

article/2025/9/8 18:05:00

EasyExcel复杂excel导入

easyexcel官方都是一些简单的导入到处示例,复杂的excel文档导入,还得自己去慢慢琢磨、百度、思考、总结、学习、观察。

代码地址在文档的最后,如果你也遇到这种需求,不妨动动你的小拇指,点个关注,要是可以点个赞,那就更好咯,做人嘛,不要这么小气,不要吝啬你的赞美,哈哈。

要导入的excel格式,如下图:

第一个sheet内容:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MqfRrgNN-1660632070755)(D:\yangfan\mdpic\2022-08-16-13-58-28-image.png)]

第二个sheet内容,一对多,一个阶段对应多个任务,一个任务对应多个动作:
在这里插入图片描述

废话不多说,直接上代码,能看懂多少就看你自己的功力了

controller

@RestController
@RequestMapping("/sakura/easyexcel")
@Api(value = "复杂excel导入", tags = {"复杂excel导入"})
public class ProjectExcelController {@AutowiredProjectEasyExcelService projectEasyExcelService;@ApiOperation("复杂excel导入")@PostMapping(value = "/complex/upload")public CommonResult<Object> upload(@RequestParam("file") MultipartFile file){projectEasyExcelService.projectRead(file);return CommonResult.success();}
}

service

/*** 项目信息excel*/
@Transactional(rollbackFor = Exception.class)
public void projectRead(MultipartFile file) {EasyExcelListener easyExcelListener = new EasyExcelListener();ExcelReader excelReader = null;try {excelReader = EasyExcelFactory.read(file.getInputStream(), easyExcelListener).build();} catch (IOException e) {throw new YErrorException("项目信息导入出错!");}// step2. 获取各个sheet页信息List<ReadSheet> sheets = excelReader.excelExecutor().sheetList();// step3. 获取各个Shhet页表格内容存于mapMap<Integer, List<LinkedHashMap<String, String>>> sheetInfos = new HashMap<>(sheets.size());for (ReadSheet sheet : sheets) {Integer sheetNo = sheet.getSheetNo();excelReader.read(sheet);sheetInfos.put(sheetNo, easyExcelListener.getListMap());}//保存数据到数据库saveExcelInfo(sheetInfos);
}

上面projectRead方法用到的EasyExcelListener

@Slf4j
public class EasyExcelListener extends AnalysisEventListener<Object> {// 创建list集合封装最终的数据private List<Object> list = new ArrayList<>();// sheet页索引private int sheetNo = 0;@Overridepublic void invoke(Object t, AnalysisContext context) {// 读取excle内容int currentSheetNo = context.readSheetHolder().getSheetNo();if (currentSheetNo != sheetNo) {// 如果不根据sheet页索引更新状态重新创建list,list会反复添加前面的sheet页对象值list = new ArrayList<>();sheetNo = currentSheetNo;}list.add(t);}// 读取excel表头信息@Overridepublic void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {}// 读取完成后执行@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {}/*** 将表格转化为map集合(复杂excel读取用此方法)** @return map集合*/public List<LinkedHashMap<String, String>> getListMap() {String jsonObj = JSON.toJSONString(list);return JSON.parseArray(jsonObj, LinkedHashMap.class);}}

上面projectRead中的方法

public void saveExcelInfo(Map<Integer, List<LinkedHashMap<String, String>>> sheetInfos) {for (Integer sheetNo : sheetInfos.keySet()) {List<LinkedHashMap<String, String>> maps = sheetInfos.get(sheetNo);// 不同sheet页数据处理方式不同switch (sheetNo) {case 0:saveProject(maps);break;case 1:saveTarget(maps);break;default:break;}}
}

保存第一个sheet的项目信息,并返回全局的项目id,代码很长,简化了一部分,全部代码可以看最后github的地址


public void saveProject(List<LinkedHashMap<String, String>> maps) {ProjectManage projectManage = new ProjectManage();for (LinkedHashMap<String, String> map : maps) {if (map.containsValue("项目名称")) {String projectName = map.getOrDefault("1", "");if (StringUtils.isBlank(projectName)) {throw new YWarmingException("项目名称不能为空!");}projectManage.setProjectName(projectName);}if (map.containsValue("项目编号")) {String projectCode = map.getOrDefault("4", "");projectManage.setProjectCode(projectCode);}if (map.containsValue("合同签订时间")) {String contractSignTimeStr = map.getOrDefault("1", "");if (StringUtils.isNotBlank(contractSignTimeStr)) {Date contractSignDate = DateUtil.parse(contractSignTimeStr);Instant instant = contractSignDate.toInstant();LocalDateTime contractSignTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();projectManage.setContractSignTime(contractSignTime);}}if (map.containsValue("合同规定终验时间")) {String contractRuleFinalAcceptTimeStr = map.getOrDefault("3", "");if (StringUtils.isNotBlank(contractRuleFinalAcceptTimeStr)) {Date contractSignDate = DateUtil.parse(contractRuleFinalAcceptTimeStr);Instant instant = contractSignDate.toInstant();LocalDateTime contractRuleFinalAcceptTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();projectManage.setContractRuleFinalAcceptTime(contractRuleFinalAcceptTime);}}if (map.containsValue("开工时间")) {String startTimeStr = map.getOrDefault("5", "");if (StringUtils.isNotBlank(startTimeStr)) {Date startDate = DateUtil.parse(startTimeStr);Instant instant = startDate.toInstant();LocalDateTime startTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();projectManage.setStartTime(startTime);}}}//这里项目背景的行数,写死了,后面调整表格时,会影响这一块Map<String, String> projectBackgroudMap = maps.get(8);  String projectBackgroud = projectBackgroudMap.getOrDefault("0", "").toString();projectManage.setProjectBackgroud(projectBackgroud);projectManageService.save(projectManage);projectId = projectManage.getId();
}

保存第二个sheet的目标,将数据组装成多级嵌套的集合。有点绕,要花点时间去想想,项目赶工,瞎几把乱写了,没想到可以凑合着用。

public void saveTarget(List<LinkedHashMap<String, String>> list) {if (projectId == 0) {throw new YErrorException("请先成功导入项目!");}FirstTarget firstTarget = new FirstTarget();SecondTarget secondTarget = new SecondTarget();List<FirstTarget> firstTargetList = new ArrayList<>();List<SecondTarget> secondTargetList = new ArrayList<>();List<ThirdTarget> thirdTargetList = new ArrayList<>();for (Map<String, String> map : list) {System.err.println(map);String firstTargetName = map.getOrDefault("0", "");String firstTargetType = map.getOrDefault("1", "");String secondTargetName = map.getOrDefault("2", "");String thirdTargetName = map.getOrDefault("3", "");String thirdTargetBudget = map.getOrDefault("4", "");String positions = map.getOrDefault("5", "");if (StringUtils.isNotBlank(firstTargetName)) {//第一阶段名称不为空时,二三阶段一定不为空if (StringUtils.isNotBlank(secondTargetName)) {//第二阶段名称不为空if (secondTargetList.size() != 0) {List<SecondTarget> secondTargets = firstTarget.getSecondTargets();secondTargets.addAll(secondTargetList);}secondTarget = new SecondTarget();thirdTargetList = new ArrayList<>();firstTarget = new FirstTarget();secondTargetList = new ArrayList<>();secondTarget.setSecondTargetName(secondTargetName);ThirdTarget thirdTarget = new ThirdTarget();thirdTarget.setThirdTargetName(thirdTargetName);thirdTarget.setThirdTargetBudget(thirdTargetBudget);thirdTargetList.add(thirdTarget);secondTarget.setThirdTargets(thirdTargetList);secondTargetList.add(secondTarget);firstTarget.setSecondTargets(secondTargetList);firstTarget.setFirstTargetName(firstTargetName);firstTarget.setFirstTargetType(firstTargetType);firstTargetList.add(firstTarget);}} else {//第一阶段名称为空,且第二阶段名称不为空if (StringUtils.isNotBlank(secondTargetName)) {//去重if (secondTargetList.size() != 0) {SecondTarget st = secondTargetList.get(0);List<SecondTarget> secondTargets = firstTarget.getSecondTargets();SecondTarget secondT = secondTargets.get(0);if (!st.getSecondTargetName().equals(secondT.getSecondTargetName())) {secondTargets.addAll(secondTargetList);}}secondTarget = new SecondTarget();thirdTargetList = new ArrayList<>();secondTargetList = new ArrayList<>();secondTarget.setSecondTargetName(secondTargetName);ThirdTarget thirdTarget = new ThirdTarget();thirdTarget.setThirdTargetName(thirdTargetName);thirdTarget.setThirdTargetBudget(thirdTargetBudget);thirdTargetList.add(thirdTarget);secondTarget.setSecondTargetName(secondTargetName);secondTarget.setThirdTargets(thirdTargetList);secondTargetList.add(secondTarget);} else {//第一阶段名称为空,第二阶段名称为空,第三阶段不为空ThirdTarget thirdTarget = new ThirdTarget();thirdTarget.setThirdTargetBudget(thirdTargetBudget);thirdTarget.setThirdTargetName(thirdTargetName);thirdTargetList.add(thirdTarget);}}}// 保存最后一条数据if (secondTargetList.size() != 0) {List<SecondTarget> secondTargets = firstTarget.getSecondTargets();secondTargets.addAll(secondTargetList);}System.err.println(firstTargetList);}

还有几个实体类就不放上来了,博客太长了,看完有一点点思路,可以帮助到你,我还是很开心的,全部代码和导入的excel放下面了,可以拿去看看,参考参考。

excel地址:项目导入.xlsx

代码地址:sakura-boot-demo · GitHub


http://chatgpt.dhexx.cn/article/JkqEnOIy.shtml

相关文章

导出Excel的方式

*数据是表格的形式&#xff0c;进常用到Excel *在程序中经常可以看到有导出Excel文档&#xff0c;Excel导入数据的情况&#xff0c;现在我就说一下我学到的导出Excel *导出Excel有两种方法&#xff0c;第一种是自己设置表头的&#xff0c;第二种是填充的&#xff0c;现在我说的…

Excel文件导入导出操作

> 注意&#xff01;注意&#xff01;&#xff01;注意&#xff01;&#xff01;&#xff01; 文末有惊喜彩蛋&#xff0c;请注意查收&#xff01;日常开发工作中对于文件的相关操作大家多少都会涉及&#xff1a;上传解析、数据导出等。此篇内容主要分享一下工作中常用的Exce…

Java实现Excel导入导出

一、导入 前言&#xff1a;导入必须用post请求 具体原因在2中叙述 1、Excel导入 总结一下目标&#xff0c;就是要将excel中的数据行、逐一提取&#xff0c;最后得到一个list&#xff0c;这个list的每个元素就是excel的每个数据行的实例&#xff0c;之后的操作就是常规的jav…

Java实现Excel导入

实现前准备&#xff08;导入所需要的依赖&#xff09; <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.22</version></dependency><dependency><groupId>org.apache.…

导入Excel文件的方法

我们在做一些项目的时候通常会遇到有导入文件的这种需求&#xff0c;下面我给大家分享一下导入Excel文件的方法。 首先我们得准备一个模板&#xff0c;下图就是一个简单的EX导入模板&#xff0c; 下图就是一个导入模板&#xff0c; 我们先把导入模板写好&#xff0c; 还有一个…

两种方式导入excel

第一种 easyExcel pom文件导入 com.alibaba easyexcel 2.2.3 然后 /** * 导入用户excel * param * return */ PostMapping(“manage/imporAcc”) Message<?> imporAcc(RequestParam(“accountFile”) MultipartFile file,RequestParam(“role”)String role,Request…

Java实现Excel导入和导出,看这一篇就够了(珍藏版)

目录 目录 前言 1. 功能测试 1.1 测试准备 1.2 数据导入 1.2.1 导入解析为JSON 1.2.2 导入解析为对象&#xff08;基础&#xff09; 1.2.3 导入解析为对象&#xff08;字段自动映射&#xff09; 1.2.4 导入解析为对象&#xff08;获取行号&#xff09; 1.2.5 导入解析…

常见机器学习面试题

参考&#xff1a;http://kubicode.me/2015/08/16/Machine%20Learning/Common-Interview/?fromsinglemessage# http://blog.csdn.NET/heyongluoyao8/article/details/49429629 http://lib.csdn.Net/article/machinelearning/33798 http://www.cnblogs.com/zuochongyan/p/540705…

机器学习面试题60~100

61.说说梯度下降法 LeftNotEasy&#xff0c;本题解析来源&#xff1a;http://www.cnblogs.com/LeftNotEasy/archive/2010/12/05/mathmatic_in_machine_learning_1_regression_and_gradient_descent.html 下面是一个典型的机器学习的过程&#xff0c;首先给出一个输入数据&#…

深度学习机器学习面试题汇——模型优化,轻量化,模型压缩

深度学习机器学习面试题汇——模型优化&#xff0c;轻量化&#xff0c;模型压缩 提示&#xff1a;互联网大厂可能考的面试题 若CNN网络很庞大&#xff0c;在手机上运行效率不高&#xff0c;对应模型压缩方法有了解吗 介绍一下模型压缩常用的方法&#xff1f;为什么用知识蒸馏&…

Python干货:破解40大机器学习面试题(包含初中高级)

机器学习&#xff08;ML&#xff09;是我们世界的未来。在未来的几年中&#xff0c;几乎每种产品都将包含ML组件。ML预计将从2020年的$ 7.3B增长到2024年的$ 30.6B。对ML技能的需求遍及整个行业。 机器学习面试是一个严格的过程&#xff0c;在此过程中&#xff0c;应聘者会评估…

2021机器学习面试必考面试题汇总(附答案详解)

问题&#xff1a;Xgboost、lightGBM和Catboost之间的异同&#xff1f; 树的特征 三种算法基学习器都是决策树&#xff0c;但是树的特征以及生成的过程仍然有很多不同。 CatBoost使用对称树&#xff0c;其节点可以是镜像的。CatBoost基于的树模型其实都是完全二叉树。 XGBoo…

机器学习面试题之——简单介绍最小二乘

1、常用到的最小二乘场合&#xff1a;最小二乘法直线拟合&#xff0c;最小二乘法多项式&#xff08;曲线&#xff09;拟合&#xff0c;机器学习中线性回归的最小二乘法&#xff0c;系统辨识中的最小二乘辨识法&#xff0c;参数估计中的最小二乘法&#xff0c;等等。 2、为什么…

AI人工智能、机器学习 面试题(2022最新版)

人工智能、机器学习面试题总结&#xff0c;侧重于理解&#xff0c;回答供参考&#xff0c;欢迎讨论。 General 深度学习&#xff08;Deep Learning, DL&#xff09;和机器学习&#xff08;Machine Learning, ML&#xff09;的关系是什么&#xff1f; 深度学习是机器学习的子类…

面试官最爱用的统计学、数据科学、机器学习面试题答案

【导读】本文盘点了数据科学和机器学习面试中的常见问题&#xff0c;着眼于不同类型的面试问题。如果您计划向数据科学领域转行&#xff0c;这些问题一定会有所帮助。 技术的不断进步使得数据和信息的产生速度今非昔比&#xff0c;并且呈现出继续增长的趋势。此外&#xff0c;…

41个机器学习面试题

####41 Essential Machine Learning Interview Questions (with answers) <font color‘orange’&#xff0c;size5>一、算法理论 Q1: 什么是偏倚&#xff08;bias&#xff09;、方差&#xff08;variable&#xff09;均衡&#xff1f; 偏倚指的是模型预测值与真实值的…

推荐收藏,25道机器学习面试问题(附答案)

近年来&#xff0c;对深度学习的需求不断增长&#xff0c;其应用程序被应用于各个商业部门。各公司现在都在寻找能够利用深度学习和机器学习技术的专业人士。 在本文中&#xff0c;将整理深度学习面试中最常被问到的25个问题和答案。如果你最近正在参加深度学习相关的面试工作…

机器学习面试题之机器学习基础(一)

1、L1与L2正则化 他们都是可以防止过拟合&#xff0c;降低模型复杂度。 L1会趋向于产生少量的特征&#xff0c;而其他的特征都是0&#xff1b;L2会选择更多的特征&#xff0c;这些特征都会接近于0。L1在特征选择时非常有用&#xff0c;L2就只是一种规则化而已。 简单总结一下就…

机器学习面试必考面试题汇总—附解析

问题&#xff1a;xgboost对特征缺失敏感吗&#xff0c;对缺失值做了什么操作&#xff0c;存在什么问题 不敏感&#xff0c;可以自动处理&#xff0c;处理方式是将missing值分别加入左节点 右节点取分裂增益最大的节点将missing样本分裂进这个节点 。这种处理方式的问题在xgboo…

机器学习面试题——聚类算法

机器学习面试题——聚类算法 提示&#xff1a;互联网大厂经常考的传统机器学习算法 文章目录 机器学习面试题——聚类算法[TOC](文章目录) 题目k-means介绍一下&#xff0c;K-means的过程k-means优缺点k-means的簇&#xff08;k簇&#xff09;怎么选&#xff0c;K-means如何选取…