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查看

Springboot---后台导出功能,easyExcel的更多相关文章

  1. SpringCloud微服务实战——搭建企业级开发框架(三十):整合EasyExcel实现数据表格导入导出功能

      批量上传数据导入.数据统计分析导出,已经基本是系统必不可缺的一项功能,这里从性能和易用性方面考虑,集成EasyExcel.EasyExcel是一个基于Java的简单.省内存的读写Excel的开源项 ...

  2. SpringBoot图文教程9—SpringBoot 导入导出 Excel 「Apache Poi」

    有天上飞的概念,就要有落地的实现 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍 先赞后看,养成习惯 SpringBoot 图文教程系列文章目录 SpringBoot图文教程1「概念+ ...

  3. ActiveReports中如何在后台导出运行时绑定数据源报表

    ActiveReports支持运行时绑定数据源功能,这种绑定数据源方法使用较为普及,然而很多系统中都需要在后台导出报表文件,所以用户就很困惑,ActiveReports中如何在后台导出运行时绑定数据源 ...

  4. 用SpringMvc实现Excel导出功能

    以前只知道用poi导出Excel,最近用了SpringMvc的Excel导出功能,结合jxl和poi实现,的确比只用Poi好,两种实现方式如下: 一.结合jxl实现: 1.引入jxl的所需jar包: ...

  5. 利用Aspose.Cells完成easyUI中DataGrid数据的Excel导出功能

    我准备在项目中实现该功能之前,google发现大部分代码都是利用一般处理程序HttpHandler实现的服务器端数据的Excel导出,但是这样存在的问题是ashx读取的数据一般都是数据库中视图的数据, ...

  6. [转载]ecshop 实现订单导出功能 指定订单导出 EXCEL 数据文件

    当下很多功能都觉得理所当然,但是实际作为2012年停更的ECSHOP来说,很多功能其实都是缺少的,好比今天的要说的功能 订单导出 这个功能对于现在的产品设计来说,应该属于一个比较常规的功能,但是ECS ...

  7. 实现excel导入导出功能,excel导入数据到页面中,页面数据导出生成excel文件

    今天接到项目中的一个功能,要实现excel的导入,导出功能.这个看起来思路比较清楚,但是做起了就遇到了不少问题. 不过核心的问题,大家也不会遇到了.每个项目前台页面,以及数据填充方式都不一样,不过大多 ...

  8. xadmin后台导出时gunicorn报错ascii

    django + xadmin + nginx + gunicorn部署后,xadmin后台导出model数据报错,gunicorn日志记录为:UnicodeEncodeError: 'ascii' ...

  9. asp.net导出excel-一行代码实现excel、xml、pdf、word、html、csv等7种格式文件导出功能而且美观-SNF快速开发平台

    分享: 腾讯微博  新浪微博   搜狐微博   网易微博  腾讯朋友  百度贴吧  豆瓣   QQ好友  人人网 作者:王春天  原文地址:http://www.cnblogs.com/spring_ ...

随机推荐

  1. Python三引号(triple quotes)

    python中三引号可以将复杂的字符串进行复制: python三引号允许一个字符串跨多行,字符串中可以包含换行符.制表符以及其他特殊字符. 三引号的语法是一对连续的单引号或者双引号(通常都是成对的用) ...

  2. 斐波那契数列的通项公式x+洛谷P2626x

    #include<cstdio> #include<iostream> #include<cmath> using namespace std; int main( ...

  3. Jmeter设置成中文

    首次启动Jmeter为中文 选择后即变为中文

  4. $\LaTeX$数学公式大全12

    $12\ Font\ sizes$ ${\displaystyle \int f^{-1}(x-x_a)\,dx}$ {\displaystyle \int f^{-1}(x-x_a)\,dx} ${ ...

  5. C++入门经典-友元

    1:在讲述类的内容时说明了隐藏数据成员的好处,但是有时类会允许一些特殊的函数直接读写其私有数据成员. 使用friend关键字可以使特定的函数或者别的类的所有成员函数对私有数据成员进行读写.这既可以保持 ...

  6. Windows Server 2012R2 / 2008R2 修改密码策略(password policy)

    一.  针对于未添加到域中的机器 cmd中执行gpedit.msc 打开Local Group Policy Editor查看password policy设置,修改对应的password polic ...

  7. JSP——JavaServer Page中的隐式对象(implicit object)、指令(directive)、脚本元素(scripting element)、动作(action)、EL表达式

    目录 1.JSP概述 2.注释(comment) 2.1.JSP注释 2.2.HTML注释 3.隐式对象(implicit object) 3.1.隐式对象清单 3.2.request对象 3.3.o ...

  8. Cortex-M3 在C中上报入栈的寄存器和各fault状态寄存器

    因为在标准C语音中是不能获取SP指针的.因而,如果想通过C代码来获取入栈的寄存器值,需要配合一小段汇编代码来获取当前的SP值,然后再把这个SP值以参数形式传送给C代码,最后以指针的形式把栈中的各寄存器 ...

  9. 实用的60个CSS代码片段[上]

    1.垂直对齐 如果你用CSS,则你会有困惑:我该怎么垂直对齐容器中的元素?现在,利用CSS3的Transform,可以很优雅的解决这个困惑: .verticalcenter{ position: re ...

  10. 自定义有焦点的TextView实现广告信息左右一直滚动的跑马灯效果

    import android.content.Context; import android.text.TextUtils; import android.util.AttributeSet; imp ...