Springboot---后台導出功能,easyExcel


Sprintboot+vuejs+easyExcel實現excel導出功能

一、背景

前段時間,有個需求,想要做一個excel導出功能,用來把查詢到的數據進行導出。第一次做,所以搜了大量的資料,分為兩種,一個是查詢出來前端用XLSX和File-saver導出,一個是springboot導出,返回文件流。這次就做一個后端導出的記錄吧!

二、幾種excel導出方式比較

用 Apache 開源框架 poi, 或者 jxl 都可以實現。

傳統 Excel 框架的不足:Apache poi、jxl 都存在生成 excel 文件不夠簡單優雅快速外,它們都還存在一個嚴重的問題,那就是非常耗內存嚴重時會導致內存溢出

POI 雖然目前來說,是 excel 解析框架中被使用最廣泛的,但這個框架並不完美。

為什么這么說呢?

開發者們大部分使用 POI,都是使用其 userModel 模式。而 userModel 的好處是上手容易使用簡單,隨便拷貝個代碼跑一下,剩下就是寫業務轉換了,雖然轉換也要寫上百行代碼,但是還是可控的。

然而 userModel 模式最大的問題是在於,對內存消耗非常大,一個幾兆的文件解析甚至要用掉上百兆的內存。現實情況是,很多應用現在都在采用這種模式,之所以還正常在跑是因為並發不大,並發上來后,一定會OOM或者頻繁的 full gc。

三、easyExcel

 由阿里出品的easyExcel,gitHub地址:https://github.com/alibaba/easyexcel

四、快速上手

 1.添加依賴

<!--alibaba easyexcel-->
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>easyexcel</artifactId>
  <version>1.1.2-beta5</version>
</dependency>
<!--lombok-->
<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
</dependency>

 

lombok這個依賴在后面如果使用model接受數據設置excel的列名的時候需要用到。

2.pojo設置列名(創建需要寫入的數據集

正常業務中,這塊都是從數據庫中查詢出來的。

@Data
public class WriteModel extends BaseRowModel {

    @ExcelProperty(value = "姓名", index = 0)
    private String name;

    @ExcelProperty(value = "密碼", index = 1)
    private String password;

    @ExcelProperty(value = "年齡", index = 2)
    private Integer age;
}

ExayExcel 提供注解的方式, 來方便的定義 Excel 需要的數據模型:

  • :首先,定義的寫入模型必須要繼承自 BaseRowModel.java;
  • :通過 @ExcelProperty 注解來指定每個字段的列名稱,以及下標位置

3.邏輯代碼,生成excel

1)生成到本地

public void writeExcel1(String pathName,List<? extends BaseRowModel> dataInfo) throws Exception {
  // 文件輸出位置
  OutputStream out = new FileOutputStream(filePath);

  ExcelWriter writer = EasyExcelFactory.getWriter(out);

  // 寫僅有一個 Sheet 的 Excel 文件, 此場景較為通用
  Sheet sheet1 = new Sheet(1, 0, WriteModel.class);

  // 第一個 sheet 名稱
  sheet1.setSheetName("第一個sheet");

  // 寫數據到 Writer 上下文中
  // 入參1: 創建要寫入的模型數據
  // 入參2: 要寫入的目標 sheet
  writer.write(dataInfo, sheet1);

  // 將上下文中的最終 outputStream 寫入到指定文件中
  writer.finish();

  // 關閉流
  out.close();
}

 

2)生成文件流返回給前端

public void cooperation(HttpServletResponse response,String fileName,String sheetName,List<? extends BaseRowModel> dataInfo,Class<? extends BaseRowModel> clazz) {
        ExcelWriter writer = null;
        OutputStream out = null;
        out = response.getOutputStream();
        writer = new ExcelWriter(out, ExcelTypeEnum.XLSX);
        Sheet sheet1 = new Sheet(1, 0,clazz);
        sheet1.setSheetName("第一個sheet");
        writer.write(dataInfo, sheet1);
        writer.finish();
        response.setContentType("multipart/form-data");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename="+fileName+".xlsx");
        response.setHeader("FileName", fileName+".xlsx");
        out.flush();
        }
    }

 

 前端主要是發送請求,當成功的時候,就接受文件流,創建一個超鏈接a,點擊

axios({
        method: "post",
        url: "/excel",
        data:this.query.data,
        responseType: "blob"
      })
        .then(res => {
         // console.log(decodeURI(res.headers['filename']));
          const link = document.createElement("a");
          let blob = new Blob([res.data], { type: "multipary/form-data" });
          link.style.display = "none";
          link.href = URL.createObjectURL(blob);
          link.setAttribute("download", decodeURI(res.headers['filename']));
          document.body.appendChild(link);
          link.click();
          document.body.removeChild(link);
        })
        .catch(error => {
          this.$Notice.error({
            title: "錯誤",
            desc: "系統數據錯誤"
          });
          console.log(error);
        });
    },

 

3)動態生成excel的表頭

有的時候我們不知道表頭是什么,什么形式,有哪些,需要通過查詢數據庫才能獲得,這個時候我們就需要mybatis先查出數據庫中的字段名,然后創建表頭,之后再進行數據填充

因為easyExcel的函數編寫,需要給他List<List<String>> 類型的表頭信息,以及List<List<object>>類型的表內容信息

而mybatis中生成返回的僅僅是List<String >和List<HashHap<String,String>>類型的,所以需要自己進行轉換一下

public void cooperation(HttpServletResponse response,String fileName,String sheetName,List<List<Object>> dataInfo,List<List<String>> params) {
        ExcelWriter writer = null;
        OutputStream out = null;
        out = response.getOutputStream();
        writer = new ExcelWriter(out, ExcelTypeEnum.XLSX);
        Sheet sheet1 = new Sheet(1, 0);
        sheet1.setSheetName("第一個sheet");
        sheet1.setHead(params);
        writer.write1(dataInfo, sheet1);
        writer.finish();
        response.setContentType("multipart/form-data");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename="+fileName+".xlsx");
        response.setHeader("FileName", fileName+".xlsx");
        out.flush();
        }
    }

 

 

 

 

 

 

 

 

以上就是我在寫的過程中用到的三種生成excel的方法。更多詳細的內容可以去github查看

 


免責聲明!

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



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