SpringBoot图文教程10—模板导出|百万数据Excel导出|图片导出「easypoi」
有天上飞的概念,就要有落地的实现
概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍
先赞后看,养成习惯
SpringBoot 图文教程系列文章目录
- SpringBoot图文教程1「概念+案例 思维导图」「基础篇上」
- SpringBoot图文教程2—日志的使用「logback」「log4j」
- SpringBoot图文教程3—「‘初恋’情结」集成Jsp
- SpringBoot图文教程4—SpringBoot 实现文件上传下载
- SpringBoot图文教程5—SpringBoot 中使用Aop
- SpringBoot图文教程6—SpringBoot中过滤器的使用
- SpringBoot图文教程7—SpringBoot拦截器的使用姿势这都有
- SpringBoot图文教程8 — SpringBoot集成MBG「代码生成器」
- SpringBoot图文教程9—SpringBoot 导入导出 Excel 「Apache Poi」
前言
上一篇文章中简单介绍了Poi的使用方式,但是用Poi去写代码着实繁琐了一些,假如你要实现的是复杂的需求,譬如:图片导出,多表数据导出,模板导出,大数据量导出等等,用最原生的Poi就不是很好的选择了。
难道要自己封装工具类了吗?
no no 轮子虽好,最好是别人写好的。所以从这篇文章开始介绍两个优秀的Poi工具 Easypoi 和 阿里开源的 EasyExcel。
EasyPoi
EasyPoi 是对poi封装的一个工具库,封装好了一些常见的Excel操作
- 最基本的导入导出
- 图片的导入导出
- 多表数据的导入导出
- 大批量数据的导入导出
- 模板的导出
接下来我们一起来将以上的功能实现出来
最基本的导入导出
最基本的导入导出,要导出的数据的实体类如下:
public class Teacher {
/**
* 老师的主键
*/
private Integer teacherId;
/**
* 名字
*/
private String teacherName;
/**
* 头像图片地址
*/
private String teacherImage;
/**
* 老师的状态 0代表正常 1代表删除
*/
private Integer teacherStatus;
}
省略get set
1.导入依赖
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>3.2.0</version>
</dependency>
2.给要导出数据实体类加注解
我们要导出的数据的实体类是Teacher 所以需要给Teacher加 Easypoi的注解
EasyPoi是注解式开发,所有的注解详情见官方文档,但是如果要完成的需求是最简单的导入导出的话,@Excel
一个注解就足够了。
@Excel
这个是必须使用的注解,如果需求简单只使用这一个注解也是可以的,涵盖了常用的Excel需求,需要大家熟悉这个功能,主要分为基础,图片处理,时间处理,合并处理几块
@Excel 的官方api http://easypoi.mydoc.io/#text_186900
添加好注解的实体类如下:
3.直接使用 EasyPoi 中的工具类导入导出
EasyPoi 是注解式开发,对Excel所有的定义,样式也好,日期格式化也好,都是在实体类的注解中定义
导出代码
/**
* easypoi导出
*/
@Test
public void test4() throws IOException {
// 模拟数据
List<Teacher> list = new ArrayList<>();
list.add(new Teacher(1,"李老师","hhh.jpg",1));
list.add(new Teacher(2,"李老师","hhh.jpg",1));
list.add(new Teacher(3,"李老师","hhh.jpg",1));
list.add(new Teacher(4,"李老师","hhh.jpg",1));
list.add(new Teacher(5,"李老师","hhh.jpg",1));
list.add(new Teacher(6,"李老师","hhh.jpg",1));
/**
* 导出参数对象
* 参数1 标题
* 参数2 表的名字
*/
ExportParams exportParams = new ExportParams("所有老师数据","teacher");
/**
* exportExcel 导出Excel文件
* 参数1 导出参数对象
* 参数2 要导出的实体类的类对象
* 参数3 要导出的数据 需要一个集合 数据库查询出来的老师对象的集合
*
* 返回值就是封装好的文件对象
*/
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, Teacher.class, list);
workbook.write(new FileOutputStream("/Users/lubingyang/Desktop/teachers.xls"));
}
导出之后的Excel如下:
导入代码
关于导入 没有需要单独定义的配置 只要能够导出就能够直接写导入的代码
/**
* easypoi导入
*/
@Test
public void test5() throws Exception {
FileInputStream inputStream = new FileInputStream("/Users/lubingyang/Desktop/teachers.xls");
/**
* ImportParams 导入参数对象
* 定义标题栏和表头数据
*/
ImportParams importParams = new ImportParams();
importParams.setTitleRows(1);
importParams.setHeadRows(1);
/**
* importExcel 导入方法
* 参数1 流 读取要导入的文件
* 参数2 要导入的实体类的类对象 上师对象的类对象
* 参数3 导入参数对象
*
* 返回值 导入数据 直接封装为集合对象
*/
List<Teacher> teachers = ExcelImportUtil.importExcel(inputStream, Teacher.class, importParams);
for (Teacher teacher : teachers) {
System.out.println(teacher);
}
}
值的替换 图片导入导出
值的替换
通过官方文档很容易找到如下内容
根据文档修改实体类
执行导出代码 可以得到如下效果
图片导出
修改实体类
修改完之后可以直接导出
根据测试,如果图片地址字段存储的是相对路径,最好处理为网络绝对绝对路径或者本地绝对路径
图片导入
在实体类的注解上需要设置图片导入之后的保存路径
api
集合数据导入导出
在增加一个实体类 Student ,在Teacher类中有一个学生集合,导出Teacher的同时需要将Student的数据也导出,对应的数据库操作一般都是连表查询,那么这样的数据怎么导出到Excel呢?
实体类加注解
针对 Teacher 类集合属性的导入导出,需要给该属性加注解 @ExcelConllection
官方文档地址:http://easypoi.mydoc.io/#text_197841
导出代码如下
@Test
public void test4() throws IOException {
List<Student> students = new ArrayList<>();
students.add(new Student("hh","男"));
students.add(new Student("hh","男"));
// 模拟数据
List<Teacher> list = new ArrayList<>();
list.add(new Teacher(1,"李老师","/Users/lubingyang/Desktop/hhh.jpg",1,students));
list.add(new Teacher(6,"李老师","/Users/lubingyang/Desktop/hhh.jpg",1,students));
/**
* 导出参数对象
* 参数1 标题
* 参数2 表的名字
*/
ExportParams exportParams = new ExportParams("所有老师数据","teacher");
/**
* exportExcel 导出Excel文件
* 参数1 导出参数对象
* 参数2 要导出的实体类的类对象
* 参数3 要导出的数据 需要一个集合 数据库查询出来的老师对象的集合
*
* 返回值就是封装好的文件对象
*/
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, Teacher.class, list);
workbook.write(new FileOutputStream("/Users/lubingyang/Desktop/teachers.xls"));
}
效果如下
大批量数据导出(百万数据)
关于百万数据导出 推荐使用 阿里开源的 EasyExcel 官方介绍可以将内存控制在kb
大数据导出是当我们的导出数量在几万,到上百万的数据时,一次从数据库查询这么多数据加载到内存,然后写入会对我们的内存和CPU都产生压力,这个时候需要我们像分页一样处理导出,分段写入Excel缓解压力
EasyPoi提供的是两个方法 强制使用 xssf版本的Excel
/**
* @param entity
* 表格标题属性
* @param pojoClass
* Excel对象Class
* @param dataSet
* Excel对象数据List
*/
public static Workbook exportBigExcel(ExportParams entity, Class<?> pojoClass,
Collection<?> dataSet) {
ExcelBatchExportServer batachServer = ExcelBatchExportServer
.getExcelBatchExportServer(entity, pojoClass);
return batachServer.appendData(dataSet);
}
public static void closeExportBigExcel() {
ExcelBatchExportServer batachServer = ExcelBatchExportServer.getExcelBatchExportServer(null,
null);
batachServer.closeExportBigExcel();
}
思路
- 分页读取数据
- 将每次读取到的数据写入Excel
实现代码
准备一个百万数据的用户表
@Test
public void test10() throws IOException {
Date start = new Date();
// 查询数据库 用户表总条数
Integer userCount = userDao.selectCount(null);
// 计算总页数
Integer pageCount = userCount / 200000 + 1;
List<CmfzUser> users = null;
Workbook workbook = null;
ExportParams params = new ExportParams("大数据测试", "测试");
// 查询测试 页数 每次查询20w条数据
for (int i = 1; i <= pageCount; i++) {
System.out.println(i);
users = userDao.selectPage(new Page<>(i, 200000), null).getRecords();
// 通过 EasyPoi 的大数据导出方法 导出
workbook = ExcelExportUtil.exportBigExcel(params, CmfzUser.class, users);
users.clear();
}
Date end = new Date();
System.out.println(new Date().getTime() - start.getTime());
workbook.write(new FileOutputStream("/Users/lubingyang/Desktop/hhhh.xlsx"));
}
执行的总时间为:
Tips:
- 时间问题没做详细的性能测试 官方有相关的测试:http://easypoi.mydoc.io/#text_202983
- 数据库查询使用MybatisPlus 如果有兴趣 可以看我的相关文章 SpringBoot 集成 MybatisPlus
- 百万数据用 xssf 不如使用 CSV 和 SXSSF( POI针对大数据量的导出,专门提供了一个类)
模板导出
模板是处理复杂Excel的简单方法,复杂的Excel样式,可以用Excel直接编辑,完美的避开了代码编写样式的雷区,同时指令的支持,也提了模板的有效性。
EasyPoi支持的指令以及作用
空格分割
三目运算 {{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: 统计数据
采用的写法是{{}}代表表达式,然后根据表达式里面的数据取值
代码如下
示例代码所用模板文件地址:
@Test
public void fe_map() throws Exception {
// 读取模板文件
TemplateExportParams params = new TemplateExportParams(
"/Users/k/Desktop/专项支出用款申请书_map.xls");
// 模拟要写入模板的数据
Map<String, Object> map = new HashMap<String, Object>();
map.put("date", "2014-12-25");
map.put("money", 2000000.00);
map.put("upperMoney", "贰佰万");
map.put("company", "执笔潜行科技有限公司");
map.put("bureau", "财政局");
map.put("person", "JueYue");
map.put("phone", "1879740****");
List<Map<String, String>> listMap = new ArrayList<Map<String, String>>();
for (int i = 0; i < 4; i++) {
Map<String, String> lm = new HashMap<String, String>();
lm.put("id", i + 1 + "");
lm.put("zijin", i * 10000 + "");
lm.put("bianma", "A001");
lm.put("mingcheng", "设计");
lm.put("xiangmumingcheng", "EasyPoi " + i + "期");
lm.put("quancheng", "开源项目");
lm.put("sqje", i * 10000 + "");
lm.put("hdje", i * 10000 + "");
listMap.add(lm);
}
map.put("maplist", listMap);
// 导出模板
Workbook workbook = ExcelExportUtil.exportExcel(params, map);
FileOutputStream fos = new FileOutputStream("/Users/k/Desktop/专项支出用款申请书111_map.xls");
workbook.write(fos);
fos.close();
}
结果如下
总结
Tips:通过EasyPoi 基本上已经可以完成所有的Excel相关的工作
可以关注相关文章 poi 和 EasyExcel 以及 Poi中文 API 文档 「40种操作 Excel文件的姿势」
恭喜你完成了本章的学习,为你鼓掌!如果本文对你有帮助,请帮忙点赞,评论,转发,这对作者很重要,谢谢。
让我们再次回顾本文的学习目标
- 掌握SpringBoot中Easypoi的使用
要掌握SpringBoot更多的用法,请持续关注本系列教程。
求关注,求点赞,求转发
欢迎关注本人公众号:鹿老师的Java笔记,将在长期更新Java技术图文教程和视频教程,Java学习经验,Java面试经验以及Java实战开发经验。
SpringBoot图文教程10—模板导出|百万数据Excel导出|图片导出「easypoi」的更多相关文章
- SpringBoot图文教程11—从此不写mapper文件「SpringBoot集成MybatisPlus」
有天上飞的概念,就要有落地的实现 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍 先赞后看,养成习惯 SpringBoot 图文教程系列文章目录 SpringBoot图文教程1「概念+ ...
- SpringBoot图文教程12—SpringData Jpa的基本使用
有天上飞的概念,就要有落地的实现 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍 先赞后看,养成习惯 SpringBoot 图文教程系列文章目录 SpringBoot图文教程1「概念+ ...
- SpringBoot图文教程14—SpringBoot集成EasyExcel「上」
有天上飞的概念,就要有落地的实现 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍 先赞后看,养成习惯 SpringBoot 图文教程系列文章目录 SpringBoot图文教程1「概念+ ...
- SpringBoot图文教程15—项目异常怎么办?「跳转404错误页面」「全局异常捕获」
有天上飞的概念,就要有落地的实现 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍 先赞后看,养成习惯 SpringBoot 图文教程系列文章目录 SpringBoot图文教程1-Spr ...
- SpringBoot图文教程17—上手就会 RestTemplate 使用指南「Get Post」「设置请求头」
有天上飞的概念,就要有落地的实现 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍 先赞后看,养成习惯 SpringBoot 图文教程系列文章目录 SpringBoot图文教程1-Spr ...
- SpringBoot图文教程9—SpringBoot 导入导出 Excel 「Apache Poi」
有天上飞的概念,就要有落地的实现 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍 先赞后看,养成习惯 SpringBoot 图文教程系列文章目录 SpringBoot图文教程1「概念+ ...
- SpringBoot图文教程「概念+案例 思维导图」「基础篇上」
有天上飞的概念,就要有落地的实现 概念+代码实现是本文的特点,教程将涵盖完整的图文教程,代码案例 每个知识点配套自测面试题,学完技术自我测试 本文初学向,所以希望文中所有的代码案例都能敲一遍 大哥大姐 ...
- 🔥SpringBoot图文教程2—日志的使用「logback」「log4j」
有天上飞的概念,就要有落地的实现 概念+代码实现是本文的特点,教程将涵盖完整的图文教程,代码案例 文章结尾配套自测面试题,学完技术自我测试更扎实 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例 ...
- SpringBoot图文教程5—SpringBoot 中使用Aop
有天上飞的概念,就要有落地的实现 概念+代码实现是本文的特点,教程将涵盖完整的图文教程,代码案例 文章结尾配套自测面试题,学完技术自我测试更扎实 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例 ...
随机推荐
- linux操作提示:“Can't open file for writing”或“operation not permitted”的解决办法
在linux上使用vi命令修改一个文件内容的时候,发现无法保存,每次写完使用":q!"命令可以正常退出但是使用":wq!"命令保存文件并退出时出现一下信息提示: ...
- php time()时间戳作为文件名产生文件同名的bug
/*time()函数生成的文件名可能是相同的,因为如果php运行的过程如果足够快,time()函数调用的足够频繁,那么有可能time()生成的时间戳会相同,因为时间戳是以秒为单位,所以如果足够频繁有可 ...
- 37)PHP,获取数据库值并在html中显示(晋级2)
下面的是上一个的改进版,我知道为啥我的那个有问题了,因为我的__construct()这个函数的里面的那个变量名字搞错了,哎,这是经常犯得毛病,傻了吧唧,气死我了. 之前的那个变量的代码样子: cla ...
- 吴裕雄--天生自然C语言开发:运算符
#include <stdio.h> int main() { ; ; int c ; c = a + b; printf("Line 1 - c 的值是 %d\n", ...
- LeetCode No.118,119,120
No.118 Generate 杨辉三角 题目 给定一个非负整数 numRows,生成杨辉三角的前 numRows 行. 在杨辉三角中,每个数是它左上方和右上方的数的和. 示例 输入: 5 输出: [ ...
- Linux命令:ldd
1.ldd不是一个可执行程序,而是一个shell脚本. zlf@ubuntu:~/$ which ldd /usr/bin/ldd zlf@ubuntu:~/$ file /usr/bin/ldd / ...
- javascript正则表达式和php匹配 获取文章的 图片集
1.脚本javascript: var str="<a href='05.html'><img src='img/4.jpg' alt='单击查看下一张' />< ...
- OA-APP增加空间
第一步:虚拟机增加一块200G的硬盘,使用fdisk -l 命令可以看到增加的硬盘(centos6可能需要重启系统) 第二步:然后对 /dev/sdc进行分区 第三步:创建一个分区 第四步:重新查看磁 ...
- HTML5 Fundamental Syntax
HTML5 Fundamental Syntax */--> HTML5 Fundamental Syntax 1 Adding Document Structure with HTML5's ...
- 前端-html-长期维护
############### 前端学什么? ################ # 前端三大部分 # HTML,页面内容,学习标签 # CSS,页面样式,学习选择器和属性 # JS,页面 ...