Springboot 我随手封装了一个万能的导出excel工具,传什么都能导出
前言
如题,这个小玩意,就是不限制你查的是哪张表,用的是什么类。
我直接一把梭,嘎嘎给你一顿导出。
我知道,这是很多人都想过的, 至少我就收到很多人问过我这个类似的问题。
我也跟他们说了,但是他们就是不动手,其实真的很简单。
不动手怎么办? 我出手呗。
不多说开搞 。
正文
玩法很简单,我之前有写过一篇利用csv文件内容格式做excel文件导出的。
如果没有看过的,还等什么,现在就去看看:
Springboot 那年我双手插兜,手写一个excel导出
要实现的效果 :
类是不确定的 ,User ? Student ? District ? 不确定。但是呢我们封装出来的函数,要足够支撑不同的类,我们自动去读取遍历list ,然后导出生成文件。
核心的思路是什么 ?
其实就还是利用csv文件的内容格式本质 ,看这两幅图 :
我们要实现万能的类导出excel !!!
思路是什么 :
① 我们从不确定的类 的集合list 中,取出 里面的类。
反射一手,拿出里面的属性名, 做第一行表格行标题名称拼接。
②拼接内容
因为类不确定,那么我们就采取反射把类全部字段属性作为key丢到map里面,
同时把值丢到value里面。这样我们拼接内容的时候只需要根据map 嘎嘎一顿遍历 拼接即可。
1.依赖
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.15</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-scratchpad</artifactId><version>3.15</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.69</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.5</version></dependency>
2. 核心的工具类,函数我都封装好了
MyCsvFileUtil.java
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.*;/*** @author JCccc* @Remark 是我*/
@Slf4j
public class MyCsvFileUtil {public static final String FILE_SUFFIX = ".csv";public static final String CSV_DELIMITER = ",";public static final String CSV_TAIL = "\r\n";protected static final String DATE_STR_FILE_NAME = "yyyyMMddHHmmssSSS";/*** 将字符串转成csv文件*/public static void createCsvFile(String savePath, String contextStr) throws IOException {File file = new File(savePath);//创建文件file.createNewFile();//创建文件输出流FileOutputStream fileOutputStream = new FileOutputStream(file);//将指定字节写入此文件输出流fileOutputStream.write(contextStr.getBytes("gbk"));fileOutputStream.flush();fileOutputStream.close();}/*** 写文件** @param fileName* @param content*/public static void writeFile(String fileName, String content) {FileOutputStream fos = null;OutputStreamWriter writer = null;try {fos = new FileOutputStream(fileName, true);writer = new OutputStreamWriter(fos, "GBK");writer.write(content);writer.flush();} catch (Exception e) {log.error("写文件异常|{}", e);} finally {if (fos != null) {IOUtils.closeQuietly(fos);}if (writer != null) {IOUtils.closeQuietly(writer);}}}/*** 构建文件名称* @param dataList* @return*/public static String buildCsvFileFileName(List dataList) {return dataList.get(0).getClass().getSimpleName() + new SimpleDateFormat(DATE_STR_FILE_NAME).format(new Date()) + FILE_SUFFIX;}/*** 构建excel 标题行名* @param dataList* @return*/public static String buildCsvFileTableNames(List dataList) {Map<String, Object> map = toMap(dataList.get(0));StringBuilder tableNames = new StringBuilder();for (String key : map.keySet()) {tableNames.append(key).append(MyCsvFileUtil.CSV_DELIMITER);}return tableNames.append(MyCsvFileUtil.CSV_TAIL).toString();}/*** 构建excel内容* @param dataLists* @return*/public static String buildCsvFileBodyMap(List dataLists) {//不管你传什么玩意,我都给你反射一手,搞成MapList<Map<String, Object>> mapList = new ArrayList<>();for (Object o : dataLists) {mapList.add(toMap(o));}//然后利用csv格式,对着map嘎嘎一顿拼接数据StringBuilder lineBuilder = new StringBuilder();for (Map<String, Object> rowData : mapList) {for (String key : rowData.keySet()) {Object value = rowData.get(key);if (Objects.nonNull(value)) {lineBuilder.append(value).append(MyCsvFileUtil.CSV_DELIMITER);} else {lineBuilder.append("--").append(MyCsvFileUtil.CSV_DELIMITER);}}lineBuilder.append(MyCsvFileUtil.CSV_TAIL);}return lineBuilder.toString();}/*** 类转map* @param entity* @param <T>* @return*/public static<T> Map<String, Object> toMap(T entity){Class<? extends Object> bean = entity.getClass();Field[] fields = bean.getDeclaredFields();Map<String, Object> map = new HashMap<>(fields.length);for(Field field:fields){try {if(!"serialVersionUID".equals(field.getName())){String methodName = "get"+field.getName().substring(0, 1).toUpperCase()+field.getName().substring(1);Method method = bean.getDeclaredMethod(methodName);Object fieldValue = method.invoke(entity);map.put(field.getName(),fieldValue);}} catch (Exception e) {log.warn("toMap() Exception={}",e.getMessage());}}return map;}
}
代码注意点(各种小封装):
①类转map
② 反射转map 取字段属性名 拼接 标题
③ 针对list<不确定类> 转化成 list<map> ,然后拼接excel内容
测试代码:
@RequestMapping("/createCsvFileJcTest")public void createCsvFileJcTest() {//类不确定 随便怎么传都行List<District> districts = districtService.queryByParentCodes(Arrays.asList("110100"));//存放地址&文件名String fileName = "D:\\mycsv\\"+MyCsvFileUtil.buildCsvFileFileName(districts);//创建表格行标题String tableNames = MyCsvFileUtil.buildCsvFileTableNames(districts);//创建文件MyCsvFileUtil.writeFile(fileName, tableNames);//写入数据String contentBody = MyCsvFileUtil.buildCsvFileBodyMap(districts);//调用方法生成MyCsvFileUtil.writeFile(fileName, contentBody);}
看看效果:
导出的excel文件内容:
接下来换个类玩玩:
然后导出看看效果:
可以看到数据导出也是OK的:
没错就是这么简单, 当然也是抛转引玉, 希望大家看了这篇文章,可以借鉴这些反射的函数玩法,做更多的好玩的封装,比如加上一些自定义注解的解析,比如加上一些前后置拦截器拓展等等。
好了该篇就到这。
ps:
Springboot 最简单的结合MYSQL数据实现EXCEL表格导出及数据导入
Springboot 指定自定义模板导出Excel文件
SpringBoot 导出多个Excel文件,压缩成.zip格式下载
Springboot 获取导入的Excel文件的sheet表 列名
Springboot 导入导出Excel ,一对多关系,复合表格、合并单元格数据
Springboot 那年我双手插兜,手写一个excel导出
相关文章:

Springboot 我随手封装了一个万能的导出excel工具,传什么都能导出
前言 如题,这个小玩意,就是不限制你查的是哪张表,用的是什么类。 我直接一把梭,嘎嘎给你一顿导出。 我知道,这是很多人都想过的, 至少我就收到很多人问过我这个类似的问题。 我也跟他们说了,但…...

【Linux详解】——进程控制(创建、终止、等待、替换)
📖 前言:本期介绍进程控制(创建、终止、等待、替换)。 目录🕒 1. 进程创建🕘 1.1 fork函数初识🕘 1.2 fork的返回值问题🕘 1.3 写时拷贝🕘 1.4 创建多个进程🕒…...

HummerRisk V0.9.1:操作审计增加百度云,增加主机检测规则及多处优化
HummerRisk V0.9.0发布:增加RBAC 资源拓扑图,首页新增检查的统计数据,云检测、漏洞、主机等模块增加规则,对象存储增加京东云,操作审计增加金山云,镜像仓库新增设置别名。 感谢社区中小伙伴们的反馈&#…...
Rust入门(十六):手写web服务器和线程池
这一章将实现一个手写的 web server 和 多线程的服务器,用到之前学到的所有特性 简单的web server 作为一个 web 服务器,我们首先要能接收到请求,目前市面上的 web 服务大多数都是基于 HTTP 和 HTTPS 协议的,而他们有是基于 TCP…...

数据结构——第二章 线性表(1)——顺序结构
线性表1. 线性表1.1 线性表的定义1.1.1 访问型操作1.1.2 加工型操作1.2 线性表的顺序存储结构1.2.1 定义顺序表数据类型方法11.2.2 定义顺序表数据类型方法21.3 顺序表的基本操作实现1.3.1 顺序表的初始化操作1.3.2 顺序表的插入操作1.3.3 顺序表的删除操作1.3.4 顺序表的更新操…...

YOLO 格式数据集制作
目录 1. YOLO简介 2.分割数据集准备 3.代码展示 整理不易,欢迎一键三连!!! 1. YOLO简介 YOLO(You Only Look Once)是一种流行的目标检测和图像分割模型,由华盛顿大学的 Joseph Redmon 和 Al…...
基于linux内核的驱动开发
1 字符设备驱动框架 1.1字符设备 定义:只能以一个字节一个字节的方式读写的设备,不能随机的读取设备中中的某一段数据,读取数据需要按照先后顺序。(字符设备是面向字节流的) 常见的字…...

找不到工作的测试员一大把,大厂却招不到优秀软件测试员?高薪难寻测试工程师。
测试工程师招了快一个月了,实在招不到合适的,已经在被解雇的边缘了。。。” 初级测试工程师非常多,但真正掌握测试思维、能力强的优秀测试太少了! 据我所知, 当下的测试人员不少状态都是这样的: 在工作中…...

buuctf Basic
buuctf Basic 1.Linux Labs 根据提示我们可以知道需要远程连接linux服务器,这里使用xshell进行如下配置 输入ssh的用户名root,密码123456 连接成功 构造命令 ls …/ 查看文件 查看flag cat …/flag.txt 为flag{8fee8783-1ed5-4b67-90eb-a1d603a0208…...

赛狐ERP|亚马逊产品缺货怎么办?该如何补救?
由于物流时效的延长,运输成本的增加,亚马逊的仓储限制等各种原因,断货问题很常成为亚马逊卖家的普遍困扰。那么亚马逊产品缺货应该怎么办!1、提高产品价格:除了卖自己的Listing此外,提高产品价格也是一种保…...
《Elasticsearch源码解读与优化实战》张超-读书笔记
写在前面 好久没更新博客了,应届狗没办法啊╮(╯▽╰)╭为了秋招搞了小半年,从去年5月到现在搞了两段实习(京东、游戏公司),最终年前拿到一家还不错的offer,现在已经入职实习了,不出意外的话以…...

编码踩坑——运行时报错java.lang.NoSuchMethodError / 同名类加载问题 / 双亲委派【建议收藏】
本篇介绍一个实际遇到的排查异常的case,涉及的知识点包括:类加载机制、jar包中的类加载顺序、JVM双亲委派模型、破坏双亲委派模型及自定义类加载器的代码示例;问题背景业务版本,旧功能升级,原先引用的一个二方包中的du…...

软件测试选Python还是Java?
目录 前言 1、先从一门语言开始 2、两个语言的区别 3、两个语言的测试栈技术 4、如何选择两种语言? 总结 前言 对于工作多年的从业者来说,同时掌握java和Python两门语言再好不过,可以大大增加找工作时的选择范围。但是对于转行的人或者…...

“2023数据安全智能化中国行”活动,开幕即高能
工信部等16部门近日发布的《关于促进数据安全产业发展的指导意见》提出,到2025年,数据安全产业基础能力和综合实力明显增强,数据安全产业规模超过1500亿元,年复合增长率超过30%。到2035年,数据安全产业进入繁荣成熟期。…...

机器人操作规划——Deep Visual Foresight for Planning Robot Motion(2017 ICRA)
1 简介 model-based RL方法,预测Action对图像的变化,以push任务进行研究。 采用完全自监督的学习方式,不需要相机标定、3D模型、深度图像和物理仿真。 2 数据集 采用几百个物体、10个7dof机械臂采集了包括5万个push attempts的数据集。 每…...
go 连接redis集群
最近用redis shake做redis数据迁移,由于redis提供的客户端没有用于查看集群的工具,且我部署的redis集群是基于k8s来构建的,没有使用ingress做转发,所以只能在k8s内部访问集群,于是我先用gogin框架编写了访问redis集群的…...
LeetCode 146. LRU 缓存
原题链接 难度:middle\color{orange}{middle}middle 题目描述 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCacheLRUCacheLRUCache 类: LRUCache(intcapacity)LRUCache(int capacity)LRUCache(intcapacity) 以 正整数 …...

【mac】在m2 mbp上通过Parallels Desktop安装ubuntu22.04
文章目录前言一、参考文章二、版本信息三、方法1:通过ubuntu官网提供的iso安装3.1 配置服务器3.2 安装图形界面四、方法2:通过Parallels Desktop提供的安装包五、 小工具5.1 调整应用栏图标大小5.2 ubuntu获取mac的剪切板5.3 调整terminal字体大小5.4 安装samba5.5 ubuntu连接m…...

C++类和对象,初见类
坚持看完,结尾有思维导图总结 这里写目录标题C语言和 C 的区别类的定义类的初认识类的内容访问限定符类的作用域类的实例化类中的 this 指针总结C语言和 C 的区别 C 的祖师爷除了在 C语言的基础上化简了一些复杂操作 更为重要的是,两个语言实现的过程是…...

Redis常用数据结构及应用场景
1.总体结构 Redis中的数据,总体上是键值对,不同数据类型指的是键值对中值的类型。 2.string类型 Redis中最基本的类型,它是key对应的一个单一值。二进制安全,不必担心由于编码等问题导致二进制数据变化。所以redis的string可以…...

网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...

2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...

Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...

自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...

python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...