1. 程式人生 > >java實現如何將百萬級資料高效的匯出到Excel表單

java實現如何將百萬級資料高效的匯出到Excel表單

ps: 首先科普一下基礎知識

  Excel 2003及以下的版本。一張表最大支援65536資料,256列。也就是說excel2003完全不可能滿足百萬資料匯出的需求。

  Excel 2007-2010版本。一張表最大支援1048576行,16384列;

  筆者使用的是office 2010,更高的版本筆者沒有使用過,暫時無法判斷。

  由此看來百萬級的資料量對Excel自身已經是屬於接近極限的程度。

  假如我們有更大的需求怎麼辦呢?

  既然單表支援最大是104w條資料,那麼更大的需求量我們就只能通過程式級分表操作的方式來實現了。O(∩_∩)O哈哈~

  對於操作Excel的類庫。筆者其實瞭解的並不是很多。只是很早以前使用過POI這個類庫,感覺很不錯。於是決定從它入手。看看POI有沒有什麼比較有效的好點的解決辦法。由於筆者以前使用的POI版本比較低。而且使用於excel 2003版本。所以遇到了不少問題。

poi-ooxml和poi-ooxml-schemas是poi對2007及以上版本的擴充。於是在maven依賴中增加:

 <dependency>
 2             <groupId>org.apache.poi</groupId>
 3             <artifactId>poi-ooxml</artifactId>
 4             <version>3.10-FINAL</version>
 5         </dependency>
 6         <dependency>
 7             <groupId>org.apache.poi</groupId>
 8             <artifactId>poi-ooxml-schemas</artifactId>
 9             <version>3.10-FINAL</version>
10         </dependency>

趕緊修改自己的程式碼。實現了支援Excel 2010版本。瞬間有種大功告成的感覺,有木有。。O(∩_∩)O哈哈~。好有成就感的說。

 public static void Excel2007AboveOperateOld(String filePath) throws IOException {
          XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream(new File(filePath)));
          // 獲取第一個表單
          Sheet first = workbook.getSheetAt(0);
          for (int i = 0; i < 100000; i++) {
              Row row = first.createRow(i);
              for (int j = 0; j < 11; j++) {
                  if(i == 0) {
                      // 首行
                     row.createCell(j).setCellValue("column" + j);
                 } else {
                     // 資料
                     if (j == 0) {
                         CellUtil.createCell(row, j, String.valueOf(i));
                     } else
                         CellUtil.createCell(row, j, String.valueOf(Math.random()));
                }
            }
         }
         // 寫入檔案
         FileOutputStream out = new FileOutputStream("workbook.xlsx");
         workbook.write(out);
         out.close();
     }

趕緊執行跑起來。第一次測試寫入1w條資料。耗時8秒多點。感覺寫入速度好慢,1w條8秒,100w。。我的天。這效率完全不能接受。於是測試10w,看看測試一下是不是真的寫入速度過慢。測試結果讓人崩潰。

測試匯出10w條資料到excel耗時將近50秒。於是這種方式被暫時放棄。成就感瞬間被打落在地。

  官方提到自POI3.8版本開始提供了一種SXSSF的方式,用於超大資料量的操作。於是...

  原文:

  SXSSF is an API-compatible streaming extension of XSSF to be used when very large spreadsheets have to be produced...

馬上開動修改程式碼。程式碼如下:

public static void Excel2007AboveOperate(String filePath) throws IOException {
        XSSFWorkbook workbook1 = new XSSFWorkbook(new FileInputStream(new File(filePath)));
        SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(workbook1, 100);
//            Workbook workbook = WorkbookFactory.create(new FileInputStream(new File(filePath)));
        Sheet first = sxssfWorkbook.getSheetAt(0);
        for (int i = 0; i < 100000; i++) {
            Row row = first.createRow(i);
            for (int j = 0; j < 11; j++) {
                if(i == 0) {
                    // 首行
                    row.createCell(j).setCellValue("column" + j);
                } else {
                    // 資料
                    if (j == 0) {
                        CellUtil.createCell(row, j, String.valueOf(i));
                    } else
                        CellUtil.createCell(row, j, String.valueOf(Math.random()));
                }
            }
        }
        FileOutputStream out = new FileOutputStream("workbook.xlsx");
        sxssfWorkbook.write(out);
        out.close();
    }
多次執行測試。檢視資料
1 Cast time : 11604

  看到資料的瞬間感覺,哇塞。好給力的說。居然從將近50秒縮短帶11秒。。。

  為什麼都是程式碼差距就這麼大呢?

  原來,SXSSF實現了一套自動刷入資料的機制。當資料數量達到一定程度時(使用者可以自己設定這個限制)。像文字中刷入部分資料。這樣就緩解了程式執行時候的壓力。達到高效的目的。O(∩_∩)O哈哈~

  再一次測試單表寫入100w條資料。

1 Cast time : 87782

  將近90秒就完成了100w條資料的寫入。O(∩_∩)O哈哈~。   雖然看上去依舊有一點慢。但是考慮到資料量這樣的耗時,想來已經是可以接受的了。100w條資料生成的Excel表單居然有136mb。開啟就這個文件都花了不少時間。哈哈