在開發過程中經常會有需要將數據導出到 excel 的需求,當數據量很大,達到幾萬甚至幾十萬、幾百萬級別的時候,如何加快生成 excel 的速度呢?
首先普及一下知識背景:
Excel2003 及以下版本一張表最多支持 65536 行、256 列數據,所以要生成十萬、百萬級別數據就不能用 Excel2003 了;
Excel2007 版本一張表最多支持1048576行,16384 列,基本可以滿足百萬級別以下的數據量級。
一般通過 poi 生成 excel 的方式如下:(原諒我以前沒有研究過poi,就只會用這種方式,而且網上的demo好多也是這種方式)
1 public static void exportDataToExcel1(String[] header, List<String[]> datas, String path) { 2 File file = new File(path); 3 Workbook workbook = null; 4 if (path.endsWith(EXCEL_2003)) { 5 workbook = new HSSFWorkbook(); 6 } 7 if (path.endsWith(EXCEL_2007)) { 8 workbook = new XSSFWorkbook(); 9 } 10 Sheet sheet = workbook.createSheet(); 11 Row firstRow = sheet.createRow(0); //第一行 12 for (int i = 0; i < header.length; i++) { 13 Cell cell = firstRow.createCell(i); 14 cell.setCellValue(header[i]); 15 } 16 if (datas != null && datas.size() > 0) { 17 for (int i = 0; i < datas.size(); i++) { 18 Row row = sheet.createRow(i + 1); 19 String[] d = datas.get(i); 20 for (int j = 0; j < d.length; j++) { 21 Cell cell = row.createCell(j); 22 cell.setCellValue(d[j]); 23 } 24 } 25 } 26 try { 27 OutputStream outputStream = new FileOutputStream(file); 28 workbook.write(outputStream); 29 outputStream.flush(); 30 outputStream.close(); 31 } catch (FileNotFoundException e) { 32 e.printStackTrace(); 33 } catch (IOException e) { 34 e.printStackTrace(); 35 } 36 }
利用上述方式生成一張 10萬 行、30 列的 excel 表在我的電腦上耗時大約40多秒
數據准備了 1731 ms
導出花費了 46795 ms
查看 poi 官網http://poi.apache.org/spreadsheet/index.html發現從 3.8 beta3 版本開始新增 SXSSF api 用於解決大數據量場景
這種方式新增了自動刷入數據的機制,可以設置一個數據量閾值,達到這個閾值后會將數據刷入到磁盤,緩解了運行時的壓力。
改后的代碼如下:
public static void exportDataToExcel(String[] header, List<String[]> datas, String path) { File file = new File(path); SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(100); Sheet sheet = sxssfWorkbook.createSheet(); Row firstRow = sheet.createRow(0); //第一行 for (int i = 0; i < header.length; i++) { Cell cell = firstRow.createCell(i); cell.setCellValue(header[i]); } if (datas != null && datas.size() > 0) { for (int i = 0; i < datas.size(); i++) { Row row = sheet.createRow(i + 1); String[] d = datas.get(i); for (int j = 0; j < d.length; j++) { Cell cell = row.createCell(j); cell.setCellValue(d[j]); } } } try { OutputStream outputStream = new FileOutputStream(file); sxssfWorkbook.write(outputStream); outputStream.flush(); outputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { sxssfWorkbook.dispose(); } }
使用這種方式測試相同量級的數據,導出excel縮短到了6、7秒,可見這個提升幅度還是很明顯的。
數據准備了 1096 ms
導出花費了 6784 ms