前言

如题,这个小玩意,就是不限制你查的是哪张表,用的是什么类。

我直接一把梭,嘎嘎给你一顿导出。

我知道,这是很多人都想过的, 至少我就收到很多人问过我这个类似的问题。

我也跟他们说了,但是他们就是不动手,其实真的很简单。

不动手怎么办? 我出手呗。

不多说开搞 。

正文

玩法很简单,我之前有写过一篇利用csv文件内容格式做excel文件导出的。

如果没有看过的,还等什么,现在就去看看:

Springboot 那年我双手插兜,手写一个excel导出

要实现的效果 :

类是不确定的 ,User ? Student ” />

我们要实现万能的类导出excel !!!

思路是什么 :

① 我们从不确定的类 的集合list 中,取出 里面的类。

反射一手,拿出里面的属性名, 做第一行表格行标题名称拼接。

②拼接内容
因为类不确定,那么我们就采取反射把类全部字段属性作为key丢到map里面,
同时把值丢到value里面。

这样我们拼接内容的时候只需要根据map 嘎嘎一顿遍历 拼接即可。

1.依赖

org.apache.poipoi-ooxml3.15org.apache.poipoi-scratchpad3.15com.alibabafastjson1.2.69commons-iocommons-io2.5

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 是我 */@Slf4jpublic 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 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> mapList = new ArrayList();for (Object o : dataLists) {mapList.add(toMap(o));}//然后利用csv格式,对着map嘎嘎一顿拼接数据StringBuilder lineBuilder = new StringBuilder();for (Map 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  * @return */public static Map toMap(T entity){Class

代码注意点(各种小封装):

①类转map

② 反射转map 取字段属性名 拼接 标题

③ 针对list 转化成 list

,然后拼接excel内容

测试代码:

@RequestMapping("/createCsvFileJcTest")public void createCsvFileJcTest() {//类不确定 随便怎么传都行List 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的:

没错就是这么简单, 当然也是抛转引玉, 希望大家看了这篇文章,可以借鉴这些反射的函数玩法,做更多的好玩的封装,比如加上一些自定义注解的解析,比如加上一些前后置拦截器拓展等等。

好了该篇就到这。

-------持续有空就继续玩封装---------

哦豁,我的看官们提出了想法,很不错:

是的导出来的这个属性名,客户不满意呀。 那就搞一手。 自定义注解搞起来!

我出手侠从来不迟到!

JcExcelName.java

/** * @Author : JCccc * @CreateTime : 2020/5/14 * @Description : **/@Target({ElementType.METHOD, ElementType.FIELD})@Retention(RetentionPolicy.RUNTIME)public @interface JcExcelName {String name() default "";}

然后在想导出的类里面,想加看得懂的名字就加,不加就拿属性名:

随手再写一个 ,新的反射解析拿字段属性注解值函数:

public static  List resolveExcelTableName(T entity) {List tableNamesList = new ArrayList();Class

然后根据解析出来的注解值列名拼接 表格标题名格式:

public static String buildCsvFileTableNamesNew(List dataList) {StringBuilder tableNames = new StringBuilder();for (String name : dataList) {tableNames.append(name).append(MyCsvFileUtil.CSV_DELIMITER);}return tableNames.append(MyCsvFileUtil.CSV_TAIL).toString();}

测试看看效果:

public static void main(String[] args) {User user = new User();List nameList = MapUtils.resolveExcelTableName(user);System.out.println(nameList.toString());String tableNames = buildCsvFileTableNamesNew(nameList);System.out.println(tableNames);}

效果嘎嘎好:

然后反手就搞到我们前面的文章使用例子里面:

String tableNames = MyCsvFileUtil.buildCsvFileTableNamesNew( MyCsvFileUtil.resolveExcelTableName(dataList.get(0)));

执行一下示例接口,看看效果:

文件出来了:

打开看看效果:

好了,就到这吧。

ps:

Springboot 最简单的结合MYSQL数据实现EXCEL表格导出及数据导入

Springboot 指定自定义模板导出Excel文件

SpringBoot 导出多个Excel文件,压缩成.zip格式下载

Springboot 获取导入的Excel文件的sheet表 列名

Springboot 导入导出Excel ,一对多关系,复合表格、合并单元格数据

Springboot 那年我双手插兜,手写一个excel导出