当前位置: 首页 > 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可以…...

C++虚继承内存布局

C菱形继承内存布局 编译器&#xff1a;Visual Studio 2019 关于如何查看内存布局 B class B { public:B(): _ib(10), _cb(B){cout << "B()" << endl;}B(int ib, char cb): _ib(ib), _cb(cb){cout << "B(int,char)" << endl;}vi…...

IO模型--从BIO、NIO、AIO到内核select、poll、epoll剖析

IO基本概述 IO的分类 IO以不同的维度划分&#xff0c;可以被分为多种类型&#xff1b;从工作层面划分成磁盘IO&#xff08;本地IO&#xff09;和网络IO&#xff1b; 也从工作模式上划分&#xff1a;BIO、NIO、AIO&#xff1b;从工作性质上分为阻塞式IO与非阻塞式IO&#xff1b…...

Zebec完成BNB Chain以及Near链上协议部署,多链化进程加速

从去年开始&#xff0c;Zebec 就开始以多链的形式来拓展自身的流支付生态&#xff0c;一方面向更多的区块链系统拓展自身流支付协议&#xff0c;即从Solana上向EVM链上对协议与通证等进行迁移与拓展。目前基本完成了在BNB Chain以及Near上的合约部署&#xff0c;且能够在这些EV…...

wpscan常见的使用方法

目录 简单介绍 暴力破解 信息收集 指定用户爆破 命令集合 简单介绍 Wordpress是一个以PHP和MySQL为平台的免费自由开源的博客软件和内容管理系统。 WPScan是Kali Linux默认自带的一款漏洞扫描工具&#xff0c;它采用Ruby编写&#xff0c;能够扫描WordPress网站中的多种安…...

Tree 底层源码实现(二叉树、递归、迭代)

树&#xff08;Tree&#xff09;是一种非线性数据结构&#xff0c;由一组节点和它们之间的边组成。在树中&#xff0c;每个节点都有零个或多个子节点&#xff0c;除了根节点外&#xff0c;每个节点都有且仅有一个父节点。树可以被用于许多应用程序&#xff0c;如文件系统、XML文…...

家政服务小程序实战教程13-接入客服

小程序在微信里使用&#xff0c;以其无需安装随用随走为特点。但是有个问题是&#xff0c;如果提供商品或者服务的&#xff0c;用户如果有问题往往希望平台的运营方给出专业的解答。为了满足这类需求&#xff0c;就需要我们提供客服接入的功能&#xff0c;用户可以点击客服图标…...

大白话高并发(三)

背景 高并发得第三篇&#xff0c;讲一讲压测吧&#xff0c;因为我的目的是模拟100万人同时来秒杀。 是不是真的要找100万个人 没必要 &#xff0c;你就算100万人掐着表在同一毫秒内把请求请求某一台机器&#xff0c;服务器也不可能在同一时间处理那么多请求&#xff0c;因为…...

vue全家桶(四)前端工程化

vue全家桶&#xff08;四&#xff09;前端工程化1.模块化的相关规范1.1模块化概述1.2模块化的分类A.浏览器端的模块化B.服务器端的模块化C.ES6模块化1.2.1 Node.js中通过bable体验ES6模块化1.2.2 ES6模块化的基本语法1.2.2.1 默认导出与默认导入1.2.2.2 按需导出与按需导入1.2.…...

超螺旋滑模控制(STA)

超螺旋滑模控制(Super Twisting Algorithm, STA) 超螺旋滑模控制又称超扭滑模控制&#xff0c;可以说是二阶系统中最好用的滑模控制方法。 系统模型 对于二阶系统可以建立具有标准柯西形式的微分方程组 {x˙1x2x˙2fg⋅u\begin{cases} \dot x_1 x_2 \\ \dot x_2 f g \cdo…...

NX二次开发编译时dll自动数字签名及拷贝

前言 在UG5.0开始&#xff0c;所有基于UG二次开发的DLL都要“签名”后才能被客户端上正版的NX调用。 一、基于C# 开发签名 1、添加资源文件 &#xff08;1&#xff09;项目类库上右键–>属性–>资源–>添加资源右边小三角–>添加现有文件–>切换到UG安装目录下…...

网站开发公司上/优化公司网站

大家有没有这样的感受&#xff0c;一涉及XML文档操作就得百度一遍。是不是非&#xff01;常&#xff01;烦&#xff01;。各种类型&#xff0c;各种方法&#xff0c;更别提为了找到一个节点多费劲。本来想写个XML操作的工具方法&#xff0c;写了两行一想既然XML文档是有规律的&…...

东莞做网站网络公司/品牌宣传推广策划方案

CodeForces - 579E 可以发现结果关于x的函数是一个单谷函数&#xff0c;所以三分。 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define MAXN 200000 int a[MAXN10],n; double l[MAXN10]; void Read(int &x){char c…...

苏州沧浪区做网站的/友情链接出售平台

warning: incompatible implicit declaration of built-in function ‘strlen’ [enabled by default] 警告:不兼容的隐式声明的内置函数的strlen(默认启用) 出现此错误的原因&#xff1a;函数声明的头文件没有包含进来&#xff0c;故将strlen的头文件string.h包含进来&#…...

中国进口贸易网官网/安徽网络seo

http://projectkuto.web.fc2.com/work/kutocsveditor.html...

邯郸市做网站建设/提交网站收录入口

对于少量元素,它是一个有效的算法 我们将一个数组一切两半&#xff0c;分为有序组和待插入组&#xff0c;从待插入组逐次拿出元素&#xff0c;与放入有序组的合适位置&#xff0c;就这样&#xff0c;每插入一个元素&#xff0c;有序组元素增加&#xff0c;待插入组元素减少&am…...

广西南宁房产网站建设/地推app接任务平台

0x01 漏洞利用知识点 1.代码执行 2.变量覆盖 3.文件包含 0x02 漏洞分析 首先在/fenlei1.0/do/jf.php文件中存在代码执行片段 $query2 $db->query("SELECT * FROM {$pre}jfabout WHERE fid$rs[fid] ORDER BY list");while($rs2 $db->fetch_array($query2)){ev…...