超好用的【通用Excel导入功能】

2024-04-16 15:32

本文主要是介绍超好用的【通用Excel导入功能】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 一、需求
      • 1-1、下载模板(excel)
      • 1-2、数据填充并导入
      • 1-3、导入结果展示
      • 1-4、数据校验规则
    • 二、方案思路
    • 三、代码使用
      • 3-1、新建一个VO,比如你导入的字段是 `name`、`age`、`gender` 那么你的实体应该如下:
      • 3-2、新增一个ImportExcel接口的实现类,实现里面的 check 方法(这个接口下面讲解)
      • 3-3、调用
    • 四、代码思路讲解
      • 4-1、准备
      • 4-2、importCheck方法
      • 4-3、check 方法
      • 4-4、其它

之前写过一个简单的Excel导入功能,大家可以先看这个: https://www.bilibili.com/video/BV1kf4y1i761?p=5

最近接到一个需求,做一个Excel的批量导入功能,具体的步骤如下:


一、需求

1-1、下载模板(excel)

姓名(2-4个字符)年纪(1-150)性别(男/女)

1-2、数据填充并导入

姓名(2-4个字符)年纪(1-150)性别(男/女)
张三丰20
小道仙9724
慕容晓晓18女性

1-3、导入结果展示

在这里插入图片描述


1-4、数据校验规则

  • 姓名不能为空且只能是2-4个字符
  • 年纪不能为空且只能是1-150
  • 性别不能为空且只能是男/女
  • 导入的数据不能有两个同名,如果存在则都导入失败
  • 数据库如果有同名的人也不可以导入

二、方案思路

使用上面的Excel导入功能,把Excel模板数据解析成对应的 List<Map<String,Object>> 数据。

使用数据把对应的数据格式化成对应的实体,再依次循环按照条件去校验对应的数据。

其实除了导入数据校验规则之外,其它都是通用的,比如返回字段、解析excel并封装成bean,对异常数据进行处理等。


三、代码使用

3-1、新建一个VO,比如你导入的字段是 nameagegender 那么你的实体应该如下:

注:省略了 get 、set 、和空参构造方法

public class TestImportExcelVo {/*** 表头*/public final static String[] HEADER = {"name","age","gender"};/*** 姓名*/private String name;/*** 年纪*/private String age;/*** 性别*/private String gender;
}

可以看到唯一不同的就是多了一个常量HEADER,它的规则就是导入模板字段顺序


3-2、新增一个ImportExcel接口的实现类,实现里面的 check 方法(这个接口下面讲解)

@Service
public class TestImportExcelImpl implements ImportExcel<TestImportExcelVo> {@Overridepublic String[] check(ImportItem importItem, List<TestImportExcelVo> successResult, List<ImportItem> errorResult) {return new String[]{"1",""};}
}

3-3、调用

@RestController
public class ImportExcelController {@Autowiredpublic TestImportExcelImpl testImportExcelImpl;@PostMapping("/importExcel")public Object importExcel(MultipartFile file) {return testImportExcelImpl.importCheck(file, TestImportExcelVo.HEADER, TestImportExcelVo.class);}
}

四、代码思路讲解

其实就是看接口 ImportExcel 里面的两个方法。

4-1、准备

这里使用了两个bean如下(去掉了get/set)

/*** 导出错误结果集实体bean** 因为错误结果集需要多一个原因字段** @author 小道仙* @date 2021年8月4日*/
public class ImportItem<T> {private String errorReason;public T t;
}
/*** 导入Excel返回结果实体** @author 小道仙* @date 2021-08-04*/
public class ImportResultVo<T> {/*** 总行数*/private Integer totalRows;/*** 错误行数*/private Integer errorRows;/*** 成功行数*/private Integer successRows;/*** 失败结果集*/private List<T> errorResults;/*** 成功结果集*/private List<T> successResults;public ImportResultVo() {}public ImportResultVo(Integer totalRows,Integer errorRows,Integer successRows,List<T> errorResults,List<T> successResults) {this.totalRows = totalRows;this.errorRows = errorRows;this.successRows = successRows;this.errorResults =errorResults;this.successResults = successResults;}
}

4-2、importCheck方法

这是一个默认方法完成一些通用的功能,如:excel解析、实体bean封装等

default ImportResultVo importCheck(MultipartFile file, String[] header,Class clazz){// 从excel里面解析出来数据List<Map<String, Object>> maps;try {maps = ExcelUtils.importExcel(file, header);}catch (Exception e){logger.error("解析失败,数据模板不对",e);throw new RuntimeException("解析失败,数据模板不对");}if (CollectionUtils.isEmpty(maps)){return new ImportResultVo(0,0,0,null,null);}// 对数据进行逐步的验证int totalRows = 0;int successRows = 0;int errorRows = 0;List<T> successResult = new ArrayList<>(50);List<ImportItem> errorResult = new ArrayList<>(50);for (Map map : maps) {ImportItem<T> importItem = new ImportItem();totalRows ++;try {Object tmpT = JsonUtils.objectToPojo(map, clazz);importItem.setT((T)tmpT);}catch (Exception e) {errorRows ++;logger.error("bean转换失败", e);continue;}String[] check = check(importItem, successResult, errorResult);if ("1".equals(check[0])) {successRows ++;successResult.add(importItem.getT());}else if ("2".equals(check[0])) {errorRows ++;importItem.setErrorReason(check[1]);errorResult.add(importItem);}else if ("3".equals(check[0])){successRows --;errorRows ++;importItem.setErrorReason(check[1]);errorResult.add(importItem);}}return new ImportResultVo(totalRows,errorRows,successRows,errorResult,successResult);
}

4-3、check 方法

这是一个接口方法,需要自己去实现具体的校验规则

/**** @param t 当前需要校验的实体bean* @param successResult 已校验的正确结果集* @param errorResult 已校验错误的结果集* @return 第一个参数是校验结果,第二个是失败的原因*      1  成功*      2  正常失败(比如字段为空,字段格式不对,和数据库冲突等)*      3  异常失败(和之前已经成功的数据冲突,比如唯一性字段已经存在了)*      注:【异常失败】的时候,你需要在check方法里面去删除掉之前成功的数据,并把之前的数据插入到 errorResult 里面*/
String[] check(ImportItem t, List<T> successResult, List<ImportItem> errorResult);

4-4、其它

这里的excel导出工具类之前已经说过了,这里就简单的复制一下吧。

/*** Excel 导入* @param file 文件* @param keys 数据顺序*/
public static  List<Map<String, Object>>  importExcel(MultipartFile file, String[] keys) throws Exception{Workbook wb = null;String fileName = file.getOriginalFilename();if (fileName.endsWith("xls")) {POIFSFileSystem pois = new POIFSFileSystem(file.getInputStream());wb = new HSSFWorkbook(pois);} else if (fileName.endsWith("xlsx")) {wb = new XSSFWorkbook(file.getInputStream());}Sheet sheet = wb.getSheetAt(0);int rowCount = sheet.getPhysicalNumberOfRows();if (sheet.getRow( 1).getPhysicalNumberOfCells() != keys.length){throw new RuntimeException("导入的Excel和模板的列不匹配");}List<Map<String,Object>> result = new ArrayList<>();for (int i = 0; i < rowCount - 1; i++) {Row row = sheet.getRow(i + 1);Map<String,Object> tmp = new HashMap<>();for (int j = 0;j < keys.length; j++){Cell cell = row.getCell(j);if(cell == null) {tmp.put(keys[j], null);}else {// 把类型转行Springcell.setCellType(CellType.STRING);tmp.put(keys[j], cell.getStringCellValue());}}result.add(tmp);}return result;
}

视频看讲解地址:https://www.bilibili.com/video/BV1kf4y1i761

关注微信公众号回复:xdxFrameSimple 获取源码。

在这里插入图片描述

这篇关于超好用的【通用Excel导入功能】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/909179

相关文章

mysql表操作与查询功能详解

《mysql表操作与查询功能详解》本文系统讲解MySQL表操作与查询,涵盖创建、修改、复制表语法,基本查询结构及WHERE、GROUPBY等子句,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随... 目录01.表的操作1.1表操作概览1.2创建表1.3修改表1.4复制表02.基本查询操作2.1 SE

Java easyExcel实现导入多sheet的Excel

《JavaeasyExcel实现导入多sheet的Excel》这篇文章主要为大家详细介绍了如何使用JavaeasyExcel实现导入多sheet的Excel,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录1.官网2.Excel样式3.代码1.官网easyExcel官网2.Excel样式3.代码

Golang如何用gorm实现分页的功能

《Golang如何用gorm实现分页的功能》:本文主要介绍Golang如何用gorm实现分页的功能方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录背景go库下载初始化数据【1】建表【2】插入数据【3】查看数据4、代码示例【1】gorm结构体定义【2】分页结构体

Java Web实现类似Excel表格锁定功能实战教程

《JavaWeb实现类似Excel表格锁定功能实战教程》本文将详细介绍通过创建特定div元素并利用CSS布局和JavaScript事件监听来实现类似Excel的锁定行和列效果的方法,感兴趣的朋友跟随... 目录1. 模拟Excel表格锁定功能2. 创建3个div元素实现表格锁定2.1 div元素布局设计2.

HTML5实现的移动端购物车自动结算功能示例代码

《HTML5实现的移动端购物车自动结算功能示例代码》本文介绍HTML5实现移动端购物车自动结算,通过WebStorage、事件监听、DOM操作等技术,确保实时更新与数据同步,优化性能及无障碍性,提升用... 目录1. 移动端购物车自动结算概述2. 数据存储与状态保存机制2.1 浏览器端的数据存储方式2.1.

基于 HTML5 Canvas 实现图片旋转与下载功能(完整代码展示)

《基于HTML5Canvas实现图片旋转与下载功能(完整代码展示)》本文将深入剖析一段基于HTML5Canvas的代码,该代码实现了图片的旋转(90度和180度)以及旋转后图片的下载... 目录一、引言二、html 结构分析三、css 样式分析四、JavaScript 功能实现一、引言在 Web 开发中,

springboot下载接口限速功能实现

《springboot下载接口限速功能实现》通过Redis统计并发数动态调整每个用户带宽,核心逻辑为每秒读取并发送限定数据量,防止单用户占用过多资源,确保整体下载均衡且高效,本文给大家介绍spring... 目录 一、整体目标 二、涉及的主要类/方法✅ 三、核心流程图解(简化) 四、关键代码详解1️⃣ 设置

苹果macOS 26 Tahoe主题功能大升级:可定制图标/高亮文本/文件夹颜色

《苹果macOS26Tahoe主题功能大升级:可定制图标/高亮文本/文件夹颜色》在整体系统设计方面,macOS26采用了全新的玻璃质感视觉风格,应用于Dock栏、应用图标以及桌面小部件等多个界面... 科技媒体 MACRumors 昨日(6 月 13 日)发布博文,报道称在 macOS 26 Tahoe 中

Java使用HttpClient实现图片下载与本地保存功能

《Java使用HttpClient实现图片下载与本地保存功能》在当今数字化时代,网络资源的获取与处理已成为软件开发中的常见需求,其中,图片作为网络上最常见的资源之一,其下载与保存功能在许多应用场景中都... 目录引言一、Apache HttpClient简介二、技术栈与环境准备三、实现图片下载与保存功能1.

MybatisPlus service接口功能介绍

《MybatisPlusservice接口功能介绍》:本文主要介绍MybatisPlusservice接口功能介绍,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友... 目录Service接口基本用法进阶用法总结:Lambda方法Service接口基本用法MyBATisP