SpringBoot內(nèi)存數(shù)據(jù)導出成Excel的實現(xiàn)方法
前言
這是本人寫的一個SpringBoot對Excel寫入的方法,實測能用,待提升的地方有很多,有不足之處請多多指點。
Excel2003版(后綴為.xls)最大行數(shù)是65536行,最大列數(shù)是256列。
Excel2007以上的版本(后綴為.xlsx)最大行數(shù)是1048576行,最大列數(shù)是16384列。
若數(shù)據(jù)量超出行數(shù),需要進行腳頁的控制,這一點沒做,因為一般100W行已夠用。
提供3種方法寫入:
1.根據(jù)給定的實體類列List和列名數(shù)組arr[]進行Excel寫入
2.根據(jù)給定的List和key的順序數(shù)組key[]進行Excel寫入
3.根據(jù)給定的List按順序Excel寫入,列名數(shù)組arr[]需要自行和數(shù)據(jù)列順序進行一一對應
同名的Excel會被覆蓋?。?!
寫入Excel所需要的幾個類

1.在pom.xml加上依賴
</dependencies> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.0.1</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.0.1</version> </dependency> </dependencies>
2.ExcelPOJO實體類
package com.cly.utils.Excel;
/**
* @author : CLy
* @ClassName : ExcelPOJO
* @date : 2020/7/9 17:13
* 實體類所有成員變量都需要有GET,SET方法
* 所有成員變量都要加上注解@excelRescoure(value = "?"),?為Excel真實列名,必須一一對應
* @excelRescoure(value = "?"),?可為空,需要用到才賦值
* 成員變量目前只允許String,Double,Interge,Float
**/
public class ExcelPOJO {
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPasswork() {
return passwork;
}
public void setPasswork(String passwork) {
this.passwork = passwork;
}
public String getLook() {
return look;
}
public void setLook(String look) {
this.look = look;
}
@excelRescoure(value = "姓名")
private String name;
@excelRescoure(value = "密碼")
private String passwork;
@excelRescoure(value = "工號")
private String look;
@Override
public String toString(){
return "name:"+this.getName()+",passwork:"+this.getPasswork()+",look:"+this.getLook();
}
public ExcelPOJO() {}
}
3.@interface自定義注解(用于實體類讀取)
package com.cly.utils.Excel;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author : CLy
* @ClassName : myRescoure
* @date : 2020/7/10 9:31
**/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface excelRescoure {
String value() default "";//默認為空
}
4.excelWrite類(寫入Excel數(shù)據(jù)類)有很多冗余的代碼,可抽離出來
package com.cly.utils.Excel;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletResponse;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* @author : CLy
* @ClassName : excelWrite
* @date : 2020/7/17 17:01
**/
public class excelWrite {
//日志輸出
private static Logger logger = LoggerFactory.getLogger(excelWrite.class);
/**
* 方法一:
* 實體類數(shù)據(jù)寫入新建的excel
* @path:excel文件路徑
* @array[]:文件首行數(shù)據(jù)列名,可為空,為空時不存在首行列名
* @list<T>:實體類數(shù)據(jù)數(shù)列
*/
public static <T> String writeToExcelByPOJO(String path, String[] array, List<T> list) {
/* for (T t : list) {
System.out.println(t);
}*/
//創(chuàng)建工作薄
Workbook wb = new XSSFWorkbook();
/**標題和頁碼*/
CellStyle titleStyle = wb.createCellStyle();
// 設置單元格對齊方式
titleStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
//titleStyle.setVerticalAlignment(); // 默認垂直居中
// 設置字體樣式
Font titleFont = wb.createFont();
titleFont.setFontHeightInPoints((short) 12); // 字體高度
titleFont.setFontName("黑體"); // 字體樣式
titleStyle.setFont(titleFont);
//創(chuàng)建sheet
Sheet sheet = wb.createSheet("第一頁");
sheet.autoSizeColumn(0);// 自動設置寬度
// 在sheet中添加標題行
Row row = sheet.createRow((int) 0);// 行數(shù)從0開始
for (int i = 0; i < array.length; i++) {
Cell cell = row.createCell(i);
cell.setCellValue(array[i]);
cell.setCellStyle(titleStyle);
}
/**數(shù)據(jù)樣式*/
// 數(shù)據(jù)樣式 因為標題和數(shù)據(jù)樣式不同 需要分開設置 不然會覆蓋
CellStyle dataStyle = wb.createCellStyle();
// 設置居中樣式
dataStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
/**處理實體類數(shù)據(jù)并寫入*/
//獲取當前的泛型對象
Object obj = list.get(0);
ArrayList arrayList = new ArrayList();
//LinkedHashMap保證順序
LinkedHashMap<String, Object> POJOfields = getPOJOFieldAndValue(obj);
for (int i = 0; i < array.length; i++) {
for (Map.Entry<String, Object> map : POJOfields.entrySet()) {
if (map.getKey().equals(array[i])) {
arrayList.add(map.getValue());
}
}
}
if (array.length != arrayList.size()) {
return "標題列數(shù)和實體類標記數(shù)不相同";
}
try {
//數(shù)據(jù)從序號1開始
int index = 1;
//利用迭代器,遍歷集合數(shù)據(jù),產(chǎn)生數(shù)據(jù)行
Iterator<T> it = list.iterator();
while (it.hasNext()) {
row = sheet.createRow(index);// 默認的行數(shù)從0開始,為了統(tǒng)一格式設置從1開始,就是從excel的第二行開始
index++;
T t = (T) it.next();
//System.out.println("t:" + t);
for (int i = 0; i < arrayList.size(); i++) {
String fieldName = (String) arrayList.get(i);
//System.out.println(fieldName);
String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
//System.out.println(getMethodName);
Class<? extends Object> tCls = t.getClass();// 泛型為Object以及所有Object的子類
//System.out.println(tCls);
Method method = tCls.getMethod(getMethodName, new Class[]{});// 通過方法名得到對應的方法
//PropertyDescriptor pd = new PropertyDescriptor((String) arrayList.get(i), it.getClass());
//獲取成員變量的get方法
//Method method = pd.getWriteMethod();
Object value = method.invoke(t, new Object[]{});// 動態(tài)調(diào)用方,得到屬性值
//System.out.println(value.toString());
Cell cell = row.createCell(i);
if (value != null) {
if (value instanceof Date) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
value = simpleDateFormat.format(value);
}
cell.setCellValue(value.toString());// 為當前列賦值
cell.setCellStyle(dataStyle);//設置數(shù)據(jù)的樣式
}
}
}
FileOutputStream fileOut = new FileOutputStream(path);
wb.write(fileOut);
fileOut.flush();
wb.close();
fileOut.close();
return "success";
} catch (Exception e) {
e.printStackTrace();
}
return "faile";
}
/**
* 獲取對應的實體類成員
*/
private static LinkedHashMap<String, Object> getPOJOFieldAndValue(Object T) {
//聲明返回結(jié)果集
LinkedHashMap<String, Object> result = new LinkedHashMap<>();
Field[] fields = T.getClass().getDeclaredFields();//獲取屬性名
if (fields != null) {
for (Field field : fields) {
excelRescoure Rescoure = field.getAnnotation(excelRescoure.class);
if (Rescoure.value() != null && !"".equals(Rescoure.value())) {
result.put(Rescoure.value(), field.getName());
}
}
} else {
logger.warn("實體類:" + T + "不存在成員變量");
return null;
}
return result;
}
/**---------------------===================================================---------------------------**/
/**
* 方法2:
* HashMap數(shù)據(jù)寫入新建的excel
* @path:excel文件路徑
* @array[]:文件首行數(shù)據(jù)列名,可為空,為空時不存在首行列名
* @List<Map<?,?>>:HashMap數(shù)據(jù)數(shù)列
* @key:hashmap里面的key值,需要一一對應列名的順序
* */
public static String writeToExcelByHashMap (String path, String[] array, List<HashMap> list,String[] key){
//創(chuàng)建工作薄
Workbook wb = new XSSFWorkbook();
/**標題和頁碼*/
CellStyle titleStyle = wb.createCellStyle();
// 設置單元格對齊方式
titleStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
//titleStyle.setVerticalAlignment(); // 默認垂直居中
// 設置字體樣式
Font titleFont = wb.createFont();
titleFont.setFontHeightInPoints((short) 12); // 字體高度
titleFont.setFontName("黑體"); // 字體樣式
titleStyle.setFont(titleFont);
//創(chuàng)建sheet
Sheet sheet = wb.createSheet("第一頁");
sheet.autoSizeColumn(0);// 自動設置寬度
// 在sheet中添加標題行
Row row = sheet.createRow((int) 0);// 行數(shù)從0開始
for (int i = 0; i < array.length; i++) {
Cell cell = row.createCell(i);
cell.setCellValue(array[i]);
cell.setCellStyle(titleStyle);
}
/**數(shù)據(jù)樣式*/
// 數(shù)據(jù)樣式 因為標題和數(shù)據(jù)樣式不同 需要分開設置 不然會覆蓋
CellStyle dataStyle = wb.createCellStyle();
// 設置居中樣式
dataStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
/**數(shù)據(jù)寫入*/
//數(shù)據(jù)從序號1開始
try {
int index = 1;
for (int i = 0; i < list.size(); i++) {
row = sheet.createRow(index);// 默認的行數(shù)從0開始,為了統(tǒng)一格式設置從1開始,就是從excel的第二行開始
index++;
HashMap hashMap= list.get(i);
for (int j = 0; j < key.length; j++) {
Cell cell = row.createCell(j);
cell.setCellValue(hashMap.get(key[j]).toString());// 為當前列賦值
cell.setCellStyle(dataStyle);//設置數(shù)據(jù)的樣式
}
}
FileOutputStream fileOut = new FileOutputStream(path);
wb.write(fileOut);
fileOut.flush();
wb.close();
fileOut.close();
return "success";
}catch (Exception e){
e.printStackTrace();
}
return "faile";
}
/**------------------===========================================================------------------------------------------------------*/
/**
* 方法3:
* HashMap數(shù)據(jù)寫入新建的excel
* @path:excel文件路徑
* @array[]:文件首行數(shù)據(jù)列名,可為空,為空時不存在首行列名,列名需要和數(shù)列的數(shù)據(jù)順序一一對應
* @List<List>:數(shù)列數(shù)據(jù)數(shù)列
*
* */
public static String writeToExcelByList(String path, String[] array, List<List> list){
//創(chuàng)建工作薄
Workbook wb = new XSSFWorkbook();
/**標題和頁碼*/
CellStyle titleStyle = wb.createCellStyle();
// 設置單元格對齊方式
titleStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
//titleStyle.setVerticalAlignment(); // 默認垂直居中
// 設置字體樣式
Font titleFont = wb.createFont();
titleFont.setFontHeightInPoints((short) 12); // 字體高度
titleFont.setFontName("黑體"); // 字體樣式
titleStyle.setFont(titleFont);
//創(chuàng)建sheet
Sheet sheet = wb.createSheet("第一頁");
sheet.autoSizeColumn(0);// 自動設置寬度
// 在sheet中添加標題行
Row row = sheet.createRow((int) 0);// 行數(shù)從0開始
for (int i = 0; i < array.length; i++) {
Cell cell = row.createCell(i);
cell.setCellValue(array[i]);
cell.setCellStyle(titleStyle);
}
/**數(shù)據(jù)樣式*/
// 數(shù)據(jù)樣式 因為標題和數(shù)據(jù)樣式不同 需要分開設置 不然會覆蓋
CellStyle dataStyle = wb.createCellStyle();
// 設置居中樣式
dataStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中
/**數(shù)據(jù)寫入*/
//數(shù)據(jù)從序號1開始
try {
int index = 1;
for (int i = 0; i < list.size(); i++) {
row = sheet.createRow(index);// 默認的行數(shù)從0開始,為了統(tǒng)一格式設置從1開始,就是從excel的第二行開始
index++;
List data= list.get(i);
for (int j = 0; j < data.size(); j++) {
Cell cell = row.createCell(j);
cell.setCellValue(data.get(j).toString());// 為當前列賦值
cell.setCellStyle(dataStyle);//設置數(shù)據(jù)的樣式
}
}
FileOutputStream fileOut = new FileOutputStream(path);
wb.write(fileOut);
fileOut.flush();
wb.close();
fileOut.close();
return "success";
}catch (Exception e){
e.printStackTrace();
}
return "faile";
}
}
5.測試類,同名的Excel會被覆蓋
package com.cly.utils.Excel;
import java.util.*;
/**
* @author : CLy
* @ClassName : WriteTest
* @date : 2020/7/31 15:26
**/
public class WriteTest {
public static void main(String[] args) throws Exception {
/**實體類測試
* writeToExcelByPOJO(String path, String[] array, List<T> list)
* @path:excel文件路徑
* @array[]:文件首行數(shù)據(jù)列名,可為空,為空時不存在首行列名
* @list<T>:實體類數(shù)據(jù)數(shù)列
* 注意同名的Excel會被覆蓋,請寫好文件名字和對應的后綴
*/
ExcelPOJO excelPOJO = new ExcelPOJO();
excelPOJO.setName("name");
excelPOJO.setPasswork("pass");
excelPOJO.setLook("look");
ExcelPOJO POJO2 = new ExcelPOJO();
POJO2.setName("name2");
POJO2.setPasswork("pass2");
POJO2.setLook("look2");
ExcelPOJO POJO3 = new ExcelPOJO();
POJO3.setName("name3");
POJO3.setPasswork("pass3");
POJO3.setLook("look3");
List<ExcelPOJO> list = new ArrayList<>();
list.add(excelPOJO);
list.add(POJO2);
list.add(POJO3);
/**列名對應實體類中成員變量@excelRescoure的值,只需要寫入要的列明,不必全部成員變量都寫上*/
String[] arr = {"姓名", "密碼"};
String s = excelWrite.writeToExcelByPOJO("D:\\123.xls", arr, list);
System.out.println(s);
/**HashMap測試
* writeToExcelByHashMap (String path, String[] array, List<HashMap> list,String[] key)
* @path:excel文件路徑
* @array[]:文件首行數(shù)據(jù)列名,可為空,為空時不存在首行列名
* @List<Map<?,?>>:HashMap數(shù)據(jù)數(shù)列
* @key:hashmap里面的key值,需要一一對應列名的順序
* 注意同名的Excel會被覆蓋,請寫好文件名字和對應的后綴
*/
HashMap hashMap= new HashMap<>();
hashMap.put("1","q");
hashMap.put("0","w");
hashMap.put("5","e");
hashMap.put("2","r");
HashMap hashMap2= new HashMap<>();
hashMap2.put("1","q2");
hashMap2.put("0","w2");
hashMap2.put("5","e2");
hashMap2.put("2","r2");
/**列名順序*/
String[] arr2 = {"第一列","第二列","第三列","第四列"};
/**HashMap中的數(shù)據(jù)KEY對應列名順序,不存在列名或順序要求可隨意,但該數(shù)組數(shù)據(jù)必須要*/
String[] key = {"0","1","2","5"};
List list = new ArrayList();
list.add(hashMap);
list.add(hashMap2);
String s = excelWrite.writeToExcelByHashMap("D:\\123.xls", arr2, list,key);
System.out.println(s);
/**List測試
* writeToExcelByList(String path, String[] array, List<List> list)
* @path:excel文件路徑
* @array[]:文件首行數(shù)據(jù)列名,可為空,為空時不存在首行列名,列名需要和數(shù)列的數(shù)據(jù)順序一一對應
* @List<List>:數(shù)列數(shù)據(jù)數(shù)列
* 注意同名的Excel會被覆蓋,請寫好文件名字和對應的后綴
*/
String[] arr3 = {"第一列","第二列","第三列","第四列"};
List data = new ArrayList();
data.add("1");
data.add("2");
data.add("3");
data.add("4");
List data2 = new ArrayList();
data2.add("5");
data2.add("6");
data2.add("7");
data2.add("8");
List<List> list1 = new ArrayList();
list1.add(data);
list1.add(data2);
String s = excelWrite.writeToExcelByList("D:\\123.xls", arr3, list1);
System.out.println(s);
}
}
6.運行結(jié)果和說明
1.實體類測試結(jié)果


2.HashMap測試

3.List測試

還有很多不足的地方,請多多指點,希望能給你帶來幫助。
SpringBoot實現(xiàn)Excel讀取在另一篇文章 文章地址:http://www.dbjr.com.cn/article/202762.htm
總結(jié)
到此這篇關(guān)于SpringBoot內(nèi)存數(shù)據(jù)導出成Excel的文章就介紹到這了,更多相關(guān)SpringBoot內(nèi)存數(shù)據(jù)導出成Excel內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java數(shù)據(jù)結(jié)構(gòu)之線段樹的原理與實現(xiàn)
線段樹是一種二叉搜索樹,是用來維護區(qū)間信息的數(shù)據(jù)結(jié)構(gòu)。本文將利用示例詳細講講Java數(shù)據(jù)結(jié)構(gòu)中線段樹的原理與實現(xiàn),需要的可以參考一下2022-06-06
Java動態(tài)初始化數(shù)組,元素默認值規(guī)則詳解
動態(tài)初始化數(shù)組涉及先定義數(shù)組長度,后填充具體數(shù)據(jù),適用于數(shù)據(jù)量已知但具體值未定的情況,這種初始化方式允許程序運行過程中賦值,并會根據(jù)數(shù)據(jù)類型設定默認值,如整型為0,字符串為null,動態(tài)初始化與靜態(tài)初始化格式不能混用2024-10-10
Java程序順序結(jié)構(gòu)中邏輯控制語句詳解流程
在程序開發(fā)的過程之中一共會存在有三種程序邏輯:順序結(jié)構(gòu)、分支結(jié)構(gòu)、循環(huán)結(jié)構(gòu),對于之前所編寫的代碼大部分都是順序結(jié)構(gòu)的定義,即:所有的程序?qū)凑斩x的代碼順序依次執(zhí)行2021-10-10
Java使用Sftp和Ftp實現(xiàn)對文件的上傳和下載
這篇文章主要介紹了Java使用Sftp和Ftp實現(xiàn)對文件的上傳和下載,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-03-03
Spring MVC獲取查詢參數(shù)及路徑參數(shù)代碼實例
這篇文章主要介紹了Spring MVC獲取查詢參數(shù)及路徑參數(shù)代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-02-02

