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 开发⽂档:
EasyPOI 官⽅⽰例:
<!-- easypoi -->
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-spring-boot-starter</artifactId>
<version>4.1.0</version>
</dependency>
三、基于注解实现 Excel 简单导出
通过简单的注解,完成以前复杂的写法。
创建⼀个测试类 ExcelDemo.java(含图⽚)
@Data
public class ExcelDemo {
@Excel(name = "员⼯名称")
private String employeesName;
@Excel(name = "员⼯图⽚",type = 2 ,width = 30 , height = 50)
private String image;
@Excel(name = "员⼯年龄")
private Integer age;
@Excel(name = "创建⽇期", format = "yyyy-MM-dd HH:mm", width = 20)
private Date createDate;
@Excel(name = "更新⽇期", format = "yyyy/MM/dd HH:mm", width = 20)
private Date updateDate;
}
简单看⼀下这个 @Excel 注解主要的值:
属性类型默认值功能
name String null列名,⽀持name_id
type int1导出类型 1 是⽂本, 2 是图⽚,3 是函数,10 是数字默认是⽂本
width double10列宽
width double 10列宽height
double 10列⾼,后期打算统⼀使⽤的height,这个会被废弃,注意format
String “”时间格式,相当于同时设置了exportFormat 和 importFormat imageType
int 1图⽚读取类型,1表⽰从 file 读取,2表⽰从数据库读取
属性
类型默认值功能关于图⽚路径着重说明⼀下这个图⽚路径,当 type 取值为 2 的时候表⽰导出为图⽚,同时配合使⽤的是 imageType 参数,该参数决定是从 file 读取,还是去数据库读取,默认为从 file 中读取,记得很早之前,有⼩伙伴图⽚是直接 base64 存数据库的,不过现在是没有⼈⼲这种事了。。。创建⼀个Controller ⽅法+测试数据@RequestMapping(value = "/exportExcel"
, method = RequestMethod.POST)public void exportExcel(String id,HttpServletResponse response) throws Exception {
List<ExcelDemo> excelDemoList = new ArrayList<>();
for  (int i = 0; i < 3; i++) {
ExcelDemo excelDemo = new ExcelDemo();
excelDemo.setEmployeesName("张"+i);
excelDemo.setImage("/Users/niceyoo/workspace/File/"+i+".png");
excelDemo.setAge(10+i);
excelDemoList.add(excelDemo);
}
ExportParams params = new ExportParams("员⼯数据", "员⼯");
Workbook workbook = portExcel(params, ExcelDemo.class, excelDemoList);
String fileName = "saleData.xlsx";
response.setCharacterEncoding("UTF-8");
response.setContentType("application/vnd.ms-excel; charset=utf-8");
response.setHeader("Content-Disposition", "attachment;filename=" + de(fileName, "utf-8"));
OutputStream outputStream = OutputStream();
workbook.write(outputStream);
outputStream.flush();
outputStream.close();
}
我在 /Users/niceyoo/workspace/File  ⽬录下放置了三张图⽚:
前端Vue+axios 请求
API 代码:
import axios from 'axios';
export  const exportExcel = (url, params) => {
let  accessToken = getStore("accessToken");
return  axios({
method: 'post',
url: '127.0.0.1:6666/excel/exportExcel',
data: params,
responseType: 'arraybuffer',
headers: {
'Content-Type': 'application/json;charset=utf-8',
'accessToken': 'niceyoo'
}
});
};
vue中调⽤:
if(res.byteLength!==0){
fileDownload(res,employeesName+'.xls');
}else{
<("⽆法到对应的⽂件");
}
});
其中 fileDownload ⽅法为引⼊的js-file依赖:"js-file-download": "^0.4.12",
导出结果如下:
四、⾃定义模板导出
模板⽂件:
导出⽂件:
后端代码:
@RequestMapping("download")
public String download(ModelMap modelMap) {
Map<String, Object> map = new HashMap<String, Object>();
TemplateExportParams params = new TemplateExportParams("doc/foreach.xlsx");    List<TemplateExcelExportEntity> list = new ArrayList<TemplateExcelExportEntity>(); for (int i = 0; i < 4; i++) {
TemplateExcelExportEntity entity = new TemplateExcelExportEntity();
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 = new ArrayList<Map<String, Object>>();
for (int i = 0; i < 1; i++) {
Map<String, Object> testMap = new HashMap<String, Object>();
testMap.put("id", "xman");
testMap.put("name", "⼩明" + i);
testMap.put("sex", "1");
mapList.add(testMap);
}
map.put("maplist", mapList);
mapList = new ArrayList<Map<String, Object>>();
for (int i = 0; i < 6; i++) {
Map<String, Object> testMap = new HashMap<String, Object>();
testMap.put("si", "xman");
el表达式获取map的值mapList.add(testMap);
}
map.put("sitest", mapList);
modelMap.put(TemplateExcelConstants.FILE_NAME, "⽤户信息");
modelMap.put(TemplateExcelConstants.PARAMS, params);
modelMap.put(TemplateExcelConstants.MAP_DATA, map);
return TemplateExcelConstants.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: maplist t t.id }}
t 表⽰预定义值,表⽰集合中的任意对象,如上表⽰,mplist 中每个对象叫做 t,t.id 就表⽰ t 单个元素数据的 id 属性,t 的作⽤就是占位符。EasyPOI测试项⽬
可以下载这个项⽬跑⼀下,基本覆盖了⽐较全的⽤法⽰例。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。