日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Springboot 我随手封装了一个万能的导出excel工具,传什么都能导出

發布時間:2024/3/26 javascript 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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的:?

?

沒錯就是這么簡單, 當然也是拋轉引玉, 希望大家看了這篇文章,可以借鑒這些反射的函數玩法,做更多的好玩的封裝,比如加上一些自定義注解的解析,比如加上一些前后置攔截器拓展等等。

好了該篇就到這。

-------持續有空就繼續玩封裝---------

哦豁,我的看官們提出了想法,很不錯:

?

是的導出來的這個屬性名,客戶不滿意呀。 那就搞一手。 自定義注解搞起來!

我出手俠從來不遲到!

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 <T> List<String> resolveExcelTableName(T entity) {List<String> tableNamesList = new ArrayList<>();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 tableTitleName = field.getName();JcExcelName myFieldAnn = field.getAnnotation(JcExcelName.class);String annName = myFieldAnn.name();if (StringUtils.hasLength(annName)) {tableTitleName = annName;}tableNamesList.add(tableTitleName);}} catch (Exception e) {log.warn("toMap() Exception={}", e.getMessage());}}return tableNamesList;}

然后根據解析出來的注解值列名拼接 表格標題名格式:
?

public static String buildCsvFileTableNamesNew(List<String> 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<String> 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導出

總結

以上是生活随笔為你收集整理的Springboot 我随手封装了一个万能的导出excel工具,传什么都能导出的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。