Springboot 下 EasyExcel 的数据导入导出

文章目录

  • 1.环境准备
  • 1.0. excel数据
  • 1.1. pom
  • 1.2. excle映射实体
  • 1.3. 自定义日期转换器
    • 1.4.自定义异常
  • 2. 数据导出
  • 3. 数据导入
  • 3.1. excel解析监听类
  • 3.2. excel导入

1.环境准备

1.0. excel数据

在这里插入图片描述

1.1. pom

	 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.1.4.RELEASE</version></dependency><!--slf4j日志--><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-simple</artifactId><version>1.7.25</version><scope>compile</scope></dependency><!--lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.4</version></dependency><!--easyexcel--><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.1.6</version></dependency><!--gson--><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.8.0</version></dependency>

1.2. excle映射实体

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ContentRowHeight(15)//内容单元格高度
@HeadRowHeight(15)//表头单元格高度
@ColumnWidth(10)//单元格宽度
public class TreeNode {//编码@ExcelProperty(index = 0,value = {"编码"})private String code;//名称@ExcelProperty(index = 1,value = {"名称"})private String name;//单位@ExcelProperty(index = 2,value = "单位")private String unit;//数量@ExcelProperty(index = 3,value = "数量")private BigDecimal qty;//单价@ExcelProperty(index = 4,value = "单价")private BigDecimal price;//金额@ExcelProperty(index = 5,value = "金额")private BigDecimal amt;//备注@ExcelProperty(index = 6,value = "备注")private String remake;//生产日期@ExcelProperty(index = 7,value = "生产日期")private LocalDateTime dateInProduced;
}

1.3. 自定义日期转换器

public class LocalDateTimeConverter implements Converter<LocalDateTime> {private DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");@Override//java类型public Class supportJavaTypeKey() {return LocalDateTime.class;}@Override//Excel内部数据类型public CellDataTypeEnum supportExcelTypeKey() {return CellDataTypeEnum.STRING;}@Overridepublic LocalDateTime convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {return LocalDateTime.parse(cellData.getStringValue(), timeFormatter);}@Overridepublic CellData convertToExcelData(LocalDateTime dateTime, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {return new CellData<>(dateTime.format(timeFormatter));}
}

1.4.自定义异常

/*** excel行解析异常,不中断后续行解析操作 <br>* @author lls* @version 1.0.0* @date 2021/5/20*/
public class ExcelRowAnalysisException extends RuntimeException {public ExcelRowAnalysisException() {}public ExcelRowAnalysisException(String message) {super(message);}}

2. 数据导出

    @PostMapping("/export")public void download(HttpServletResponse response) throws Exception {response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("UTF-8");response.setHeader("Content-disposition", "attachment");EasyExcel.write(response.getOutputStream(), ExcelBO.class).registerConverter(new LocalDateTimeConverter()).sheet("sheet1").doWrite(getDataList());}

3. 数据导入

3.1. excel解析监听类

/*** 解析监听类 <br>** @author lls* @version 1.0.0* @date 2021/5/19*/
@Slf4j
public class ExcelReadListener extends AnalysisEventListener<ExcelBO> {private Gson gson;//节点层级分组map (key:层级;value:该层级下的节点集合)private Map<Integer, List<TreeNodeBO>> hierarchyMap;//异常信息private StringBuilder errorMsg;//bean验证实例private Validator validator;//最大层级private Integer maxHierarchy = -1;//编码层级分隔符private String splitStr = "-";public ExcelReadListener() {this.gson = new Gson();this.hierarchyMap = new HashMap<>();this.errorMsg = new StringBuilder();this.validator = Validation.buildDefaultValidatorFactory().getValidator();}/*** 每行数据解析 动作 <br>** @param data:* @param context:* @return void* @see*/@Overridepublic void invoke(ExcelBO data, AnalysisContext context) {context.readWorkbookHolder().getReadWorkbook().setAutoTrim(true);//读取进datalog.info("当前解析行数据,data :{} ", gson.toJson(data));validate(context.getCurrentRowNum(), data);//参数校验TreeNodeBO treeNodeBO = new TreeNodeBO();BeanUtils.copyProperties(data, treeNodeBO);Integer hierarchy = countHierarchy(treeNodeBO.getCode()); //层级结构 = code中 splitStr 出现的次数treeNodeBO.setHierarchy(hierarchy);maxHierarchy = Math.max(maxHierarchy, hierarchy);//最大层级List<TreeNodeBO> nodeList = Optional.ofNullable(hierarchyMap.get(hierarchy)).orElse(new ArrayList<>());nodeList.add(treeNodeBO);hierarchyMap.put(hierarchy, nodeList);}/*** 解析完成后动作 <br>** @param context:* @return void* @see*/@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {if (0 != errorMsg.length()) {//模板解析不通过,不执行解析后动作throw new RuntimeException(errorMsg.toString());}log.info("解析到的所有数据集合,excelBOList :{} ", gson.toJson(hierarchyMap));initTreeNodeBO(maxHierarchy);//初始化树结构log.info("解析后的所有数据集合,excelBOList :{} ", gson.toJson(hierarchyMap));}/*** 每个sheet页的头行触发函数 <br>** @param headMap:* @param context:* @return void* @see*/@Overridepublic void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {log.info("解析到一条头数据:{}", gson.toJson(headMap));if(1==context.getCurrentRowNum()){//模板文档第二行为实际有效表头//校验excel模板的正确性,抛出异常并中断后续invoke()解析//通过 ExcelBO.class 获取field域上ExcelProperty注解。与headMap对比Field[] excelBOFields = ExcelBO.class.getDeclaredFields();if(excelBOFields.length!=headMap.size()){throw new RuntimeException("导入文档 头数据格式错误");}for (Field excelBOField : excelBOFields) {ExcelProperty excelProperty = excelBOField.getAnnotation(ExcelProperty.class);int index = excelProperty.index();String[] values = excelProperty.value();if(!headMap.get(index).equals(values[0])){throw new RuntimeException("导入文档 头数据格式错误");}}}}/*** 发生异常时触发函数 <br>** @param exception:* @param context:* @return void* @see*/@Overridepublic void onException(Exception exception, AnalysisContext context) throws Exception {log.info("捕捉到一条异常:{}", exception);if (exception instanceof ExcelRowAnalysisException) {errorMsg.append(exception.getMessage());//某行解析错误,只中断本行,不中断后续行得解析} else {throw exception;}}/*** 参数校验 <br>** @param rowNum:* @param target:* @return java.lang.String* @see*/private void validate(Integer rowNum, ExcelBO target) {//本行数据校验StringBuilder rowErrorMsg = new StringBuilder();Set<ConstraintViolation<ExcelBO>> constraintViolations = validator.validate(target);Iterator<ConstraintViolation<ExcelBO>> iterator = constraintViolations.iterator();while (iterator.hasNext()) {ConstraintViolation<ExcelBO> error = iterator.next();rowErrorMsg.append("第").append(rowNum).append("行:").append(error.getMessage()).append(";");}if (rowErrorMsg.length() != 0) {throw new ExcelRowAnalysisException(rowErrorMsg.toString());//中断本行后续解析}}/*** 初始化父节点、金额、数量 <br>** @param hierarchy: 最大层级* @return void* @see*/private void initTreeNodeBO(Integer hierarchy) {if (hierarchy <= 0) { //0层级无父级层级 、跳出递归return;}List<TreeNodeBO> currentHierarchy = hierarchyMap.get(hierarchy);//当前层级List<TreeNodeBO> parentHierarchy = hierarchyMap.get(--hierarchy);//当前层级的 父级层级if (CollectionUtils.isNotEmpty(currentHierarchy)) {parentHierarchy.stream().forEach(parent -> {//当前父节点 的子节点集合List<TreeNodeBO> childNode = currentHierarchy.stream().filter(child -> child.getCode().indexOf(parent.getCode()) == 0).collect(Collectors.toList());childNode.stream().forEach(child -> child.setParentCode(parent.getCode()));//子节点集合设置 parentCodeBigDecimal childAmount = childNode.stream().map(TreeNodeBO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);//子节点金额和BigDecimal childQty = childNode.stream().map(TreeNodeBO::getQty).reduce(BigDecimal.ZERO, BigDecimal::add);//子节点数量和parent.setAmount(parent.getAmount().add(childAmount));parent.setQty(parent.getQty().add(childQty));});}initTreeNodeBO(hierarchy);}/*** 计算节点层级结构(层级结构 = 分隔符出现的次数) <br>** @param code: 编码* @return java.lang.Integer* @see*/private Integer countHierarchy(String code) {int before = code.length();int after = code.replace(splitStr, "").length();return before - after;}}

3.2. excel导入

 @PostMapping("/import")public BaseRspBO upload(@RequestParam("file") MultipartFile file) throws Exception {String filename = file.getOriginalFilename();//文件名InputStream inputStream = null;inputStream = new ByteArrayInputStream(file.getBytes());//文件转输入流EasyExcel.read(inputStream, ExcelBO.class, build()).sheet("sheet1")//指定要读取的sheet页.headRowNumber(2)//指定行头数量.registerConverter(new LocalDateTimeConverter())//注入自定义转换器.doRead();return BaseRspBO.builder().code(HttpStatus.OK.toString()).msg("success").build();}private ReadListener build() {return new ExcelReadListener();}

参考链接:
easyExcel官方文档
EasyExcel全面教程快速上手
converter详解

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

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

相关文章

springboot spring-cloud spring-cloud nacos 整合模板

文章目录二、coding实战2.1. 版本对照2.2. 线上采用版本2.3. yml文件配置2.4. pom依赖2.5. 效果图二、coding实战 2.1. 版本对照 先阅读->版本说明 2.2. 线上采用版本 Spring Cloud Alibaba VersionSpring Cloud VersionSpring Boot VersionNacos Version2.2.7.RELEAS…

CSDN居然免费送会员? 赶紧来领!

距离春节还有不到一个月你准备好给家人的春节礼物了吗&#xff1f;疫情下&#xff0c;为了让程序猿同学开心加班小编提前准备了一份牛年大礼 周五福利日&#xff0c;人人都可免费领会员&#xff01;助你提前实现CSDN会员卡自由&#xff01;奖品多多&#xff0c;不仅有CSDN月卡会…

《Dubbo迈出云原生重要一步-应用级服务发现解析》

作者 | 刘军&#xff08;陆龟&#xff09; Apache Dubbo PMC 概述 社区版本 Dubbo 从 2.7.5 版本开始&#xff0c;新引入了一种基于实例&#xff08;应用&#xff09;粒度的服务发现机制&#xff0c;这是我们为 Dubbo 适配云原生基础设施的一步重要探索。版本发布到现在已有近…

阿里云HiShop海商创新合作—线上商城这样做更合适

做商城一直是企业商家经久不衰的话题&#xff0c;尽管人们对于网上商城系统的了解已经有很多。距离电商真正来到与消费者做到息息相关&#xff0c;或许还要很长的路要走。人、货、场三种元素没有实现根本联通是一个很重要的原因。那么企业应该怎样搭建线上商城才能最符合当下消…

nacos 开启权限验证后 报错状态 403

文章目录一、漏洞修复1. 未授权访问漏洞2. 解决方案3. 修复效果图二、403 异常解决2.1. 版本对照2.2. 线上采用版本2.3. yml文件配置2.4. pom依赖2.5. 效果图一、漏洞修复 1. 未授权访问漏洞 前因&#xff1a;政府项目被扫出nacos未授权访问漏洞 2. 解决方案 在nacos/conf…

数据爆发式增长下,CIO不可不知的“数据经济学”

导读&#xff1a;6月9日&#xff0c;全速重构•2020阿里云线上峰会如期举行。阿里巴巴研究员、阿里云智能存储资深产品总监Alex Chen做了主题为《面向未来&#xff0c;企业CIO该懂的数据经济学》的分享。在分享中&#xff0c;他畅谈了数据增长所带来的全新挑战&#xff0c;同时…

小程序快速入门

文章目录一、微信小程序和企业微信小程序相同点和区别&#xff1f;1.1.相同点1.2.不同点1.3.受众人群1.4.核心概念1.5.总结二、开发文档2.1.微信开发文档2.2.企业微信开发文档三、小程序申请&#xff1f;3.1.申请流程3.2.主体说明四、小程序如何线下调试&#xff1f;4.1.调试流…

Serverless在大规模数据处理的实践

云栖号资讯&#xff1a;【点击查看更多行业资讯】 在这里您可以找到不同行业的第一手的上云资讯&#xff0c;还在等什么&#xff0c;快来&#xff01; 前言 当您第一次接触 Serverless 的时候&#xff0c;有一个不那么明显的新使用方式&#xff1a;与传统的基于服务器的方法相…

完美日记:实现高弹性高稳定电商架构

公司简介 完美日记&#xff08;Perfect Diary&#xff09;是广州市“独角兽”创新企业——广州逸仙电子商务有限公司旗下首个美妆品牌&#xff0c;创立于2017年&#xff0c;用心为新生代女性开发高品质、精设计、易上手的彩妆及护肤产品&#xff0c;立志于打造有国际影响力的C…

云原生体系下的技海浮沉与理论探索

来源 | 阿里巴巴中间件责编 | 晋兆雨头图 | 付费下载于视觉中国概述

比GPU性能提升5倍阿里云含光800云服务器正式商用

含光800云服务器&#xff0c;配备阿里平头哥自研神经网络加速芯片含光800&#xff0c;提供全球最高单芯片AI推理性能&#xff0c;有着同类处理器的数十倍性能&#xff1b;并针对业务场景做了深度优化&#xff0c;广泛适用于图像搜索、场景识别、视频内容识别、自然语言处理等业…

阿里研发效能数据知多少

2020 年 3 月阿里云云效平台发布了阿里内部 4 万开发者的研发效能数据报&#xff0c;数据显示阿里代码量和交付表现一路飙升&#xff0c;2020 财年代码行数共新增 15 亿&#xff0c;修改重构代码总行数 4 亿&#xff0c;疫情期间新增代码行 2.9 亿&#xff1b;3 天开发出健康码…

春招抢跑丨腾讯新年放大“招”!超3000+岗位!

虽然离春节仅剩 1 个月的时间&#xff0c;大厂依旧没有停止招人。就在上周&#xff0c;腾讯官宣新年大扩招&#xff0c;放出 3000 多个岗位需求&#xff01;我们查看了腾讯的招聘数据发现&#xff0c;除了大量招聘运营人员&#xff0c;你猜&#xff0c;他们还在批量招聘什么岗位…

对话阿里云MVP裔隽跨界半生,不改赤子心

云栖号资讯&#xff1a;【点击查看更多行业资讯】 在这里您可以找到不同行业的第一手的上云资讯&#xff0c;还在等什么&#xff0c;快来&#xff01; 简介&#xff1a; 我从没想过会用“少年感”来形容一位40岁的商界人士。裔隽在很多时候像一位人生导师&#xff0c;儒雅随和&…

从 2018 年 Nacos 开源说起

2018 年夏天 国内微服务开源 领域&#xff0c;迎来了一位新成员。此后&#xff0c;在构建微服务注册中心和配置中心的过程中&#xff0c;国内开发者多了一个可信赖的选项。 Nacos 是阿里巴巴开源的一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台(官方网站)…

用三国杀讲分布式算法,舒适了吧?

来源 | 悟空聊架构头图 | 付费下载于视觉中国点击播放&#xff0c;看文效果更佳&#xff01;东汉末年&#xff0c;袁绍作为盟主&#xff0c;汇合了十八路诸侯一起攻打董卓。在讲解之前&#xff0c;我们先聊下分布式协议和算法整体脉络。现在很多开发同学对分布式的组件怎么使用…

软件设计师 - UML图

文章目录总览UML图关系活动图通信图用例图类图 对象图顺序图状态图组件图总览 UML图关系 包含&#xff1a; 扩展&#xff1a; 泛化&#xff1a; 用例的泛化&#xff1a;把可选行为从必须行为中分离出来&#xff1b; 参与者的泛化&#xff1a;可以完成参与者的同样的任务&am…

SpringBoot 使用宝兰德中间件替换tomcat运行部署+控制台部署

文章目录1. 排除tomcat依赖2. 集成宝兰德依赖3. 项目打包方式4. 支持war部署配置5. 控制台部署1. 排除tomcat依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions>…

戚俊:可能是最懂架构的投资人

云栖号资讯&#xff1a;【点击查看更多行业资讯】 在这里您可以找到不同行业的第一手的上云资讯&#xff0c;还在等什么&#xff0c;快来&#xff01; 简介&#xff1a; 戚俊的快速成长离不开恰逢其时的机遇和委以重任的伯乐&#xff0c;毕业一两年受邀创业。当腻了CTO&#xf…

除了 Docker,我们还有哪些选择?

来源 | CSDN编译 | 弯月 责编 | 张文头图 | CSDN下载于视觉中国【编者按】所谓三十年河东&#xff0c;三十年河西&#xff0c;曾经在容器领域叱咤风云的 Docker 如今已风光不再。抛开情怀&#xff0c;我们不得不承认&#xff0c;Docker 已经被后浪拍死在沙滩上了……大约 4 年前…