背景介绍
easyexcel 表头及数据
表头
简单合并 web项目导出方式 实践出真知
简单动态表头案例遇到的问题
前端联调时excel无法打开
导出数据是后端经典模块之一,从原有的poi到现在的easyexcel等等都在努力的帮助开发们缩小数据与excel之间的鸿沟。但是在简单的导出也会遇到一些有的没的问题,特地写个文章记录下~
一般导出流程图如下:
组装数据: 包括excel中表头、数据及样式
**导出:**文件流
官方文档总结的都是经典~
**表头:**分为固定表头和动态表头,然后再可以继续划分简单版本和复杂版本,其中复杂版本就是那种可以有三四级表头的~ 如下图(图片来源):
固定表头,可声明一个实体类进行定义,如下:
@Data public class TitleData { @ExcelProperty("字符串标题") private String string; @ExcelProperty("日期标题") private Date date; @ExcelProperty("数字标题") private Double doubleData; }
动态表头,只能自己手动写代码进行定义,如下:
// 外层数组,一个值代表一列 List合并> headList = new ArrayList
>(); List
head0 = new ArrayList (); head0.add("字符串标题"); headList.add(head0); List head1 = new ArrayList (); head1.add("日期标题"); headList.add(head1); List head2 = new ArrayList (); head2.add("数字标题"); headList.add(head2);
@Data public class ComplexHeadData { @ExcelProperty({"主标题", "字符串标题"}) private String string; @ExcelProperty({"主标题", "日期标题"}) private Date date; @ExcelProperty({"主标题", "数字标题"}) private Double doubleData; }web项目导出方式
web项目一般有两种导出方式:
提供下载链接(异步):先生成excel并上传至oss/文件服务器,返回文件链接给前端,由前端自行下载文件流(同步):生成excel并塞入response流中
本文主要关注文件流方式,示例代码如下:
// 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman response.setContentType("application/vnd.ms-excel"); response.setCharacterEncoding("utf-8"); // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系 String fileName = URLEncoder.encode("测试", "UTF-8"); response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data());实践出真知 简单动态表头案例
本案例比较简单,根据请求参数time来动态定义表头和创建数据,并以文件流方式返回给前端。 效果如下:
pom中添加依赖:
com.alibaba easyexcel2.2.7
业务逻辑代码如下:
@RestController public class ResultController { @PostMapping(value = "/export") public void export(@RequestParam Integer time) { try { HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse(); response.setHeader("Content-Disposition", "attachment; filename=export.xlsx"); // 响应类型,编码 response.setContentType("application/vnd.ms-excel;charset=utf-8"); response.setCharacterEncoding("utf-8"); EasyExcel.write(response.getOutputStream()).head(getHead(time)).sheet("数据").doWrite(getData(time)); } catch (IOException e) { log.error("导出问卷数据失败!错误信息为:{}", e.getMessage()); e.printStackTrace(); } } private List遇到的问题 前端联调时excel无法打开> getHead(Integer time) { // 外层数组,一个值代表一列 List
> headList = new ArrayList
>(); List
nameList = new ArrayList (); nameList.add("姓名"); headList.add(nameList); List telList = new ArrayList (); telList.add("手机号"); headList.add(telList); List submitDTList = new ArrayList (); submitDTList.add("提交时间"); headList.add(submitDTList); for (int i = 0 ; i < time ; i ++ ) { List list = new ArrayList (); list.add("动态标题" + i); headList.add(list); } return headList; } private List > getData(Integer time) { // 将填写结果 + 提交时间合并为一行数据 List
> resultList = new ArrayList
>(); for (int i = 0 ; i < 3 ; i ++ ) { List
问题描述: 后台用postman调试都ok,能正常打开excel!但是前端调试时下载的excel提示有破损,无法打开!!!
Tips: 勇敢(不怕死)的质疑前端,你代码有BUG!
解决方案: 前端需在request和response中添加responseType: blob设置
(以下伪代码,请重点关注responseType设置即可)
- 前端request应该设置responseType为arraybuffer或blob
return request({ url: '/platform/export', method: 'post', responseType: 'blob', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, data: qs.stringify(data) })
- 前端以blob格式接收response,并设置type为application/msexcel
handleExport(){ exportData({id: this.id}).then(res => { if(res){ const fileName = this.name + '.xlsx'; var blob = new Blob([res], { type: "application/msexcel;charset=utf-8", }); const URL = window.URL || window.webkitURL; const downloadElement = document.createElement("a"); const href = URL.createObjectURL(blob); // 创建下载的链接 downloadElement.href = href; downloadElement.download = fileName; // 下载后文件名 document.body.appendChild(downloadElement); downloadElement.click(); // 点击下载 document.body.removeChild(downloadElement); // 下载完成移除元素 URL.revokeObjectURL(href); // 释放掉blob对象 } }) },
未完待续......
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)