java poi匯出Excel表格超大資料量解決方案
阿新 • • 發佈:2019-02-06
Java實現匯出excel表格功能,大部分都會使用apache poi,apache poi API 地址
POI之前的版本不支援大資料量處理,如果資料過多則經常報OOM錯誤,有時候調整JVM大小效果也不是太好。3.8版本的POI新出來了SXSSFWorkbook,可以支援大資料量的操作,只是SXSSFWorkbook只支援.xlsx格式,不支援.xls格式。
3.8版本的POI對excel的匯出操作,一般只使用HSSFWorkbook以及SXSSFWorkbook,HSSFWorkbook用來處理較少的資料量,SXSSFWorkbook用來處理大資料量以及超大資料量的匯出。
程式碼:
git地址 有3.9jar包
package qs.test;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
/**
* ClassName: SXSSFTest
* @Description: TODO
* @author qiaoshuai
*/
public class SXSSFTest {
public static void main(String[] args) throws IOException {
// 建立基於stream的工作薄物件的
SXSSFWorkbook wb = new SXSSFWorkbook(100); // keep 100 rows in memory,
// exceeding rows will be
// flushed to disk
// SXSSFWorkbook wb = new SXSSFWorkbook();
// wb.setCompressTempFiles(true); // temp files will be gzipped
Sheet sh = wb.createSheet();
// 使用createRow將資訊寫在記憶體中。
for (int rownum = 0; rownum < 1000; rownum++) {
Row row = sh.createRow(rownum);
for (int cellnum = 0; cellnum < 10; cellnum++) {
Cell cell = row.createCell(cellnum);
String address = new CellReference(cell).formatAsString();
cell.setCellValue(address);
}
}
// Rows with rownum < 900 are flushed and not accessible
// 當使用getRow方法訪問的時候,將記憶體中的資訊重新整理到硬碟中去。
for (int rownum = 0; rownum < 900; rownum++) {
System.out.println(sh.getRow(rownum));
}
// ther last 100 rows are still in memory
for (int rownum = 900; rownum < 1000; rownum++) {
System.out.println(sh.getRow(rownum));
}
// 寫入檔案中
FileOutputStream out = new FileOutputStream("G://sxssf.xlsx");
wb.write(out);
// 關閉檔案流物件
out.close();
System.out.println("基於流寫入執行完畢!");
}
}
在此基礎上再優化的方案是匯出的Excel表格生成多個工作表即生成多個sheet。
程式碼:
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import com.common.DateFormatUtil;
public class ExlUtil2 {
/**
* @param excelHeader
* 表頭資訊
* @param list
* 要匯出到excel的資料來源,List型別
* @param sheetName
* 表名
* @return
*/
public static ResponseEntity<byte[]> getDataStream(ExcelHeader excelHeader,
List list, String sheetName) {
LinkedHashMap<String, List> map = new LinkedHashMap<String, List>();
List<String[]> headNames = new ArrayList<String[]>();
List<String[]> fieldNames = new ArrayList<String[]>();
String[] sheetNames = new String[100];
//處理Excel生成多個工作表
//定義為每個工作表資料為50000條
if (list.size() > 50000) {
int k = (list.size() + 50000) / 50000;
for (int i = 1; i <= k; i++) {
if (i < k) {
map.put(sheetName + i,
list.subList((i - 1) * 50000, i * 50000));
} else {
map.put(sheetName + i,
list.subList((i - 1) * 50000, list.size()));
}
headNames.add(excelHeader.getHeadNames().get(0));
fieldNames.add(excelHeader.getFieldNames().get(0));
sheetNames[i - 1] = sheetName;
}
} else {
map.put(sheetName, list);
headNames.add(excelHeader.getHeadNames().get(0));
fieldNames.add(excelHeader.getFieldNames().get(0));
sheetNames[0] = sheetName;
}
byte[] buffer = null;
try {
buffer = ExcelUtil2.output(headNames, fieldNames, sheetNames, map);
} catch (IllegalArgumentException | IllegalAccessException
| IOException e) {
e.printStackTrace();
}
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
/*
* try { sheetName=URLEncoder.encode(sheetName,"UTF8"); } catch
* (UnsupportedEncodingException e) { e.printStackTrace(); }
*/
try {
sheetName = new String(sheetName.getBytes("gbk"), "iso-8859-1");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String fileGenerateTime = DateFormatUtil.toStr(new Date());
headers.setContentDispositionFormData("attachment", sheetName
+ fileGenerateTime + ".xlsx");
return new ResponseEntity<byte[]>(buffer, headers, HttpStatus.CREATED);
};
}