EasyExcel是一個基於Java的簡單、省內存的讀寫Excel的開源項目。在儘可能節約內存的情況下支持讀寫百M的Excel。
github地址:https://github.com/alibaba/easyexcel
直接上實現代碼,即可運行查看效果生成的文件,十分簡單粗暴
package com.myFirstSpring.test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.metadata.Table;
import com.alibaba.excel.support.ExcelTypeEnum;
/**
* @author tqf
* @version 創建時間:2020-4-1 下午2:21:08
* 類說明: 阿里開源(EasyExcel)---生成導出EXCEL文件 Soeasy
*/
public class ExcelMain {
public static void main(String[] args) {
try {
long time = System.currentTimeMillis();//獲取當前系統時間(毫秒)
writeExcelOneSheetOnceWrite();
System.out.println(System.currentTimeMillis()-time+"毫秒");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 針對較少的記錄數(20W以內大概)可以調用該方法一次性查出然後寫入到EXCEL的一個SHEET中
* 注意: 一次性查詢出來的記錄數量不宜過大,不會內存溢出即可。
*
* @throws IOException
*/
public static void writeExcelOneSheetOnceWrite() throws IOException {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 生成EXCEL並指定輸出路徑
//在本地新建一個文件夾 用於保存文件
File file1=new File("D:\\測試生成Excel文件");
if(!file1.exists()){//如果文件夾不存在
file1.mkdir();//創建文件夾
}
OutputStream out = new FileOutputStream(""+file1+"\\測試SHEET.xls");
ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLS);
for (int j = 0; j < 2; j++) { //這個地方是寫入了2個SHEET文件裏面
// 設置SHEET
Sheet sheet = new Sheet(j, 0);
sheet.setSheetName("測試sheet"+j);
Table table;
// 設置標題
if(j == 0){
table = new Table(1);
List<List<String>> titles = new ArrayList<List<String>>();
titles.add(Arrays.asList("用戶ID"));
titles.add(Arrays.asList("名稱"));
titles.add(Arrays.asList("年齡"));
titles.add(Arrays.asList("生日"));
table.setHead(titles);
}else{
table = new Table(2);
List<List<String>> titles = new ArrayList<List<String>>();
titles.add(Arrays.asList("用戶ID1"));
titles.add(Arrays.asList("名稱1"));
titles.add(Arrays.asList("年齡1"));
titles.add(Arrays.asList("生日1"));
titles.add(Arrays.asList("多個字段"));
table.setHead(titles);
}
// 查詢數據導出即可 比如說一次性總共查詢出1000條數據 模擬數據插入
List<List<String>> userList = new ArrayList<List<String>>();
for (int i = 0; i < 1000; i++) {
userList.add(Arrays.asList("ID_" + i, "小譚" + i, String.valueOf(i), format.format(new Date())));
}
writer.write0(userList, sheet, table);
}
writer.finish();
out.close();
}
/**
* 針對幾百萬的記錄數可以調用該方法分多批次查出然後寫入到EXCEL的多個SHEET中
* 注意:
* perSheetRowCount % pageSize要能整除 爲了簡潔,非整除這塊不做處理
* 每次查詢出來的記錄數量不宜過大,根據內存大小設置合理的每次查詢記錄數,不會內存溢出即可。
*
* @throws IOException
*/
public static void writeExcelMoreSheetMoreWrite() throws IOException {
// 生成EXCEL並指定輸出路徑
OutputStream out = new FileOutputStream("F:\\temp\\withoutHead3.xls");
ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLS);
File file = new File("F:\\測試生成Excel文件");
if(!file.exists()){
file.mkdir();
}
// 設置SHEET名稱
String sheetName = "測試SHEET";
// 設置標題
Table table = new Table(1);
List<List<String>> titles = new ArrayList<List<String>>();
titles.add(Arrays.asList("用戶ID"));
titles.add(Arrays.asList("名稱"));
titles.add(Arrays.asList("年齡"));
titles.add(Arrays.asList("生日"));
table.setHead(titles);
// 模擬分批查詢:總記錄數250條,每個SHEET存100條,每次查詢20條 則生成3個SHEET,前倆個SHEET查詢次數爲5, 最後一個SHEET查詢次數爲3 最後一次寫的記錄數是10
// 注:該版本爲了較少數據判斷的複雜度,暫時perSheetRowCount要能夠整除pageSize, 不去做過多處理 合理分配查詢數據量大小不會內存溢出即可。
Integer totalRowCount = 250;
Integer perSheetRowCount = 100;
Integer pageSize = 20;
Integer sheetCount = totalRowCount % perSheetRowCount == 0 ? (totalRowCount / perSheetRowCount) : (totalRowCount / perSheetRowCount + 1);
Integer previousSheetWriteCount = perSheetRowCount / pageSize;
Integer lastSheetWriteCount = totalRowCount % perSheetRowCount == 0 ?
previousSheetWriteCount :
(totalRowCount % perSheetRowCount % pageSize == 0 ? totalRowCount % perSheetRowCount / pageSize : (totalRowCount % perSheetRowCount / pageSize + 1));
for (int i = 0; i < sheetCount; i++) {
// 創建SHEET
Sheet sheet = new Sheet(i, 0);
sheet.setSheetName(sheetName + i);
if (i < sheetCount - 1) {
// 前2個SHEET, 每個SHEET查5次 每次查20條 每個SHEET寫滿100行 2個SHEET合計200行 實用環境:參數: currentPage: j+1 + previousSheetWriteCount*i, pageSize: pageSize
for (int j = 0; j < previousSheetWriteCount; j++) {
List<List<String>> userList = new ArrayList<List<String>>();
for (int k = 0; k < 20; k++) {
userList.add(Arrays.asList("ID_" + Math.random(), "小明", String.valueOf(Math.random()), new Date().toString()));
}
writer.write0(userList, sheet, table);
}
} else if (i == sheetCount - 1) {
// 最後一個SHEET 實用環境不需要將最後一次分開,合成一個即可, 參數爲: currentPage = i+1; pageSize = pageSize
for (int j = 0; j < lastSheetWriteCount; j++) {
// 前倆次查詢 每次查詢20條
if (j < lastSheetWriteCount - 1) {
List<List<String>> userList = new ArrayList<List<String>>();
for (int k = 0; k < 20; k++) {
userList.add(Arrays.asList("ID_" + Math.random(), "小明", String.valueOf(Math.random()), new Date().toString()));
}
writer.write0(userList, sheet, table);
} else if (j == lastSheetWriteCount - 1) {
// 最後一次查詢 將剩餘的10條查詢出來
List<List<String>> userList = new ArrayList<List<String>>();
Integer lastWriteRowCount = totalRowCount - (sheetCount - 1) * perSheetRowCount - (lastSheetWriteCount - 1) * pageSize;
for (int k = 0; k < lastWriteRowCount; k++) {
userList.add(Arrays.asList("ID_" + Math.random(), "小明1", String.valueOf(Math.random()), new Date().toString()));
}
writer.write0(userList, sheet, table);
}
}
}
}
writer.finish();
}
}