记EasyExcel的初次使用 (生成简单文件和动态表头)
前言
年后回来到三月底一直忙于项目,前段时间才稍微空闲下来。在这个项目中遇到了很多之前没有接触过的东西(虽然不是多高级的东西,但是也算是自己第一次使用),因此打算逐一记录下来,以便以后回看这段时光。
本篇内容主要记录对于EasyExcel的初次使用。
正篇
提到EasyExcel,大多数人都知道是用于生成Excel文件的,而无论是在项目中直接生成还是生成后提供下载,邮件发送等等场景,可以看到首先最重要的就是要生成一个Excel文件。所以,掌握文件的生成至关重要。
EasyExcel简单介绍: EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下,它支持读写百M级别的Excel文件。相较于其他Java领域的Excel解析、生成框架(如Apache POI、jxl等),EasyExcel以其使用简单和节省内存的特点而著称。 (没错,答案来自文心一言,别问我为什么是文心一言,因为不用每次都用登录~)
官方文档地址:easyexcel.opensource.alibaba.com/docs/curren… Github地址:github.com/alibaba/eas…
使用EasyExcel去生成具体的Excel文件可以有多种方式,下面记录我所用到的几种方式
1、使用注解生成
使用注解生成的方式很简单,根据要生成的文件定义不同的实体,在实体的不同属性上灵活运用相关注解就能达到目的,例如以下的列子: 目标生成文件内容截图
可以看到,表头是姓名,年龄,性别等,而表格里有两条记录。因此,结合官方文档,能够很容易得写出这个生成的代码,根据表头定义Person实体类
Person类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
@ExcelProperty("姓名")
private String name;
@ExcelProperty("住址")
private String address;
@ExcelProperty("性别")
private String gender;
@ExcelProperty("年龄")
private int age;
@ExcelProperty("工作单位")
private String workPlace;
}
上述代码可以看到每一个属性上面都有一个@ExcelProperty
注解,结合表格的内容,可以看到注解的属性就是我们的表头的值
那么,如何结合这个生成一个文件呢,示例代码如下
public static void main(String[] args) {
String fileName = "demoExcel.xlsx";
EasyExcel.write(fileName, Person.class)
.sheet()
.doWrite(getPersonInfo());
}
public static List<Person> getPersonInfo() {
List<Person> personList = Lists.newArrayList();
Person person1 = new Person();
person1.setName("张三");
person1.setAge(23);
person1.setGender("男");
person1.setAddress("中国北京市");
person1.setWorkPlace("保密单位");
personList.add(person1);
Person person2 = new Person();
person2.setName("李四");
person2.setAge(28);
person2.setGender("男");
person2.setAddress("中国上海市");
person2.setWorkPlace("互联网公司");
personList.add(person2);
return personList;
}
生成效果如下:
当然,你会发现这里的表头样式和宽度等等都和最开始的模板不一致,这是因为EasyExcel在生产表头时有默认的规则和宽度,我们可以使用相关组件或内容去修改这些内容,例如,我们可以使用
@ColumnWidth
注解来指定当前表头所在的列的宽度是多少,例如:
@ExcelProperty("工作单位")
@ColumnWidth(15)
private String workPlace;
可以看到,最后一列的宽度得到了改变。什么?你发现列的顺序与模板的不一致,很好办,调整实体类的顺序就可以了。
这个时候有的人可能就会问到我已经有一个Person类了, 但是我里面有一些其他属性,在文件模板中又不想展示这个字段应该怎么办? 这点EasyExcel已经替我们想到了,使用
@ExcelIgnore
注解,该注解的作用就是在文件生成head(表头)的时候忽略该字段,不进行填充,例如在Person类中新增了一个属性salary,你会发现,如果我们不标记任何注解,那么生成出来的内容是下面这个
而我们又不想标识出来薪水,因此可以使用
@ExcelIgnore
注解来实现,例如
@ExcelIgnore
private String salary;
效果如下
好了,到这里,就介绍了简单形式的Excel的文件生成,当然,这里生成的是xlsx格式,我们也可以使用EasyExcel提供的ExcelTypeEnum
来生产多种格式的文件,例如csv。只是文件格式不同,而根本上的生成文件的方式则是相同的
EasyExcel.write(fileName, Person.class).excelType(ExcelTypeEnum.CSV)
.sheet()
.doWrite(getPersonInfo());
2、动态表头生成
上面的内容提到过,如果我已经有一个实体类了,里面有一些字段能满足我目标生产文件的表头要求,但是有一些不需要,同时我也不能使用@ExcelIgnore
注解,因为有其他场景也需要用到这些字段。
举个具体的例子,对于Person类,A场景需要使用到name
,address
,gender
字段,而B场景需要用到name
,age
,wordPlace
字段,因此不能简单的将不需要的字段标记@ExcelIgnore
字段。这个时候可能有人想到的是那我多定义几个实体类,在生成文件时用不同的实体类去映射就行了,这么做固然可行,但是场景少还行,如果场景多,需要使用到的字段又比较零散,那么通过这种方式就要定义很多实体类,维护起来很麻烦,这个时候可以用到动态生成表头,下面是一个简单的示例
public static void main(String[] args) {
String fileAName = System.currentTimeMillis() + "demoAExcel.xlsx" ;
String fileBName = System.currentTimeMillis() + "demoBExcel.xlsx" ;
// 定义场景A所需要的表头
List<List<String>> headsA = Lists.newArrayList();
List<String> columnsA1 = Lists.newArrayList("姓名");
List<String> columnsA2 = Lists.newArrayList("住址");
List<String> columnsA3 = Lists.newArrayList("性别");
headsA.add(columnsA1);
headsA.add(columnsA2);
headsA.add(columnsA3);
// 定义场景B所需要的表头
List<List<String>> headsB = Lists.newArrayList();
List<String> columnsB1 = Lists.newArrayList("姓名");
List<String> columnsB2 = Lists.newArrayList("年龄");
List<String> columnsB3 = Lists.newArrayList("工作单位");
headsB.add(columnsB1);
headsB.add(columnsB2);
headsB.add(columnsB3);
// 构造场景A所需要的数据
List<List<String>> dataA = Lists.newArrayList();
List<String> rowA1 = Lists.newArrayList("张三", "中国北京市", "男");
List<String> rowA2 = Lists.newArrayList("李四", "中国上海市", "男");
dataA.add(rowA1);
dataA.add(rowA2);
// 构造场景B所需要的数据
List<List<String>> dataB = Lists.newArrayList();
List<String> rowB1 = Lists.newArrayList("张三", "23", "保密单位");
List<String> rowB2 = Lists.newArrayList("李四", "28", "互联网公司");
dataB.add(rowB1);
dataB.add(rowB2);
// 生成场景A的文件
EasyExcel.write(fileAName).sheet().head(headsA).doWrite(dataA);
// 生成场景B的文件
EasyExcel.write(fileBName).sheet().head(headsB).doWrite(dataB);
}
下面是两个场景的输出结果
A场景:
B场景:
可以看到根据不同的条件我们生成了不同的文件,避免了因过多创建不同的实体类而带来的维护问题。
当然这只是一个例子,真实使用中,我们需要通过待组装的列去对实体类进行反射,拿到具体的value,在组装成文件。
结尾
上述内容其实也不算复杂,只是由于本人第一次使用EasyExcel去完成某个具体的需求,因此记录下来当时的想法,并且也没有用到EasyExcel中多复杂的功能,希望能给那些第一次使用EasyExcel的朋友一点经验。也希望能看到本文章的大佬给一些指导建议,不胜感激! 后续会再整理一篇文章,用于记录使用EasyExcel来生成多sheet,稍微复杂点的文件。
不积跬步,无以至千里,不积小流,无以成江海。
转载自:https://juejin.cn/post/7356906581780922409