SpringBoot入門教程(十四)導出Excel


用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運行與調試

SpringBoot入門教程(十四)導出Excel

SpringBoot入門教程(十四)導出Excel

v源碼地址

https://github.com/toutouge/javademosecond/tree/master/hellospringboot

其他參考原文資料:


作  者:請叫我頭頭哥
出  處:http://www.cnblogs.com/toutou/
關於作者:專注於基礎平台的項目開發。如有問題或建議,請多多賜教!
版權聲明:本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。
特此聲明:所有評論和私信都會在第一時間回復。也歡迎園子的大大們指正錯誤,共同進步。或者直接私信
聲援博主:如果您覺得文章對您有幫助,可以點擊文章右下角推薦一下。您的鼓勵是作者堅持原創和持續寫作的最大動力!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM