spring boot导入导出excel,集成EasyExcel
一、安装依赖
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.2.0</version></dependency>
二、新建导出工具类
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.2.0</version></dependency>
三、新建实体类
package com.example.springbootclickhouse.Excel;import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.example.springbootclickhouse.ExcelValidTools.ExcelValid;
import com.example.springbootclickhouse.ExcelValidTools.NumberValid;
import com.example.springbootclickhouse.utils.GenderConverter;
import lombok.*;import java.io.Serializable;
import java.time.LocalDateTime;@Data
@AllArgsConstructor
@NoArgsConstructor
public class StudentExcel implements Serializable {private static final long serialVersionUID = 1L;@ExcelProperty("姓名")@ColumnWidth(20)@ExcelValid(message = "姓名列不能有空数据!")private String name;@ExcelProperty("年龄")@ColumnWidth(20)@NumberValid(message = "年龄不得小于0")private Integer age;@ExcelProperty(value = "性别",converter = GenderConverter.class)@ColumnWidth(20)private Integer gender;@ExcelProperty("日期")@ColumnWidth(20)private LocalDateTime date;}
@ExcelProperty: 核心注解,value属性可用来设置表头名称,converter属性可以用来设置类型转换器;
@ColumnWidth: 用于设置表格列的宽度;
@DateTimeFormat: 用于设置日期转换格式;
@NumberFormat: 用于设置数字转换格式。
四、如果需要有字段进行转换的,则为新建转换类,并在实体类上加注解
1、实体类上加如下
@ExcelProperty(value = "性别",converter = GenderConverter.class)
2、新建枚举类
package com.example.springbootclickhouse.ExcelEnum;import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;import java.util.stream.Stream;@AllArgsConstructor
@Getter
public enum GenderEnum {/*** 未知*/UNKNOWN(0, "未知"),/*** 男性*/MALE(1, "男性"),/*** 女性*/FEMALE(2, "女性");private final Integer value;@JsonFormatprivate final String description;public static GenderEnum convert(Integer value) {
// 用于为给定元素创建顺序流
// values:获取枚举类型的对象数组return Stream.of(values()).filter(bean -> bean.value.equals(value)).findAny().orElse(UNKNOWN);}public static GenderEnum convert(String description) {return Stream.of(values()).filter(bean -> bean.description.equals(description)).findAny().orElse(UNKNOWN);}
}
3、新建转换器类
package com.example.springbootclickhouse.utils;import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.converters.ReadConverterContext;
import com.alibaba.excel.converters.WriteConverterContext;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.data.WriteCellData;import com.example.springbootclickhouse.ExcelEnum.GenderEnum;public class GenderConverter implements Converter<Integer> {@Overridepublic Class<?> supportJavaTypeKey() {// 实体类中对象属性类型return Integer.class;}@Overridepublic CellDataTypeEnum supportExcelTypeKey() {// Excel中对应的CellData(单元格数据)属性类型return CellDataTypeEnum.STRING;}/*** 将单元格里的数据转为java对象,也就是女转成2,男转成1,用于导入excel时对性别字段进行转换* */@Overridepublic Integer convertToJavaData(ReadConverterContext<?> context) throws Exception {// 从CellData中读取数据,判断Excel中的值,将其转换为预期的数值return GenderEnum.convert(context.getReadCellData().getStringValue()).getValue();}/*** 将java对象转为单元格数据,也就是2转成女,1转成男,用于导出excel时对性别字段进行转换* */@Overridepublic WriteCellData<?> convertToExcelData(WriteConverterContext<Integer> context) throws Exception {// 判断实体类中获取的值,转换为Excel预期的值,并封装为CellData对象return new WriteCellData<>(GenderEnum.convert(context.getValue()).getDescription());}
}
五、导入时,数据进行验证的话
1、新建注解
package com.example.springbootclickhouse.ExcelValidTools;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExcelValid {String message() default "导入有未填入的字段";
}
2、新建验证类
package com.example.springbootclickhouse.ExcelValidTools;import java.lang.reflect.Field;
import java.util.Objects;public class ExcelImportValid {/*** Excel导入字段校验* @param object 校验的JavaBean 其属性须有自定义注解*/public static void valid(Object object,Integer rowIndex) throws Exception {Field[] fields = object.getClass().getDeclaredFields();for (Field field : fields) {//设置可访问field.setAccessible(true);//属性的值Object fieldValue = null;try {fieldValue = field.get(object);} catch (IllegalAccessException e) {throw new Exception("第" + rowIndex + "行" + field.getAnnotation(ExcelValid.class).message(),e);}//是否包含必填校验注解boolean isExcelValid = field.isAnnotationPresent(ExcelValid.class);if (isExcelValid && Objects.isNull(fieldValue)) {throw new Exception("excel中第" + rowIndex + "行的" + field.getAnnotation(ExcelValid.class).message());}else if(isExcelValid && !(fieldValue instanceof Integer)){throw new Exception("excel中第" + rowIndex + "行的类型不正确" + field.getAnnotation(ExcelValid.class).message());}}}public static void validNumber(Object object,Integer rowIndex) throws Exception {Field[] fields = object.getClass().getDeclaredFields();for (Field field : fields) {//设置可访问field.setAccessible(true);//属性的值Object fieldValue = null;try {fieldValue = field.get(object);} catch (IllegalAccessException e) {throw new Exception("第" + rowIndex + "行" + field.getAnnotation(NumberValid.class).message(),e);}//是否包含必填校验注解boolean isExcelValid = field.isAnnotationPresent(NumberValid.class);if (isExcelValid && (Integer)fieldValue<=0) {throw new Exception("excel中第" + rowIndex + "行的" + field.getAnnotation(NumberValid.class).message());}}}
}
3、新建监听器类
package com.example.springbootclickhouse.ExcelValidTools;import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.example.springbootclickhouse.Excel.StudentExcel;
import lombok.Getter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;import static com.alibaba.druid.sql.dialect.mysql.ast.clause.MySqlFormatName.JSON;@Slf4j
public class StudentListener extends AnalysisEventListener<StudentExcel> {private static final int BATCH_COUNT = 500;@GetterList<StudentExcel> list=new ArrayList<>(BATCH_COUNT);@Override@SneakyThrowspublic void invoke(StudentExcel studentExcel, AnalysisContext analysisContext) {log.info("数据校验:"+studentExcel);ExcelImportValid.valid(studentExcel,analysisContext.readRowHolder().getRowIndex()+1);ExcelImportValid.validNumber(studentExcel,analysisContext.readRowHolder().getRowIndex()+1);//可不用
// list.add(studentExcel);
// if (list.size() >= BATCH_COUNT) {
// log.info("已经解析"+list.size()+"条数据");
// list.clear();
// }}@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {}}
4、在实体类上使用注解@ExcelValid(message = “姓名列不能有空数据!”),同时在导入时新增
.registerReadListener(new StudentListener())
五、如果要求导出的excel加下拉选项框的话
1、新建导出处理类
package com.example.springbootclickhouse.ExcelHandler;
import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class CustomSheetWriteHandler implements SheetWriteHandler {/*** 想实现Excel引用其他sheet页数据作为单元格下拉选项值,* 需要重写该方法** @param writeWorkbookHolder* @param writeSheetHolder*/@Overridepublic void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {// 构造样例数据,该数据可根据实际需要,换成业务数据// 实际数据可通过构造方法,get、set方法等由外界传入List<String> selectDataList = new ArrayList<>();for (int i = 0; i < 100; i++) {selectDataList.add("下拉选项" + i);}// 构造下拉选项单元格列的位置,以及下拉选项可选参数值的map集合// key:下拉选项要放到哪个单元格,比如A列的单元格那就是0,C列的单元格,那就是2// value:key对应的那个单元格下拉列表里的数据项,比如这里就是下拉选项1..100Map<Integer, List<String>> selectParamMap = new HashMap<>();selectParamMap.put(0, selectDataList);// 获取第一个sheet页Sheet sheet = writeSheetHolder.getCachedSheet();// 获取sheet页的数据校验对象DataValidationHelper helper = sheet.getDataValidationHelper();// 获取工作簿对象,用于创建存放下拉数据的字典sheet数据页Workbook workbook = writeWorkbookHolder.getWorkbook();// 迭代索引,用于存放下拉数据的字典sheet数据页命名int index = 1;for (Map.Entry<Integer, List<String>> entry : selectParamMap.entrySet()) {// 设置存放下拉数据的字典sheet,并把这些sheet隐藏掉,这样用户交互更友好String dictSheetName = "dict_hide_sheet" + index;Sheet dictSheet = workbook.createSheet(dictSheetName);// 隐藏字典sheet页workbook.setSheetHidden(index++, true);// 设置下拉列表覆盖的行数,从第一行开始到最后一行,这里注意,Excel行的// 索引是从0开始的,我这边第0行是标题行,第1行开始时数据化,可根据实// 际业务设置真正的数据开始行,如果要设置到最后一行,那么一定注意,// 最后一行的行索引是1048575,千万别写成1048576,不然会导致下拉列表// 失效,出不来CellRangeAddressList infoList = new CellRangeAddressList(1, 1048575, entry.getKey(), entry.getKey());int rowLen = entry.getValue().size();for (int i = 0; i < rowLen; i++) {// 向字典sheet写数据,从第一行开始写,此处可根据自己业务需要,自定// 义从第几行还是写,写的时候注意一下行索引是从0开始的即可dictSheet.createRow(i).createCell(0).setCellValue(entry.getValue().get(i));}// 设置关联数据公式,这个格式跟Excel设置有效性数据的表达式是一样的String refers = dictSheetName + "!$A$1:$A$" + entry.getValue().size();Name name = workbook.createName();name.setNameName(dictSheetName);// 将关联公式和sheet页做关联name.setRefersToFormula(refers);// 将上面设置好的下拉列表字典sheet页和目标sheet关联起来DataValidationConstraint constraint = helper.createFormulaListConstraint(dictSheetName);DataValidation dataValidation = helper.createValidation(constraint, infoList);sheet.addValidationData(dataValidation);}}
}
2、在导出代码注册
EasyExcel.write(response.getOutputStream()).registerWriteHandler(new CustomSheetWriteHandler()).head(StudentExcel.class).sheet("sheet1").doWrite(userList);
相关文章:
spring boot导入导出excel,集成EasyExcel
一、安装依赖 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.2.0</version></dependency>二、新建导出工具类 <dependency><groupId>com.alibaba</groupId>&…...
【错误解决方案】ModuleNotFoundError: No module named ‘zarr‘
1. 错误提示 在python程序,尝试导入一个名为zarr的模块,但Python提示找不到这个模块。 错误提示:ModuleNotFoundError: No module named ‘zarr‘ 2. 解决方案 这可能是因为你尚未安装这个模块或者安装过程中出现了问题。 zarr是一个用于存…...
什么是集成测试?
什么是集成测试 集成测试(Integration Testing),也叫组装测试或联合测试。在单元测试的基础上,将所有模块按照设计要求(如根据结构图)组装成为子系统或系统,进行集成测试。 集成测试ÿ…...
Linux———— 运算命令
Shell与其他编程语言一样,支持多种类型的运算符,包括: 算术运算符:用于执行数学运算,例如加法、减法、乘法和除法。 关系运算符:用于比较两个值之间的关系,例如相等、大于、小于等。 布尔运算…...
批量去除pdf每一页相同未知的同样的内容
例如我想去除每一页右下角的www.alevelcollege.com ①打开acrobat pro ②编辑文件和图像 ③ctrlF输入字符串www.alevelcollege.com替换为空 ④鼠标点击替换 ⑤回车键按下不放,会自动翻页,直到翻页到最后一页。...
HCIA数据通信——静态路由
之前的文章中我提到过静态路由: 数据通信——网络层(路由器以及数据转发流程)_路由器如何转发数据_咕噜跳的博客-CSDN博客这里只做一些简单描述。 路由器关注的是网络之间的通信。路由器以自身为中心,考虑的是如何将数据发送到目…...
Fourier分析导论——第2章——Fourier级数的基本属性(E.M. Stein R. Shakarchi)
第 2 章 Fourier级数的基本属性(Basic Properties of Fourier Series) Nearly fifty years had passed without any progress on the question of analytic representation of an arbitrary function, when an assertion of Fourier threw new light on the subject. Thus…...
redis实现分布式延时队列
文章目录 延时队列简介应用场景案例:考虑:实现:整体思路:具体实现生产者消费者 运行结果 redis分布式延时队列优势redis分布式延时队列劣势 延时队列简介 延时队列是一种特殊的消息队列,它允许将消息在一定的延迟时间…...
Spring AOP源码解读
今天我们来分析Spring中AOP的源码,主要是关于SpringAOP是如何发挥作用的。 前期准备 首先我们需要有一个Spring AOP项目,添加好了SpringAOP的依赖。 <dependency><groupId>org.springframework</groupId><artifactId>spring-co…...
JavaScript基础入门01
目录 1.初识 JavaScript 1.1JavaScript 是什么 1.2发展历史 1.3JavaScript 和 HTML 和 CSS 之间的关系 2.JavaScript 的组成 3.前置知识 3.1第一个程序 4.JavaScript 的书写形式 4.1 行内式 4.2. 内嵌式 4.3.外部式 5.注释 6.输入输出 6.1输入: prompt 6.2输出: …...
yum 命令
基本语法 yum [选项] [参数] 选项说明 -y 对所有提问都回答“yes” 参数说明 实操 yum list | grep firefox yum -y remove firefox yum -y install firefox...
Nginx 部署多个安全域名,多个服务【工作记录】
以下是本人通过Docker 部署的Nginx挂载出来的文件目录 先看下 nginx.conf 配置文件内容:如下 ps:当前文件就是安装后的初始内容,无修改。主要关注最后一行 include /etc/nginx/conf.d/*.conf;表示引入其他目录下的.conf配置文件;…...
性能测试QPS+TPS+事务基础知识分析
本篇文章是性能测试基础篇,主要介绍了性能测试中对QPSTPS事务的基础知识分析,有需要的朋友可以借鉴参考下,希望可以对广大读者有所帮助 事务 就是用户某一步或几步操作的集合。不过,我们要保证它有一个完整意义。比如用户对某一…...
PSP - 蛋白质复合物 AlphaFold2 Multimer MSA Pairing 逻辑与优化
欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/134144591 在蛋白质复合物结构预测中,当序列 (Sequence) 是异源多链时,无论是AB,还是AABB,都需要 …...
C++中vec.size()-1的坑
问题描述:如下代码, #include <iostream> #include <vector>using namespace std;int main() {vector<int> vec {};for (int i 0; i < vec.size() - 1; i) {cout << "i " << i << ", vec[i] …...
Flask Shell 操作 SQLite
一、前言 这段时间在玩Flask Web,发现用Flask Shell去操作SQLite还是比较方便的。今天简单地介绍一下。 二、SQLite SQLite是一种嵌入式数据库,它的数据库就是一个文件,处理速度快,经常被集成在各种应用程序中,在IO…...
Mybatis—XML配置文件、动态SQL
学习完Mybatis的基本操作之后,继续学习Mybatis—XML配置文件、动态SQL。 目录 Mybatis的XML配置文件XML配置文件规范XML配置文件实现MybatisX的使用 Mybatis动态SQL动态SQL-if条件查询 \<if\>与\<where\>更新员工 \<set\>小结 动态SQL-\<forea…...
excel求差公式怎么使用?
利用excel求差,可能有许多的小伙伴已经会了,不过还是存在一些不太熟悉的朋友们,所以这里有必要讲解一下。其实求差的实现主要就是一个公式,就是用一个单元格中的数字“减去”另一个单元格中的数字“等于”第三个单元格。此公式掌握…...
高效分割分段视频:提升您的视频剪辑能力
在数字媒体时代,视频剪辑已经成为一项重要的技能。无论是制作个人影片、广告还是其他类型的视频内容,掌握高效的视频剪辑技巧都是必不可少的。本文将介绍如何引用云炫AI智剪高效地分割和分段视频,以提升您的视频剪辑能力。以下是详细的操作步…...
【c++|opencv】二、灰度变换和空间滤波---2.直方图和均衡化
every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 图像直方图、直方图均衡化 1. 图像直方图 #include <iostream> #include <opencv2/opencv.hpp>using namespace cv; using namespace std;…...
Arduino高性能WebSocket客户端库深度解析
1. Arduino-Websocket-Fast 库深度解析:面向嵌入式物联网的高性能 WebSocket 客户端实现1.1 设计动因与工程定位在嵌入式物联网(IoT)系统开发中,WebSocket 协议因其全双工、低开销、长连接特性,已成为设备与云平台间实…...
SDMatte边缘精修效果展示:发丝级分离、玻璃折射保留、薄纱纹理还原等高清案例图集
SDMatte边缘精修效果展示:发丝级分离、玻璃折射保留、薄纱纹理还原等高清案例图集 1. 惊艳效果预览 SDMatte作为专业级AI抠图工具,在处理复杂边缘和透明物体方面展现出惊人的能力。下面我们通过一组真实案例,展示它在不同场景下的表现。 1…...
终极简单教程:如何使用bilibili-parse免费获取B站视频资源
终极简单教程:如何使用bilibili-parse免费获取B站视频资源 【免费下载链接】bilibili-parse bilibili Video API 项目地址: https://gitcode.com/gh_mirrors/bi/bilibili-parse 想要快速获取B站视频资源却不知道从何入手?bilibili-parse作为一款简…...
HY-Motion 1.0保姆级教程:解决CUDA OOM、Prompt截断等常见问题
HY-Motion 1.0保姆级教程:解决CUDA OOM、Prompt截断等常见问题 1. 前言:为什么需要这篇教程 你是不是也遇到过这样的情况:好不容易下载了HY-Motion 1.0这个强大的3D动作生成模型,准备大展身手,结果一运行就遇到CUDA内…...
LabelMe高级应用:如何利用AI辅助标注提升效率300%
LabelMe高级应用:如何利用AI辅助标注提升效率300% LabelMe是一款强大的图像标注工具,支持多边形、矩形、圆形、线条、点和图像级标记等多种标注方式。对于AI训练数据准备工作而言,高效的标注工具能显著提升工作流效率。本文将详细介绍如何利…...
突破Windows多显示器显示壁垒:SetDPI重新定义显示体验
突破Windows多显示器显示壁垒:SetDPI重新定义显示体验 【免费下载链接】SetDPI 项目地址: https://gitcode.com/gh_mirrors/se/SetDPI 在当今多设备协同工作的时代,显示器已成为我们与数字世界交互的重要窗口。然而,当程序员小李将笔…...
如何突破Cursor试用限制?3种创新方案全解析
如何突破Cursor试用限制?3种创新方案全解析 【免费下载链接】go-cursor-help 解决Cursor在免费订阅期间出现以下提示的问题: Youve reached your trial request limit. / Too many free trial accounts used on this machine. Please upgrade to pro. We have this …...
基于CYBER-VISION零号协议构建智能技术文档翻译与摘要系统
基于CYBER-VISION零号协议构建智能技术文档翻译与摘要系统 1. 引言 对于很多开发者来说,阅读英文技术文档是件挺头疼的事。尤其是遇到一些前沿的开源项目,官方文档全是英文,里面还夹杂着大量的专业术语和复杂的配置说明。有时候,…...
3步搞定Qobuz高品质音乐下载:QobuzDownloaderX-MOD完全指南 [特殊字符]
3步搞定Qobuz高品质音乐下载:QobuzDownloaderX-MOD完全指南 🎵 【免费下载链接】QobuzDownloaderX-MOD Downloads streams directly from Qobuz. Experimental refactoring of QobuzDownloaderX by AiiR 项目地址: https://gitcode.com/gh_mirrors/qo/…...
追踪Elsevier审稿进度:开源工具如何提升学术投稿效率
追踪Elsevier审稿进度:开源工具如何提升学术投稿效率 【免费下载链接】Elsevier-Tracker 项目地址: https://gitcode.com/gh_mirrors/el/Elsevier-Tracker 学术出版流程中,审稿进度的不确定性常给研究者带来困扰。Elsevier作为全球领先的学术出版…...
