有天上飞的概念,就要有落地的实现

  • 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍

  • 先赞后看,养成习惯

SpringBoot 图文教程系列文章目录

  1. SpringBoot图文教程1「概念+案例 思维导图」「基础篇上」
  2. SpringBoot图文教程2—日志的使用「logback」「log4j」
  3. SpringBoot图文教程3—「‘初恋’情结」集成Jsp
  4. SpringBoot图文教程4—SpringBoot 实现文件上传下载
  5. SpringBoot图文教程5—SpringBoot 中使用Aop
  6. SpringBoot图文教程6—SpringBoot中过滤器的使用
  7. SpringBoot图文教程7—SpringBoot拦截器的使用姿势这都有
  8. SpringBoot图文教程8 — SpringBoot集成MBG「代码生成器」
  9. SpringBoot图文教程9—SpringBoot 导入导出 Excel 「Apache Poi」

前言

上一篇文章中简单介绍了Poi的使用方式,但是用Poi去写代码着实繁琐了一些,假如你要实现的是复杂的需求,譬如:图片导出,多表数据导出,模板导出,大数据量导出等等,用最原生的Poi就不是很好的选择了。

难道要自己封装工具类了吗?

no no 轮子虽好,最好是别人写好的。所以从这篇文章开始介绍两个优秀的Poi工具 Easypoi 和 阿里开源的 EasyExcel。

EasyPoi

EasyPoi 是对poi封装的一个工具库,封装好了一些常见的Excel操作

  • 最基本的导入导出
  • 图片的导入导出
  • 多表数据的导入导出
  • 大批量数据的导入导出
  • 模板的导出

接下来我们一起来将以上的功能实现出来

官网地址:http://easypoi.mydoc.io/#category_50222

最基本的导入导出

最基本的导入导出,要导出的数据的实体类如下:

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();
}

思路

  1. 分页读取数据
  2. 将每次读取到的数据写入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:

  1. 时间问题没做详细的性能测试 官方有相关的测试:http://easypoi.mydoc.io/#text_202983
  2. 数据库查询使用MybatisPlus 如果有兴趣 可以看我的相关文章 SpringBoot 集成 MybatisPlus
  3. 百万数据用 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」的更多相关文章

  1. SpringBoot图文教程11—从此不写mapper文件「SpringBoot集成MybatisPlus」

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

  2. SpringBoot图文教程12—SpringData Jpa的基本使用

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

  3. SpringBoot图文教程14—SpringBoot集成EasyExcel「上」

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

  4. SpringBoot图文教程15—项目异常怎么办?「跳转404错误页面」「全局异常捕获」

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

  5. SpringBoot图文教程17—上手就会 RestTemplate 使用指南「Get Post」「设置请求头」

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

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

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

  7. SpringBoot图文教程「概念+案例 思维导图」「基础篇上」

    有天上飞的概念,就要有落地的实现 概念+代码实现是本文的特点,教程将涵盖完整的图文教程,代码案例 每个知识点配套自测面试题,学完技术自我测试 本文初学向,所以希望文中所有的代码案例都能敲一遍 大哥大姐 ...

  8. 🔥SpringBoot图文教程2—日志的使用「logback」「log4j」

    有天上飞的概念,就要有落地的实现 概念+代码实现是本文的特点,教程将涵盖完整的图文教程,代码案例 文章结尾配套自测面试题,学完技术自我测试更扎实 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例 ...

  9. SpringBoot图文教程5—SpringBoot 中使用Aop

    有天上飞的概念,就要有落地的实现 概念+代码实现是本文的特点,教程将涵盖完整的图文教程,代码案例 文章结尾配套自测面试题,学完技术自我测试更扎实 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例 ...

随机推荐

  1. python,openpyxl,读写excel文件

    import openpyxl as oxl from openpyxl.utils import get_column_letter, column_index_from_string import ...

  2. python-django项目-Linux系统建立django项目_20191117

    python-django项目-Linux系统建立django项目 1,Linux系统下面,cd /usr/local/lib/  看这个下面会有两个python版本,一个2.7,一个3.5,我们使用 ...

  3. vue 起步(一)

    准备 安装nodejs(下载),Windows 安装包(.msi) npm相关 打开cmd查看npm版本, npm -v,如果没有安装npm,执行npm install npm -g进行安装 查询当前 ...

  4. VB6制作的自定义ocx控件

    下载后,解压缩,有一个TreeviewExplorer.ocx文件 在Excel的开发工具选项卡,点击插入ActiveX控件 VBA窗体,VB6窗体.VB.Net窗体都可以使用这个自定义控件的功能. ...

  5. 玩转SpringBoot用好条件相关注解,开启自...

    官方提供的常用条件注解 因为Spring的核心是基于bean的,所以这些条件注解主要是影响bean的注册. 因为注册的bean不同了,最后对外呈现的行为就不同了.不就是自动配置了. 一.最常用的应该是 ...

  6. Python opencv PIL numpy base64互相转化

    PIL2numpy and numpy2PIL from PIL import Image import numpy image = Image.open('timg.jpeg')# image is ...

  7. MySQL性能优化的21条最佳经验

    英文原文:<Top 20+ MySQL Best Practices>,编译:陈皓 今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数据库的性能,这并不只 ...

  8. A 小石的签到题

    题目链接:https://ac.nowcoder.com/acm/contest/949/A 思路: 这题明确的说了是个签到题,但是一直怀疑不是签到题,是唬我的,结果仔细想了想真是这么回事. 每个人必 ...

  9. FPGA模N计数器的实现

    module ModuloN_Cntr(Clock, Clear, Q, QBAR); , UPTO = ;//计数器位数以及模数 input Clock, Clear; :]Q, QBAR; :]C ...

  10. .js——alert()语句

    在.js文件中,通过alert()语句可以生成弹出框,弹出框中的内容message部分可以是常量字符串,也可以是含有变量的字符串连接,下面举几个例子简要说明下: 1. 参数为常量字符串 alert(& ...