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 适配云原生基础设施的一步重要探索。版本发布到现在已有近…

springboot pom 依赖

基础环境pom <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.1.4.RELEASE</version></dependency>插件pom <!--slf4j日志--><dependency>…

阿里云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;同时…

统计一个字符在另一个字符串中出现的次数

文章目录1.一个字符在另一个字符串中出现的次数2.测试3.输出1.一个字符在另一个字符串中出现的次数 /*** showTime 懂得都懂 <br>* param findStr: 要寻找的字符* param fromStr: 可能包含 findStr 的字符串* return java.lang.Integer 次数* see*/private static Int…

小程序快速入门

文章目录一、微信小程序和企业微信小程序相同点和区别&#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…

达梦数据库部署多实例

文章目录1. 新建配置2. 赋予权限1. 新建配置 vim /etc/dm_svc.conf添加如下内容&#xff1a; TIME_ZONE(8:00) LANGUAGE(cn) DW1(192.202.xxx.xxx:5236,192.168.xxx.xxx:5236)[DW1] LOGIN_MODE(1) SWITCH_TIME(300) SWITCH_INTERVAL(200)2. 赋予权限 非root用户启动应用使用此…

树形结构递归初始化(父节点,统计字段等)

文章目录1.核心思想&#xff1a;2.核心方法实现&#xff1a;3.完整代码如下3.1. 树形实体3.2. 完整操作1.核心思想&#xff1a; 1.先将每个节点按层级进行分组成map&#xff0c;并记录最大层级&#xff1b; 2.层级自下而上的递归&#xff0c;赋值父节点和统计金额类的字段&…

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

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

比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 天开发出健康码…

软件设计师 -主观题总结

文章目录1.数据流图1.1.补充外部实体名称1.2.补充数据存储1.3. 补充数据流图&#xff0c;缺失数据流图、起点、终点1.4.选考2.数据库设计&#xff08;ER图&#xff09;2.1.补充中联系关联的对象及联系的类型&#xff08;概念模式设计&#xff09;2.2.补充逻辑结构设计2.3.选考3…

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

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

达梦数据库连接(单机、多实例、多数据源版本)

文章目录1. 基础版本2. 多实例版本3. 多数据源达梦多实例1. 基础版本 spring:datasource:driver-class-name: dm.jdbc.driver.DmDriverurl: jdbc:dm://192.168.xxx.86:xxx/DAMENG?serverTimezoneGMT%2B8username: usernamepassword: password2. 多实例版本 spring:datasourc…

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

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