当前位置: 首页 > news >正文

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工具,传什么都能导出

前言 如题&#xff0c;这个小玩意&#xff0c;就是不限制你查的是哪张表&#xff0c;用的是什么类。 我直接一把梭&#xff0c;嘎嘎给你一顿导出。 我知道&#xff0c;这是很多人都想过的&#xff0c; 至少我就收到很多人问过我这个类似的问题。 我也跟他们说了&#xff0c;但…...

【Linux详解】——进程控制(创建、终止、等待、替换)

&#x1f4d6; 前言&#xff1a;本期介绍进程控制&#xff08;创建、终止、等待、替换&#xff09;。 目录&#x1f552; 1. 进程创建&#x1f558; 1.1 fork函数初识&#x1f558; 1.2 fork的返回值问题&#x1f558; 1.3 写时拷贝&#x1f558; 1.4 创建多个进程&#x1f552…...

HummerRisk V0.9.1:操作审计增加百度云,增加主机检测规则及多处优化

HummerRisk V0.9.0发布&#xff1a;增加RBAC 资源拓扑图&#xff0c;首页新增检查的统计数据&#xff0c;云检测、漏洞、主机等模块增加规则&#xff0c;对象存储增加京东云&#xff0c;操作审计增加金山云&#xff0c;镜像仓库新增设置别名。 感谢社区中小伙伴们的反馈&#…...

Rust入门(十六):手写web服务器和线程池

这一章将实现一个手写的 web server 和 多线程的服务器&#xff0c;用到之前学到的所有特性 简单的web server 作为一个 web 服务器&#xff0c;我们首先要能接收到请求&#xff0c;目前市面上的 web 服务大多数都是基于 HTTP 和 HTTPS 协议的&#xff0c;而他们有是基于 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.代码展示 整理不易&#xff0c;欢迎一键三连&#xff01;&#xff01;&#xff01; 1. YOLO简介 YOLO&#xff08;You Only Look Once&#xff09;是一种流行的目标检测和图像分割模型&#xff0c;由华盛顿大学的 Joseph Redmon 和 Al…...

基于linux内核的驱动开发

1 字符设备驱动框架 1.1字符设备 定义&#xff1a;只能以一个字节一个字节的方式读写的设备&#xff0c;不能随机的读取设备中中的某一段数据&#xff0c;读取数据需要按照先后顺序。&#xff08;字符设备是面向字节流的&#xff09; 常见的字…...

找不到工作的测试员一大把,大厂却招不到优秀软件测试员?高薪难寻测试工程师。

测试工程师招了快一个月了&#xff0c;实在招不到合适的&#xff0c;已经在被解雇的边缘了。。。” 初级测试工程师非常多&#xff0c;但真正掌握测试思维、能力强的优秀测试太少了&#xff01; 据我所知&#xff0c; 当下的测试人员不少状态都是这样的&#xff1a; 在工作中…...

buuctf Basic

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

赛狐ERP|亚马逊产品缺货怎么办?该如何补救?

由于物流时效的延长&#xff0c;运输成本的增加&#xff0c;亚马逊的仓储限制等各种原因&#xff0c;断货问题很常成为亚马逊卖家的普遍困扰。那么亚马逊产品缺货应该怎么办&#xff01;1、提高产品价格&#xff1a;除了卖自己的Listing此外&#xff0c;提高产品价格也是一种保…...

《Elasticsearch源码解读与优化实战》张超-读书笔记

写在前面 好久没更新博客了&#xff0c;应届狗没办法啊╮(╯▽╰)╭为了秋招搞了小半年&#xff0c;从去年5月到现在搞了两段实习&#xff08;京东、游戏公司&#xff09;&#xff0c;最终年前拿到一家还不错的offer&#xff0c;现在已经入职实习了&#xff0c;不出意外的话以…...

编码踩坑——运行时报错java.lang.NoSuchMethodError / 同名类加载问题 / 双亲委派【建议收藏】

本篇介绍一个实际遇到的排查异常的case&#xff0c;涉及的知识点包括&#xff1a;类加载机制、jar包中的类加载顺序、JVM双亲委派模型、破坏双亲委派模型及自定义类加载器的代码示例&#xff1b;问题背景业务版本&#xff0c;旧功能升级&#xff0c;原先引用的一个二方包中的du…...

软件测试选Python还是Java?

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

“2023数据安全智能化中国行”活动,开幕即高能

工信部等16部门近日发布的《关于促进数据安全产业发展的指导意见》提出&#xff0c;到2025年&#xff0c;数据安全产业基础能力和综合实力明显增强&#xff0c;数据安全产业规模超过1500亿元&#xff0c;年复合增长率超过30%。到2035年&#xff0c;数据安全产业进入繁荣成熟期。…...

机器人操作规划——Deep Visual Foresight for Planning Robot Motion(2017 ICRA)

1 简介 model-based RL方法&#xff0c;预测Action对图像的变化&#xff0c;以push任务进行研究。 采用完全自监督的学习方式&#xff0c;不需要相机标定、3D模型、深度图像和物理仿真。 2 数据集 采用几百个物体、10个7dof机械臂采集了包括5万个push attempts的数据集。 每…...

go 连接redis集群

最近用redis shake做redis数据迁移&#xff0c;由于redis提供的客户端没有用于查看集群的工具&#xff0c;且我部署的redis集群是基于k8s来构建的&#xff0c;没有使用ingress做转发&#xff0c;所以只能在k8s内部访问集群&#xff0c;于是我先用gogin框架编写了访问redis集群的…...

LeetCode 146. LRU 缓存

原题链接 难度&#xff1a;middle\color{orange}{middle}middle 题目描述 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCacheLRUCacheLRUCache 类&#xff1a; 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++类和对象,初见类

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

Redis常用数据结构及应用场景

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

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象&#xff0c;只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意&#xff1a;它移动的位置必须是相连的有内容的单元格…...

排序算法总结(C++)

目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指&#xff1a;同样大小的样本 **&#xff08;同样大小的数据&#xff09;**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...

自然语言处理——文本分类

文本分类 传统机器学习方法文本表示向量空间模型 特征选择文档频率互信息信息增益&#xff08;IG&#xff09; 分类器设计贝叶斯理论&#xff1a;线性判别函数 文本分类性能评估P-R曲线ROC曲线 将文本文档或句子分类为预定义的类或类别&#xff0c; 有单标签多类别文本分类和多…...

如何在Windows本机安装Python并确保与Python.NET兼容

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…...