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測試專案
可以下載這個專案跑一下,基本覆蓋了比較全的用法示例。