javascript
Springboot 我随手封装了一个万能的导出excel工具,传什么都能导出
前言
如題,這個(gè)小玩意,就是不限制你查的是哪張表,用的是什么類。
我直接一把梭,嘎嘎給你一頓導(dǎo)出。
我知道,這是很多人都想過的, 至少我就收到很多人問過我這個(gè)類似的問題。
我也跟他們說了,但是他們就是不動(dòng)手,其實(shí)真的很簡(jiǎn)單。
不動(dòng)手怎么辦? ?我出手唄。
?
不多說開搞 。
正文
玩法很簡(jiǎn)單,我之前有寫過一篇利用csv文件內(nèi)容格式做excel文件導(dǎo)出的。
如果沒有看過的,還等什么,現(xiàn)在就去看看:
Springboot 那年我雙手插兜,手寫一個(gè)excel導(dǎo)出
要實(shí)現(xiàn)的效果 :
類是不確定的 ,User ? Student ? ?District ? ? 不確定。
但是呢我們封裝出來的函數(shù),要足夠支撐不同的類,我們自動(dòng)去讀取遍歷list ,然后導(dǎo)出生成文件。
?
核心的思路是什么 ??
?
其實(shí)就還是利用csv文件的內(nèi)容格式本質(zhì) ,看這兩幅圖 :
我們要實(shí)現(xiàn)萬(wàn)能的類導(dǎo)出excel !!!
思路是什么 :
① 我們從不確定的類 的集合list 中,取出 里面的類。
反射一手,拿出里面的屬性名, 做第一行表格行標(biāo)題名稱拼接。
②拼接內(nèi)容
因?yàn)轭惒淮_定,那么我們就采取反射把類全部字段屬性作為key丟到map里面,
同時(shí)把值丟到value里面。
這樣我們拼接內(nèi)容的時(shí)候只需要根據(jù)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. 核心的工具類,函數(shù)我都封裝好了
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";/*** 將字符串轉(zhuǎn)成csv文件*/public static void createCsvFile(String savePath, String contextStr) throws IOException {File file = new File(savePath);//創(chuàng)建文件file.createNewFile();//創(chuàng)建文件輸出流FileOutputStream fileOutputStream = new FileOutputStream(file);//將指定字節(jié)寫入此文件輸出流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);}}}/*** 構(gòu)建文件名稱* @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;}/*** 構(gòu)建excel 標(biāo)題行名* @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();}/*** 構(gòu)建excel內(nèi)容* @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格式,對(duì)著map嘎嘎一頓拼接數(shù)據(jù)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();}/*** 類轉(zhuǎn)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;} }?代碼注意點(diǎn)(各種小封裝):
?
①類轉(zhuǎn)map?
② 反射轉(zhuǎn)map 取字段屬性名 拼接 標(biāo)題
③ 針對(duì)list<不確定類> 轉(zhuǎn)化成 list<map> ,然后拼接excel內(nèi)容?
?
測(cè)試代碼:
?
看看效果:
?
?
導(dǎo)出的excel文件內(nèi)容:?
?
接下來?yè)Q個(gè)類玩玩:
?然后導(dǎo)出看看效果:
可以看到數(shù)據(jù)導(dǎo)出也是OK的:?
?
沒錯(cuò)就是這么簡(jiǎn)單, 當(dāng)然也是拋轉(zhuǎn)引玉, 希望大家看了這篇文章,可以借鑒這些反射的函數(shù)玩法,做更多的好玩的封裝,比如加上一些自定義注解的解析,比如加上一些前后置攔截器拓展等等。
好了該篇就到這。
-------持續(xù)有空就繼續(xù)玩封裝---------
哦豁,我的看官們提出了想法,很不錯(cuò):
?
是的導(dǎo)出來的這個(gè)屬性名,客戶不滿意呀。 那就搞一手。 自定義注解搞起來!
我出手俠從來不遲到!
JcExcelName.java?
/*** @Author : JCccc* @CreateTime : 2020/5/14* @Description :**/@Target({ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface JcExcelName {String name() default "";}然后在想導(dǎo)出的類里面,想加看得懂的名字就加,不加就拿屬性名:
?隨手再寫一個(gè) ,新的反射解析拿字段屬性注解值函數(shù):
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;}然后根據(jù)解析出來的注解值列名拼接 表格標(biāo)題名格式:
?
測(cè)試看看效果:
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)));?
執(zhí)行一下示例接口,看看效果:
?
文件出來了:
?打開看看效果:
?
好了,就到這吧。
ps:
Springboot 最簡(jiǎn)單的結(jié)合MYSQL數(shù)據(jù)實(shí)現(xiàn)EXCEL表格導(dǎo)出及數(shù)據(jù)導(dǎo)入
Springboot 指定自定義模板導(dǎo)出Excel文件
SpringBoot 導(dǎo)出多個(gè)Excel文件,壓縮成.zip格式下載
Springboot 獲取導(dǎo)入的Excel文件的sheet表 列名
?Springboot 導(dǎo)入導(dǎo)出Excel ,一對(duì)多關(guān)系,復(fù)合表格、合并單元格數(shù)據(jù)
Springboot 那年我雙手插兜,手寫一個(gè)excel導(dǎo)出
總結(jié)
以上是生活随笔為你收集整理的Springboot 我随手封装了一个万能的导出excel工具,传什么都能导出的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python保存为xlsb_Python
- 下一篇: nvidia命令不可用linux,如何在