用JavaPOI導出Excel時,我們會考慮到Excel版本及數據量的問題。針對不同的Excel版本,要採用不同的工具類。HSSFWorkbook:是操作Excel2003以前(包括2003)的版本,擴展名是.xls;XSSFWorkbook:是操作Excel2007的版本,擴展名是.xlsx。用過... ...
用JavaPOI導出Excel時,我們會考慮到Excel版本及數據量的問題。針對不同的Excel版本,要採用不同的工具類。HSSFWorkbook:是操作Excel2003以前(包括2003)的版本,擴展名是.xls;XSSFWorkbook:是操作Excel2007的版本,擴展名是.xlsx。
用過POI的人都知道,在POI以前的版本中並不支持大數據量的處理,如果數據量過多還會常報OOM錯誤,這時候調整JVM的配置參數也不是一個好對策(註:jdk在32位系統中支持的記憶體不能超過2個G,而在64位中沒有限制,但是在64位的系統中,性能並不是太好),好在POI3.8版本新出來了一個SXSSFWorkbook對象,它就是用來解決大數據量以及超大數據量的導入導出操作的,但是SXSSFWorkbook只支持.xlsx格式,不支持.xls格式的Excel文件。
這裡普及一下,在POI中使用HSSF對象時,excel 2003最多只允許存儲65536條數據,一般用來處理較少的數據量,這時對於百萬級別數據,Excel肯定容納不了,而且在電腦性能稍低的機器上測試,就很容易導致堆溢出。而當我升級到XSSF對象時,它可以直接支持excel2007以上版本,因為它採用ooxml格式。這時excel可以支持1048576條數據,單個sheet表就支持近104萬條數據了,雖然這時導出100萬數據能滿足要求,但使用XSSF測試後發現偶爾還是會發生堆溢出,所以也不適合百萬數據的導出。
現在我們知道excel2007及以上版本可以輕鬆實現存儲百萬級別的數據,但是系統中的大量數據是如何能夠快速準確的導入到excel中這好像是個難題,對於一般的web系統,我們為瞭解決成本,基本都是使用的入門級web伺服器tomcat,既然我們不推薦調整JVM的大小,那我們就要針對我們的代碼來解決我們要解決的問題。在POI3.8之後新增加了一個類,SXSSFWorkbook,採用當數據加工時不是類似前面版本的對象,它可以控制excel數據占用的記憶體,他通過控制在記憶體中的行數來實現資源管理,即當創建對象超過了設定的行數,它會自動刷新記憶體,將數據寫入文件,這樣導致列印時,占用的CPU,和記憶體很少。但有人會說了,我用過這個類啊,他好像並不能完全解決,當數據量超過一定量後還是會記憶體溢出的,而且時間還很長。對你只是用了這個類,但是你並沒有針對你的需求進行相應的設計,僅僅是用了,所以接下來我要說的問題就是,如何通過SXSSFWorkbook以及相應的寫入設計來實現百萬級別的數據快速寫入。
v修改pom.xml
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.14</version> </dependency>
v添加controller
package com.demo.controller; import com.demo.pojo.UserDetails; import com.demo.service.UserService; import org.apache.poi.hssf.usermodel.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Date; import java.util.List; /** * Created by toutou on 2018/11/3. */ @Controller public class FileController { @Autowired UserService userService; @RequestMapping(value = "export") public void Export(HttpServletResponse response) throws IOException { HSSFWorkbook workbook = new HSSFWorkbook(); HSSFSheet sheet = workbook.createSheet("信息表"); List<UserDetails> classmateList = userService.getUserDetails(); // 設置要導出的文件的名字 String fileName = "users" + new Date() + ".xls"; // 新增數據行,並且設置單元格數據 int rowNum = 1; // headers表示excel表中第一行的表頭 在excel表中添加表頭 String[] headers = { "id", "uid", "地址", "城市"}; HSSFRow row = sheet.createRow(0); for(int i=0;i<headers.length;i++){ HSSFCell cell = row.createCell(i); HSSFRichTextString text = new HSSFRichTextString(headers[i]); cell.setCellValue(text); } //在表中存放查詢到的數據放入對應的列 for (UserDetails item : classmateList) { HSSFRow row1 = sheet.createRow(rowNum); row1.createCell(0).setCellValue(item.getId()); row1.createCell(1).setCellValue(item.getUid()); row1.createCell(2).setCellValue(item.getAddress()); row1.createCell(3).setCellValue(item.getCity()); rowNum++; } response.setContentType("application/octet-stream"); response.setHeader("Content-disposition", "attachment;filename=" + fileName); response.flushBuffer(); workbook.write(response.getOutputStream()); } }
v運行與調試
其他參考原文資料:
- HSSFWorkbook (POI API Documentation) http://poi.apache.org/apidocs/dev/org/apache/poi/hssf/usermodel/HSSFWorkbook.html
- JAVA使用POI如何導出百萬級別數據 https://blog.csdn.net/happyljw/article/details/52809244
作 者:請叫我頭頭哥
出 處:http://www.cnblogs.com/toutou/
關於作者:專註於基礎平臺的項目開發。如有問題或建議,請多多賜教!
版權聲明:本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。
特此聲明:所有評論和私信都會在第一時間回覆。也歡迎園子的大大們指正錯誤,共同進步。或者直接私信我
聲援博主:如果您覺得文章對您有幫助,可以點擊文章右下角【推薦】一下。您的鼓勵是作者堅持原創和持續寫作的最大動力!