1. 程式人生 > 實用技巧 >Vue+EasyPOI匯出Excel(帶圖片)

Vue+EasyPOI匯出Excel(帶圖片)

一、前言

平時的工作中,Excel 匯入匯出功能是非常常見的功能,無論是前端 Vue (js-xlsx) 還是 後端 Java (POI),如果讓大家手動編碼實現的話,恐怕就很麻煩了,尤其是一些定製化的模版匯入匯出,筆者前幾年就用原生 POI 編寫過報表之類的需求,像是 自定義 Word、Excel 匯入匯出,表格合併等等,那過程簡直噁心的一批....

後來接觸到了 EasyPOI ,功能也如同名稱一樣簡單,內部對 POI 進行了良好的封裝,開箱即用,即便是從來沒有接觸過 POI,只要看看簡單的示例,就能很方便的編寫出 Excel 、Word 匯出匯出,以及模版自定義匯入匯出等。

本篇主要模擬開發中最常用的場景「後端提供excel下載介面,前端呼叫」,快速的實現 Excel 的匯出功能。

二、本文環境

SpringBoot 2.2.2 + Vue(axios) + easypoi 4.1.0(boot版本)

環境為前後端分離專案,後端採用的 Spring Boot 2.2.2 版本,easyPOI 採用的是 easypoi-spring-boot-starter 4.1.0 (截止 2020.09.29 最新版)。

EasyPOI 開發文件:http://doc.wupaas.com/docs/easypoi/easypoi-1c0u6ksp2r091

EasyPOI 官方示例:https://gitee.com/lemur/easypoi-test

pom.xml 依賴

<!--easypoi-->
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-spring-boot-starter</artifactId>
<version>4.1.0</version>
</dependency>

三、基於註解實現 Excel 簡單匯出

通過簡單的註解,完成以前複雜的寫法。

建立一個測試類 ExcelDemo.java(含圖片)

@Data
publicclassExcelDemo{

@Excel(name="員工名稱")
privateStringemployeesName;

@Excel(name="員工圖片",type=2,width=30,height=50)
privateStringimage;

@Excel(name="員工年齡")
privateIntegerage;

@Excel(name="建立日期",format="yyyy-MM-ddHH:mm",width=20)
privateDatecreateDate;

@Excel(name="更新日期"
,format="yyyy/MM/ddHH:mm",width=20)
privateDateupdateDate;

}

簡單看一下這個 @Excel 註解主要的值:

屬性型別預設值功能
name String null 列名,支援name_id
type int 1 匯出型別 1 是文字, 2 是圖片,3 是函式,10 是數字 預設是文字
width double 10 列寬
height double 10 列高,後期打算統一使用@ExcelTarget的height,這個會被廢棄,注意
format String “” 時間格式,相當於同時設定了exportFormat 和 importFormat
imageType int 1 圖片讀取型別,1表示從 file 讀取,2表示從資料庫讀取

關於圖片路徑

著重說明一下這個圖片路徑,當 type 取值為 2 的時候表示匯出為圖片,同時配合使用的是 imageType 引數,該引數決定是從 file 讀取,還是去資料庫讀取,預設為從 file 中讀取,記得很早之前,有小夥伴圖片是直接 base64 存資料庫的,不過現在是沒有人幹這種事了。。。

建立一個Controller方法+測試資料

@RequestMapping(value="/exportExcel",method=RequestMethod.POST)
publicvoidexportExcel(Stringid,HttpServletResponseresponse)throwsException{
List<ExcelDemo>excelDemoList=newArrayList<>();
for(inti=0;i<3;i++){
ExcelDemoexcelDemo=newExcelDemo();
excelDemo.setEmployeesName("張"+i);
excelDemo.setImage("/Users/niceyoo/workspace/File/"+i+".png");
excelDemo.setAge(10+i);
excelDemoList.add(excelDemo);
}
ExportParamsparams=newExportParams("員工資料","員工");
Workbookworkbook=ExcelExportUtil.exportExcel(params,ExcelDemo.class,excelDemoList);
StringfileName="saleData.xlsx";
response.setCharacterEncoding("UTF-8");
response.setContentType("application/vnd.ms-excel;charset=utf-8");
response.setHeader("Content-Disposition","attachment;filename="+URLEncoder.encode(fileName,"utf-8"));
OutputStreamoutputStream=response.getOutputStream();
workbook.write(outputStream);
outputStream.flush();
outputStream.close();
}

我在 /Users/niceyoo/workspace/File 目錄下放置了三張圖片:

前端Vue+axios請求

API程式碼:

importaxiosfrom'axios';

exportconstexportExcel=(url,params)=>{
letaccessToken=getStore("accessToken");
returnaxios({
method:'post',
url:'http://127.0.0.1:6666/excel/exportExcel',
data:params,
responseType:'arraybuffer',
headers:{
'Content-Type':'application/json;charset=utf-8',
'accessToken':'niceyoo'
}
});
};

vue中呼叫:

this.exportExcel("/excel/exportExcel",{}).then(res=>{
if(res.byteLength!==0){
fileDownload(res,employeesName+'.xls');
}else{
Message.error("無法找到對應的檔案!!!");
}
});

其中 fileDownload 方法為引入的 js-file 依賴:

"js-file-download":"^0.4.12",

匯出結果如下:

四、自定義模板匯出

模板檔案:

匯出檔案:

後端程式碼:

@RequestMapping("download")
publicStringdownload(ModelMapmodelMap){
Map<String,Object>map=newHashMap<String,Object>();
TemplateExportParamsparams=newTemplateExportParams("doc/foreach.xlsx");
List<TemplateExcelExportEntity>list=newArrayList<TemplateExcelExportEntity>();

for(inti=0;i<4;i++){
TemplateExcelExportEntityentity=newTemplateExcelExportEntity();
entity.setIndex(i+1+"");
entity.setAccountType("開源專案");
entity.setProjectName("EasyPoi"+i+"期");
entity.setAmountApplied(i*10000+"");
entity.setApprovedAmount((i+1)*10000-100+"");
list.add(entity);
}
map.put("entitylist",list);
map.put("manmark","1");
map.put("letest","12345678");
map.put("fntest","12345678.2341234");
map.put("fdtest",null);
List<Map<String,Object>>mapList=newArrayList<Map<String,Object>>();
for(inti=0;i<1;i++){
Map<String,Object>testMap=newHashMap<String,Object>();
testMap.put("id","xman");
testMap.put("name","小明"+i);
testMap.put("sex","1");
mapList.add(testMap);
}
map.put("maplist",mapList);

mapList=newArrayList<Map<String,Object>>();
for(inti=0;i<6;i++){
Map<String,Object>testMap=newHashMap<String,Object>();

testMap.put("si","xman");
mapList.add(testMap);
}
map.put("sitest",mapList);
modelMap.put(TemplateExcelConstants.FILE_NAME,"使用者資訊");
modelMap.put(TemplateExcelConstants.PARAMS,params);
modelMap.put(TemplateExcelConstants.MAP_DATA,map);
returnTemplateExcelConstants.EASYPOI_TEMPLATE_EXCEL_VIEW;
}

關於模版指令:

跟 el 表示式很像,{{ }} 表示表示式,內部寫標籤:

  • 空格分割
  • 三目運算 {{test ? obj:obj2}}
  • n: 表示 這個cell是數值型別 {{n:}}
  • le: 代表長度{{le:()}} 在if/else 運用{{le:() > 8 ? obj1 : obj2}}
  • fd: 格式化時間 {{fd:(obj;yyyy-MM-dd)}}
  • fn: 格式化數字 {{fn:(obj;###.00)}}
  • fe: 遍歷資料,建立row
  • !fe: 遍歷資料不建立row
  • $fe: 下移插入,把當前行,下面的行全部下移.size()行,然後插入
  • #fe: 橫向遍歷
  • v_fe: 橫向遍歷值
  • !if: 刪除當前列 {{!if:(test)}}
  • 單引號表示常量值 '' 比如'1' 那麼輸出的就是 1
  • &NULL& 空格
  • ]] 換行符 多行遍歷匯出
  • sum: 統計資料

如上,最常用的就是 $fe 遍歷標籤,用法:

fe標誌+ 冒號 + list資料 + 單個元素資料(預設t,可以不寫)+ 第一個元素

{{$fe:maplisttt.id}}

t 表示預定義值,表示集合中的任意物件,如上表示,mplist 中每個物件叫做 t,t.id 就表示 t 單個元素資料的 id 屬性,t 的作用就是佔位符。

EasyPOI測試專案

可以下載這個專案跑一下,基本覆蓋了比較全的用法示例。