easyexcel操作Excle
EasyExcel
EasyExcel的优点
Java 中操作 Excel 的框架 POI、JXT,但是他们都存在一个问题:非常的消耗内存。这时候阿里的大佬在 POI 的基础上进一步重写,封装得到了 EasyExcel,它最大的好处就是解决了过于消耗内存问题,也让使用者使用更加便利。
EasyExcel操作Excel
引入依赖
1 | <dependency> |
相关注解
注解说明–easypoi起因就是Excel的导入导出,最初的模板是实体和Excel的对应,model–row,filed–col 这样利用注解我们可以和容易做到excel到导入导出经过一段时间发展,现在注解有5个类分别是:
- @Excel 作用到filed上面,是对Excel一列的一个描述
- @ExcelCollection 表示一个集合,主要针对一对多的导出,比如一个老师对应多个科目,科目就可以用集合表示
- @ExcelEntity 表示一个继续深入导出的实体,但他没有太多的实际意义,只是告诉系统这个对象里面同样有导出的字段
- @ExcelIgnore 和名字一样表示这个字段被忽略跳过这个导导出
- @ExcelTarget 这个是作用于最外层的对象,描述这个对象的id,以便支持一个对象可以针对不同导出做出不同处理
@ExcelTarget
- 说明:用在实体类上标识是一个可以通过EasyPOI导入导出的实体类
- 相关属性:
- value:
[String][定义id唯一标识,不能重复]
常用
- height:
[Double][定义单元格高度]
- fontSize:
[short ][定义单元格字体大小]
- value:
1 |
|
@Excel
- 说明:用在filed(属性)上面,是对Excel一列的一个描述
- 常用属性:
- name:
[String][生成Excel表格中列名]
- needMerge:
[boolean][是否需要纵向合并单元格(用于含有list中,单个的单元格,合并list创建的多个row)]
- orderNum :
[String][指定生成Excel中列的顺序,按照数字自然顺序排序]
- savePath :
[String][指定导入Excel中图片的保存路径]
- type:
[String][导出类型 1 是文本 2 是图片,3 是函数,10 是数字 默认是文本]
- width:
[Double][指定导出Excel时列的宽度]
- isImportField:
[boolean][是否是导入字段,如果没有说明是错误的Excel]
- exportFormat:
[String][导出Excel的时间格式]
- importFormat:
[String][导入Excel的时间格式]
- format:
[String][相当于同时设置了exportFormat和importFormat]
- imageType:
[int ][导出类型 1 从file读取 2 是从数据库中读取 默认是文件 同样导入也是一样的]
- suffix :
[String][文字后缀,如% 90 变成90%]
- replace:
[json对象][数据替换 要替换的值_替换的值,例如:"激活_0","锁定_1"]
- name:
1 | public class User implements Serializable { |
@ExcelEntity
- 说明:标记是不是导出excel 标记为实体类,一遍是一个内部属性类,标记是否继续穿透
- 常用属性:
- name:
[String][定义唯一标识]
- name:
1 |
|
@ExcelCollection
- 说明:一对多的集合注解,用以标记集合是否被数据以及集合的整体排序
- 常用属性
- name:
[String][定义集合列名]
- orderNum:
[int][用来指定导出excel集合内列的顺序]
- type:
[Class\<?>][用来指定导出是创建对象类型]
- name:
1 |
|
@ExcelIgnore
- 说明:用在属性上,导出Excel时忽略这个属性
1 | // @Excel(name = "年龄", orderNum = "4", suffix = " $") |
导出Excel
1.导出基本数据
注意:导出Excel的对象必须实现对象序列化接口
定义对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30package com.easy.entity;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* @author jingLv
* @date 2021/01/19
*/
public class User implements Serializable {
private static final long serialVersionUID = -3764618099931012959L;
private String id;
private String name;
private Integer age;
private Date bir;
private String status;
}
定义测试数据及导出Excel
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58package com.easy.demo;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.easy.entity.User;
import org.apache.poi.ss.usermodel.Workbook;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 导出excel
*
* @author jingLv
* @date 2021/01/19
*/
public class ExportExcel {
public static void main(String[] args) throws IOException {
//获取数据
List<User> users = getUsers();
// 导出excel
// 参数:exportParams 导出配置对象, 参数2:导出的类型, 参数3:导出数据集合
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("用户信息列表", "用户信息"), User.class, users);
// 将excel写入指定位置
FileOutputStream outputStream = new FileOutputStream("/Users/apple/JavaProject/operation-excel/ExportExcel.xls");
workbook.write(outputStream);
// 关闭流
outputStream.close();
workbook.close();
}
/**
* 定义导出数据
*
* @return
*/
public static List<User> getUsers() {
List<User> users = new ArrayList<>();
for (int i = 0; i < 5; i++) {
User user = new User();
user.setId(String.valueOf(i));
user.setName("阿花number" + i);
user.setAge(10 + i);
user.setBir(new Date());
if (i % 2 == 0) {
user.setStatus("0");
} else {
user.setStatus("1");
}
users.add(user);
}
return users;
}
}
执行结果及查看Excel
2.导出指定字段
将age的属性不导出excel中
1 | package com.easy.entity; |
执行完成查看excel
3.导出list集合
- 定义实体加入集合对象
1 | package com.easy.entity; |
- 修改测试数据及导出Excel
1 | package com.easy.demo; |
- 执行完成查看excel
从上面的结果可以看出,导出格式是默认图片中数组的格式,如果要自定义导出格式怎么办?
自定义导出格式可以在对应的get方法中进行处理即可,如下代码:
1 | package com.easy.entity; |
执行完成查看excel
从上图看到,爱好一列已经是我们定义的格式了
4.导出对象中含有对象
导出对象中含有其他对象的Excel
新建新对象,Card.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23package com.easy.entity;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import lombok.Data;
import java.io.Serializable;
/**
* @author jingLv
* @date 2021/01/20
*/
public class Card implements Serializable {
private static final long serialVersionUID = 9083730912519223193L;
private String id;
private String address;
}
在User对象中定义Card对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51package com.easy.entity;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelEntity;
import cn.afterturn.easypoi.excel.annotation.ExcelIgnore;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* @author jingLv
* @date 2021/01/19
*/
public class User implements Serializable {
private static final long serialVersionUID = -3764618099931012959L;
private String id;
private String name;
// @Excel(name = "年龄", orderNum = "4", suffix = " $")
private Integer age;
private Date bir;
private String status;
// @Excel(name = "爱好", orderNum = "6", width = 20.0)
// 1. 忽略该字段
private List<String> habits;
// 2. 定义爱好字符串代替habits
private String habitsStr;
// 3. 修改get方法
public String getHabitsStr() {
StringBuilder sb = new StringBuilder();
this.habits.forEach(s -> sb.append(s).append("、"));
return sb.toString();
}
// 标识一对一的关系
private Card card;
}
测试数据中定义Card数据及导出Excel
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68package com.easy.demo;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.easy.entity.Card;
import com.easy.entity.User;
import org.apache.poi.ss.usermodel.Workbook;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
* 导出excel
*
* @author jingLv
* @date 2021/01/19
*/
public class ExportExcel {
public static void main(String[] args) throws IOException {
//获取数据
List<User> users = getUsers();
// 导出excel
// 参数:exportParams 导出配置对象, 参数2:导出的类型, 参数3:导出数据集合
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("用户信息列表", "用户信息"), User.class, users);
// 将excel写入指定位置
FileOutputStream outputStream = new FileOutputStream("/Users/apple/JavaProject/operation-excel/ExportExcel.xls");
workbook.write(outputStream);
// 关闭流
outputStream.close();
workbook.close();
}
/**
* 定义导出数据
*
* @return
*/
public static List<User> getUsers() {
List<User> users = new ArrayList<>();
for (int i = 0; i < 5; i++) {
User user = new User();
user.setId(String.valueOf(i));
user.setName("阿花number" + i);
user.setAge(10 + i);
user.setBir(new Date());
if (i % 2 == 0) {
user.setStatus("0");
user.setHabits(Arrays.asList("打篮球", "看书", "看片"));
} else {
user.setStatus("1");
user.setHabits(Arrays.asList("喝酒", "抽烟", "烫头"));
}
// Card赋值
Card card = new Card();
card.setIdCard("123456789");
card.setAddress("北京朝阳区");
user.setCard(card);
users.add(user);
}
return users;
}
}执行完成查看excel
5.导出一对多关系
往往在业务比较复杂时,我们需要导出一对多关联关系处理,如 导出学生课程信息,导出用户的所有订单信息等等….
新增一个订单对象,Order.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28package com.easy.entity;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @author jingLv
* @date 2021/01/20
*/
public class Order implements Serializable {
private static final long serialVersionUID = -8486811488058323527L;
private String id;
private String name;
}
在User对象中定义Order对象集合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51package com.easy.entity;
import cn.afterturn.easypoi.excel.annotation.*;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* @author jingLv
* @date 2021/01/19
*/
public class User implements Serializable {
private static final long serialVersionUID = -3764618099931012959L;
private String id;
private String name;
// @Excel(name = "年龄", orderNum = "4", suffix = " $")
private Integer age;
private Date bir;
private String status;
// @Excel(name = "爱好", orderNum = "6", width = 20.0)
// 1. 忽略该字段
private List<String> habits;
// 2. 定义爱好字符串代替habits
private String habitsStr;
// 3. 修改get方法
public String getHabitsStr() {
StringBuilder sb = new StringBuilder();
this.habits.forEach(s -> sb.append(s).append("、"));
return sb.toString();
}
// 标识一对一的关系
private Card card;
private List<Order> orders;
}
测试数据中定义Order集合数据及导出Excel
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74package com.easy.demo;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.easy.entity.Card;
import com.easy.entity.Order;
import com.easy.entity.User;
import org.apache.poi.ss.usermodel.Workbook;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
* 导出excel
*
* @author jingLv
* @date 2021/01/19
*/
public class ExportExcel {
public static void main(String[] args) throws IOException {
//获取数据
List<User> users = getUsers();
// 导出excel
// 参数:exportParams 导出配置对象, 参数2:导出的类型, 参数3:导出数据集合
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("用户信息列表", "用户信息"), User.class, users);
// 将excel写入指定位置
FileOutputStream outputStream = new FileOutputStream("/Users/apple/JavaProject/operation-excel/ExportExcel.xls");
workbook.write(outputStream);
// 关闭流
outputStream.close();
workbook.close();
}
/**
* 定义导出数据
*
* @return
*/
public static List<User> getUsers() {
List<User> users = new ArrayList<>();
for (int i = 0; i < 5; i++) {
User user = new User();
user.setId(String.valueOf(i));
user.setName("阿花number" + i);
user.setAge(10 + i);
user.setBir(new Date());
if (i % 2 == 0) {
user.setStatus("0");
user.setHabits(Arrays.asList("打篮球", "看书", "看片"));
} else {
user.setStatus("1");
user.setHabits(Arrays.asList("喝酒", "抽烟", "烫头"));
}
// Card赋值
Card card = new Card();
card.setIdCard("123456789");
card.setAddress("北京朝阳区");
user.setCard(card);
// 订单赋值
List<Order> orders = new ArrayList<>();
orders.add(new Order("12", "超短裙"));
orders.add(new Order("13", "连衣裙"));
orders.add(new Order("14", "短裤"));
user.setOrders(orders);
users.add(user);
}
return users;
}
}
执行完成查看excel
6.导出图片
往往随着业务不断变化,可能需要在导出excel时将图片信息也一并导出,如商品图标,用户头像信息等数据,这个时候easypoi该如何处理呢?
在实体类中定义头像信息属性,直接写指定图片路径
1
2
3
4
5
6
7
8
9
10
public class User implements Serializable {
//.....
/**
* 定义头像 直接写指定图片路径
* type的值一定要指定为2
*/
private String photo;
}- type=2该字段表示类型为图片,imageType=1(默认可以不填),表示从file读取是个字符串类型,可以用相对路径也可以用绝对路径优先依次获取。
- type=2该字段表示类型为图片,imageType=2,表示从数据库或者已经读取完毕,字段类型是个字节数组,直接使用,同时,image类型的cell最好设置好宽和高,会百分百缩放cell那么大,不是原尺寸,这里需注意下。
准备图片放入指定路径中,并在测试数据中进行赋值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76package com.easy.demo;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.easy.entity.Card;
import com.easy.entity.Order;
import com.easy.entity.User;
import org.apache.poi.ss.usermodel.Workbook;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
* 导出excel
*
* @author jingLv
* @date 2021/01/19
*/
public class ExportExcel {
public static void main(String[] args) throws IOException {
//获取数据
List<User> users = getUsers();
// 导出excel
// 参数:exportParams 导出配置对象, 参数2:导出的类型, 参数3:导出数据集合
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("用户信息列表", "用户信息"), User.class, users);
// 将excel写入指定位置
FileOutputStream outputStream = new FileOutputStream("/Users/apple/JavaProject/operation-excel/ExportExcel.xls");
workbook.write(outputStream);
// 关闭流
outputStream.close();
workbook.close();
}
/**
* 定义导出数据
*
* @return
*/
public static List<User> getUsers() {
List<User> users = new ArrayList<>();
for (int i = 0; i < 5; i++) {
User user = new User();
user.setId(String.valueOf(i));
user.setName("阿花number" + i);
user.setAge(10 + i);
user.setBir(new Date());
if (i % 2 == 0) {
user.setStatus("0");
user.setHabits(Arrays.asList("打篮球", "看书", "看片"));
} else {
user.setStatus("1");
user.setHabits(Arrays.asList("喝酒", "抽烟", "烫头"));
}
// Card赋值
Card card = new Card();
card.setIdCard("123456789");
card.setAddress("北京朝阳区");
user.setCard(card);
// 订单赋值
List<Order> orders = new ArrayList<>();
orders.add(new Order("12", "超短裙"));
orders.add(new Order("13", "连衣裙"));
orders.add(new Order("14", "短裤"));
user.setOrders(orders);
// 图片复制绝对路径
user.setPhoto("/Users/apple/Documents/关键字01.png");
users.add(user);
}
return users;
}
}
执行完成,查看excel
7.大数据量导出
大数据导出是当我们的导出数量在几万,到上百万的数据时,一次从数据库查询这么多数据加载到内存然后写入会对我们的内存和CPU都产生压力,这个时候需要我们像分页一样处理导出分段写入Excel缓解Excel的压力
exportBigExcel提供的方法:
1 | /** |
注意:最好大量数据进行分页处理,每次导出数据最好不要超过1W条记录
导入Excel
1. 导入基本数据
准备导入的目标Excel
注意:日期的格式是2021/1/2 10:47:30 AM
定义导出数据基本对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32package com.easy.entity;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 注意:对象名必须要与excel的列名对应上
*
* @author jingLv
* @date 2021/01/25
*/
public class Student implements Serializable {
private static final long serialVersionUID = -4127812440236301876L;
private String id;
private String name;
private Integer age;
private Date bir;
private String status;
}导入excel中的数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22package com.easy.demo;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import com.easy.entity.Student;
import java.io.File;
import java.util.List;
/**
* @author jingLv
* @date 2021/01/25
*/
public class ImportExcel {
public static void main(String[] args) {
//定义导入参数
ImportParams importParams = new ImportParams();
//导出数据 餐数1:当如excel文件 参数2:导入对象的类型 参数3:导入参数配置
List<Student> students = ExcelImportUtil.importExcel(new File("/Users/apple/JavaProject/operation-excel/ExportExcel.xls"), Student.class, importParams);
students.forEach(System.out::println);
}
}
执行并查看结果
2. 导入小技巧
读取指定的sheet
比如要读取上传得第二个sheet 那么需要把startSheetIndex = 1 就可以了读取几个sheet
比如读取前2个sheet,那么 sheetNum=2 就可以了读取第二个到第五个sheet
设置 startSheetIndex = 1 然后sheetNum = 4读取全部的sheet
sheetNum 设置大点就可以了判断一个Excel是不是合法的Excel
importFields 设置下值,就是表示表头必须至少包含的字段,如果缺一个就是不合法的excel,不导入
3. 带图片导入
有图片的导出就有图片的导入,导入的配置和导出是一样的,但是需要设置保存路径
准备数据
定义导出数据基本对象,图片的列需要设置保存路径
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35package com.easy.entity;
import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 注意:对象名必须要与excel的列名对应上
*
* @author jingLv
* @date 2021/01/25
*/
public class Student implements Serializable {
private static final long serialVersionUID = -4127812440236301876L;
private String id;
private String name;
private Integer age;
private Date bir;
private String status;
private String photo;
}- type:类型为2是为图片类型
- savePath:设置保存图片的位置
导入excel
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27package com.easy.demo;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import com.easy.entity.Student;
import java.io.File;
import java.util.List;
/**
* @author jingLv
* @date 2021/01/25
*/
public class ImportExcel {
public static void main(String[] args) {
//定义导入参数
ImportParams importParams = new ImportParams();
// 导入时校验数据模板,是不是正确的Excel
importParams.setImportFields(new String[]{"生日"});
//是否保存上传的excel
importParams.setNeedSave(false);
importParams.setSaveUrl("/Users/apple/JavaProject/operation-excel/easy-excel/image");
//导出数据 餐数1:当如excel文件 参数2:导入对象的类型 参数3:导入参数配置
List<Student> students = ExcelImportUtil.importExcel(new File("/Users/apple/JavaProject/operation-excel/ExportExcel.xls"), Student.class, importParams);
students.forEach(System.out::println);
}
}
执行测试及结果