一 简介
1.EasyExcel是什么
EasyExcel是一个基于Java的简单、省内存的读写Excel的阿里开源项目在尽可能节约内存的情况下支持读写百M的Excel。
2.EasyExcel 能用在哪里
项目中涉及到Excel文件,CVS文件大多数的读写操作,均可以使用!
3 官网
EasyExcel官方文档 - 基于Java的Excel处理工具 | Easy Excel 官网
二 快速入门
1 前置案例准备
我们有一个表格
与之配套的实体类,这里只是一个简单的对应关系
java">package domain;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.Date;@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {/*** 学生姓名*/private String name;/*** 学生出生日期*/private Date birthday;/*** 学生性别*/private String gender;/*** id*/private String id;}
2 引入依赖
引入easyexcel的依赖
java"> <!-- EasyExcel --><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.1.6</version></dependency>
3 最简单的读
调用EasyExcel
的API
读取的Excel
文件的测试类StudentReadDemo
java">import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.builder.ExcelReaderBuilder;
import com.alibaba.excel.read.builder.ExcelReaderSheetBuilder;
import domain.Student;
import listener.StudentReadListener;public class StudentReadDemo {public static void main(String[] args) {// 读取文件,读取完之后会自动关闭/*pathName 文件路径;"d:\\杭州黑马在线202003班学员信息.xls"head 每行数据对应的实体;Student.classreadListener 读监听器,每读一样就会调用一次该监听器的invoke方法sheet方法参数: 工作表的顺序号(从0开始)或者工作表的名字,不传默认为0*///创建一个工作簿对象ExcelReaderBuilder read = EasyExcel.read("E:\\java\\itheima\\EasyExcel" +"公开课资料\\杭州黑马在线202003班学员信息表.xlsx", Student.class, new StudentReadListener());//创建一个工作表对象ExcelReaderSheetBuilder sheet = read.sheet();//读取信息sheet.doRead();}
}
读取Excel的监听器,用于处理读取产生的数据
java">package listener;import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import domain.Student;public class StudentReadListener extends AnalysisEventListener<Student> {/*每次读取到一行数据都会调用一次invoke方法,在这个方法内可以操作读取到的数据*/@Overridepublic void invoke(Student student, AnalysisContext analysisContext) {System.out.println(student);}@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {}
}
测试
4 最简单的写
编写导出数据的实体,修改原来的student实体类
@ColumnWidth(20):每一个字段宽度都设置成20个字符
@HeadRowHeight(15):表头的行高是15个字符
@ContentRowHeight(10):内容的行高是10个字符
@ExcelIgnore:生成的表中不会显示id
@ExcelProperty(value = "学生姓名", index = 0):规定表中第一行的数据的名字和位置
java">@Data
@AllArgsConstructor
@NoArgsConstructor
@ColumnWidth(20)
@HeadRowHeight(15)
@ContentRowHeight(10)
public class Student {/*** id*///@ExcelProperty(value = "编号",index = 3)@ExcelIgnoreprivate String id;/*** 学生姓名*/@ExcelProperty(value = "学生姓名", index = 0)//@ColumnWidth(30)private String name;/*** 学生性别*/@ExcelProperty(value = "学生性别", index = 2)private String gender;/*** 学生出生日期*/@ExcelProperty(value = "学生出生日期", index = 1)//@ColumnWidth(20)private Date birthday;
}
简单的写操作:
定义了一个生成学生实体类的方法,获取学生实体类然后调用写方法。
java">@Testpublic void write(){List<Student> students = initData();/*String pathName 写入文件的路径Class head 写入文件的对象类型默认写入到07的xlsx中,如果想要写入xls,可以指定类型(待验证)*/ExcelWriterBuilder workBook = EasyExcel.write("杭州黑马学员表写入.xlsx", Student.class);// sheet方法参数: 工作表的顺序号(从0开始)或者工作表的名字workBook.sheet().doWrite(students);}private List<Student> initData() {ArrayList<Student> students = new ArrayList<>();for (int i = 0; i < 10; i++) {Student data = new Student();data.setName("杭州黑马学号0" + i);data.setBirthday(new Date());data.setGender("男");students.add(data);}return students;}
最后生成的表:
三 常用的api
1、常用类
-
EasyExcel 入口类,用于构建开始各种操作;
-
ExcelReaderBuilder 构建出一个ReadWorkbook对象,即一个工作簿对象,对应的是一个Excel文件;
-
ExcelWriterBuilder 构建出一个WriteWorkbook对象,即一个工作簿对象,对应的是一个Excel文件;
-
ExcelReaderSheetBuilder 构建出一个ReadSheet对象,即一个工作表的对象,对应的Excel中的每个sheet,一个工作簿可以有多个工作表;
-
ExcelWriterSheetBuilder 构建出一WriteSheet对象,即一个工作表的对象,对应的Excel中的每个sheet,一个工作簿可以有多个工作表;
-
ReadListener 在每一行读取完毕后都会调用ReadListener来处理数据,我们可以把调用service的代码可以写在其invoke方法内部;
-
WriteHandler 在每一个操作包括创建单元格、创建表格等都会调用WriteHandler来处理数据,对使用者透明不可见;
-
所有配置都是继承的 Workbook的配置会被Sheet继承。所以在用EasyExcel设置参数的时候,在EasyExcel…sheet()方法之前作用域是整个sheet,之后针对单个sheet。
2、读取时的注解
@ExcelProperty
使用位置:标准作用在成员变量上
可选属性:
属性名 | 含义 | 说明 |
---|---|---|
index | 对应Excel表中的列数 | 默认-1,建议指定时从0开始 |
value | 对应Excel表中的列头 | |
converter | 成员变量转换器 | 自定义转换器需要实Converter接口 |
使用效果:index属性可以指定当前字段对应excel中的哪一列,可以根据列名value去匹配,也可以不写。
如果不使用@ExcelProperty注解,成员变量从上到下的顺序,对应表格中从左到右的顺序;
使用建议:要么全部不写,要么全部用index,要么全部用名字去匹配,尽量不要三个混着用。
@ExcelIgnore
标注在成员变量上,默认所有字段都会和excel去匹配,加了这个注解会忽略该字段
@DateTimeFormat
标注在成员变量上,日期转换,代码中用String类型的成员变量
去接收excel中日期格式的数据
会调用这个注解。里面的value
参照java.text.SimpleDateFormat
@NumberFormat
标注在成员变量上,数字转换,代码中用String类型的成员变量
去接收excel数字格式的数据
会调用这个注解。里面的value
参照java.text.DecimalFormat
示例代码:
将学生类里面的birthday由原来的Date转变为String,加上注解
java">@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {/*** 学生姓名*/private String name;/*** 学生出生日期*/@DateTimeFormat
// private Date birthday;private String birthday;/*** 学生性别*/private String gender;/*** id*/private String id;}
读取数据代码:
java">@Testpublic void read(){// 读取文件,读取完之后会自动关闭/*pathName 文件路径;"d:\\杭州黑马在线202003班学员信息.xls"head 每行数据对应的实体;Student.classreadListener 读监听器,每读一样就会调用一次该监听器的invoke方法sheet方法参数: 工作表的顺序号(从0开始)或者工作表的名字,不传默认为0*///1 创建一个工作簿对象ExcelReaderBuilder read = EasyExcel.read("E:\\java\\itheima\\EasyExcel" +"公开课资料\\杭州黑马在线202003班学员信息表.xlsx", Student.class, new StudentReadListener());//2 创建一个工作表对象ExcelReaderSheetBuilder sheet = read.sheet();//3 读取信息sheet.doRead();}
成功读取:
@ExcelIgnoreUnannotated
标注在类上。
不标注该注解时,默认类中所有成员变量都会参与读写,无论是否在成员变量上加了@ExcelProperty
的注解。
标注该注解后,类中的成员变量如果没有标注@ExcelProperty
注解将不会参与读写。
示例代码:
student类加上@ExcelIgnoreUnannotated注解,有gender,name加上了 @ExcelProperty注解
java">@Data
@ColumnWidth(20)
@HeadRowHeight(30)
@ContentRowHeight(20)
@ExcelIgnoreUnannotated
public class Student {/*** id*/
// @ExcelProperty(value = "编号",index = 3)@ExcelIgnoreprivate String id;/*** 学生姓名*/@ExcelProperty(value = "学生姓名", index = 0)//@ColumnWidth(30)private String name;/*** 学生性别*/@ExcelProperty(value = "学生性别", index = 2)private String gender;/*** 学生出生日期*/
// @ExcelProperty(value = "学生出生日期", index = 1)//@ColumnWidth(20)private Date birthday;
}
写入数据代码:
java">@Testpublic void write(){List<Student> students = initData();/*String pathName 写入文件的路径Class head 写入文件的对象类型默认写入到07的xlsx中,如果想要写入xls,可以指定类型(待验证)*/ExcelWriterBuilder workBook = EasyExcel.write("杭州黑马学员表写入.xlsx", Student.class);// sheet方法参数: 工作表的顺序号(从0开始)或者工作表的名字workBook.sheet().doWrite(students);}private List<Student> initData() {ArrayList<Student> students = new ArrayList<>();for (int i = 0; i < 10; i++) {Student data = new Student();data.setName("杭州黑马学号0" + i);data.setBirthday(new Date());data.setGender("男");students.add(data);}return students;}
结果,与预期一致。
3 读取时通用参数
ReadWorkbook
,ReadSheet
都会有的参数,如果为空,默认使用上级。
-
converter
转换器,默认加载了很多转换器。也可以自定义。 -
readListener
监听器,在读取数据的过程中会不断的调用监听器。 -
headRowNumber
指定需要读表格的 列头行数。默认有一行头,也就是认为第二行开始起为数据。 -
head
与clazz
二选一。读取文件头对应的列表,会根据列表匹配数据。建议使用clas,就是文件中每一行数据对应的代码中的实体类型。 -
clazz
与head
二选一。读取文件的头对应的class,也可以使用注解。如果两个都不指定,则会读取全部数据。 -
autoTrim
字符串、表头等数据自动trim -
password
读的时候是否需要使用密码
4 ReadWorkbook(工作簿对象)参数
-
excelType
当前excel的类型,读取时会自动判断,无需设置。 -
inputStream
与file
二选一。建议使用file。 -
file
与inputStream
二选一。读取文件的文件。 -
autoCloseStream
自动关闭流。 -
readCache
默认小于5M用 内存,超过5M会使用EhCache
,不建议使用这个参数。 -
useDefaultListener
@since 2.1.4
默认会加入ModelBuildEventListener
来帮忙转换成传入class
的对象,设置成false
后将不会协助转换对象,自定义的监听器会接收到Map<Integer,CellData>
对象,如果还想继续接听到class
对象,请调用readListener
方法,加入自定义的beforeListener
、ModelBuildEventListener
、 自定义的afterListener
即可。
5 ReadSheet(工作表对象)参数
-
sheetNo
需要读取Sheet的编号,建议使用这个来指定读取哪个Sheet。如果不指定参数默认读取第一张表 -
sheetName
根据名字去匹配Sheet,excel 2003不支持根据名字去匹配
6、写入时的注解注解
@ExcelProperty
使用位置:标准作用在成员变量上
可选属性:
属性名 | 含义 | 说明 |
---|---|---|
index | 对应Excel表中的列数 | 默认-1,指定时建议从0开始 |
value | 对应Excel表中的列头 | |
converter | 成员变量转换器 | 自定义转换器需要实Converter接口 |
使用效果:index
指定写到第几列,如果不指定则根据成员变量位置排序;
value
指定写入的列头,如果不指定则使用成员变量的名字作为列头;
如果要设置复杂的头,可以为value指定多个值。
示例代码1:
给名字设置了两个表头
java">@Data
@ColumnWidth(20)
@HeadRowHeight(30)
@ContentRowHeight(20)
//@ExcelIgnoreUnannotated
public class Student {/*** id*/
// @ExcelProperty(value = "编号",index = 3)@ExcelIgnoreprivate String id;/*** 学生姓名*/@ExcelProperty(value = {"student_name", "学生姓名"}, index = 0)//@ColumnWidth(30)private String name;/*** 学生性别*/@ExcelProperty(value = "学生性别", index = 2)private String gender;/*** 学生出生日期*/@ExcelProperty(value = "学生出生日期", index = 1)//@ColumnWidth(20)private Date birthday;
}
写入代码:
java"> @Testpublic void write(){List<Student> students = initData();/*String pathName 写入文件的路径Class head 写入文件的对象类型默认写入到07的xlsx中,如果想要写入xls,可以指定类型(待验证)*/ExcelWriterBuilder workBook = EasyExcel.write("杭州黑马学员表写入.xlsx", Student.class);// sheet方法参数: 工作表的顺序号(从0开始)或者工作表的名字workBook.sheet().doWrite(students);}private List<Student> initData() {ArrayList<Student> students = new ArrayList<>();for (int i = 0; i < 10; i++) {Student data = new Student();data.setName("杭州黑马学号0" + i);data.setBirthday(new Date());data.setGender("男");students.add(data);}return students;}
结果:
示例代码2:
给所有字段都加上表头“学生表”,写入代码与上面一致
java">@Data
@ColumnWidth(20)
@HeadRowHeight(30)
@ContentRowHeight(20)
//@ExcelIgnoreUnannotated
public class Student {/*** id*/
// @ExcelProperty(value = "编号",index = 3)@ExcelIgnoreprivate String id;/*** 学生姓名*/@ExcelProperty(value = {"学生表", "学生姓名"}, index = 0)//@ColumnWidth(30)private String name;/*** 学生性别*/@ExcelProperty(value = {"学生表", "学生性别"}, index = 2)private String gender;/*** 学生出生日期*/@ExcelProperty(value = {"学生表", "学生出生日期"}, index = 1)//@ColumnWidth(20)private Date birthday;
}
效果:
本来应该是有三个格子充当表头,现在合并成一个
其他注解:
基本和读取时一致
-
@ContentRowHeight() 标注在类上或属性上,指定内容行高
-
@HeadRowHeight() 标注在类上或属性上,指定列头行高
-
@ColumnWidth() 标注在类上或属性上,指定列宽
-
@ExcelIgnore` 默认所有字段都会写入excel,这个注解会忽略这个字段
-
@
DateTimeFormat
日期转换,将Date
写到excel会调用这个注解。里面的value
参照java.text.SimpleDateFormat
-
@
NumberFormat
数字转换,用Number
写excel会调用这个注解。里面的value
参照java.text.DecimalFormat
-
@
ExcelIgnoreUnannotated
默认不加ExcelProperty
的注解的都会参与读写,加了不会参与
四 文件上传和下载
1 模板准备
1.1 引入依赖
java"><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- EasyExcel --><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.1.6</version></dependency><!-- lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.10</version><scope>provided</scope></dependency><!-- junit --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-nop</artifactId><version>1.7.2</version></dependency><!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-log4j2 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId><version>3.2.4</version></dependency><!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.7.11</version></dependency><!-- 文件上传 --><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.4</version></dependency></dependencies>
1.2 准备要上传的表格
1.3 编写对应的实体类
java">@Data
@NoArgsConstructor
@AllArgsConstructor
//@ExcelIgnoreUnannotated
public class Student {/*** 学生姓名*/
// @ExcelProperty(value = "名字", index = 0)private String name;/*** 学生出生日期*/
// @DateTimeFormatprivate Date birthday;
// private String birthday;/*** 学生性别*/private String gender;/*** id*/private String id;}
2 文件上传(就是从外界传入文件进后端)
2.1 编写Conteoller
这时候传入file输入流给easyexcel读取文件里面的数据
java">@Slf4j
@RestController
@RequestMapping("/file")
public class StudentController {@Resourceprivate StudentReadListener studentReadListener;@PostMapping("/read")public void testRead(MultipartFile file){try {ExcelReaderBuilder read = EasyExcel.read(file.getInputStream(), Student.class, studentReadListener);ExcelReaderSheetBuilder sheet = read.sheet();sheet.doRead();log.info("成功");} catch (Exception e) {log.error(String.valueOf(e));}}
}
2.2 service
输出学生信息
java">@Service
@Slf4j
public class StudentServiceImpl implements StudentService {@Overridepublic void save(ArrayList<Student> students) {for(Student s : students){log.info(String.valueOf(s));}}
}
2.3 自定义监听器
每读到五条记录就输出
java">@Component
@Scope("prototype") // 作者要求每次读取都要使用新的Listener
public class StudentReadListener extends AnalysisEventListener<Student> {@Resourceprivate StudentService studentService;private final int BATCH_SAVE_NUM = 5;ArrayList<Student> students = new ArrayList<>();private int count = 0;// 每读一次,会调用该invoke方法一次@Overridepublic void invoke(Student data, AnalysisContext context) {students.add(data);if (++count % BATCH_SAVE_NUM == 0) {studentService.save(students);students.clear();}}// 全部读完之后,会调用该方法@Overridepublic void doAfterAllAnalysed(AnalysisContext context) {// TODO......}
2.4 测试
使用apifox
上传文件请求,首先设置请求头内的参数和参数值
然后设置上传参数的类型名字,类型以及文件本身
测试结果:
3 文件下载(就是从后端读取数据生成excel)
简单的演示,直接将业务逻辑都写在了controller上。这里注入了一个http响应,给easyExcel的write方法
java">@GetMapping("/write")public void testWrite(HttpServletResponse response) throws IOException {// 设置响应的内容类型为Excel文件格式response.setContentType("application/vnd.ms-excel");// 设置响应的字符编码为UTF-8,确保中文字符不会乱码response.setCharacterEncoding("utf-8");// 为了防止中文文件名在下载时出现乱码,使用URLEncoder对文件名进行编码// "UTF-8"指定了编码格式,确保文件名在不同语言环境下都能正确显示String fileName = URLEncoder.encode("测试", "UTF-8");// 设置响应头,告诉浏览器这是一个附件,并指定下载后的文件名// "attachment"告诉浏览器这是一个需要下载的文件// "filename*"指定了文件名的编码方式,"UTF-8''"表示使用UTF-8编码,并在文件名两边加上空格以避免浏览器解析错误// 将编码后的文件名和.xlsx后缀拼接,形成完整的文件名response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + fileName + ".xlsx");/*String pathName 写入文件的路径Class head 写入文件的对象类型默认写入到07的xlsx中,如果想要写入xls,可以指定类型(待验证)*/ExcelWriterBuilder workBook = EasyExcel.write(response.getOutputStream(), Student.class);List<Student> students = initData();// sheet方法参数: 工作表的顺序号(从0开始)或者工作表的名字workBook.sheet().doWrite(students);}private List<Student> initData() {ArrayList<Student> students = new ArrayList<>();for (int i = 0; i < 10; i++) {Student data = new Student();data.setName("杭州黑马学号0" + i);data.setBirthday(new Date());data.setGender("男");students.add(data);}return students;}
演示:
当我访问相应的路径的时候,网页自动下载excel文件
localhost:8080/file/write
五 数据填充
由于我们用代码设置填充数据是很复杂的,所以我们一般会准备一些模板,来代码按照模板的格式来进行填充。
1 填充一组数据
1.1 准备模板
Excel表格中用{} 来表示包裹要填充的变量,如果单元格文本中本来就有{
、}
左右大括号,需要在括号前面使用斜杠转义\{
、\}
。
代码中被填充数据的实体对象的成员变量名或被填充map集合的key需要和Excel中被{}包裹的变量名称一致。
1.2 封装数据
编写封装填充数据的类或选用Map
java">/*** 使用实体类封装填充数据** 实体中成员变量名称需要和Excel表各种{}包裹的变量名匹配*/
@Data
public class FillData {private String name;private int age;
}
1.3 填充
这里只能使用自动关闭输出流的方法,因为手动关闭那个需要传入的数据是已list的方式
java">@Testvoid testOne(){// 加载模板String template = "fill_data_template1.xlsx";// 准备工作簿ExcelWriterBuilder excelWriterBuilder= EasyExcel.write("填充-单个数据.xlsx", FillData.class).withTemplate(template);// 准备单个工作表ExcelWriterSheetBuilder sheet = excelWriterBuilder.sheet();// 准备数据填充//方法一:使用实体类
// FillData fillData = new FillData();
// fillData.setAge(100);
// fillData.setName("吴彦煮");//方法2:使用mapHashMap<String, String> fillData = new HashMap<>();fillData.put("name", "陈冠希");fillData.put("age", "50");// 填充数据sheet.doFill(fillData);}
1.4 测试
测试成功
2 填充多组数据
2.1 准备模板
注意,由于我们要填充多组数据,我们要在name,age前面加上一点 '.',代表多组数据
2.2 填充
方式1 自动关闭输出流
java">@Testvoid testMoreThanOne(){// 加载模板String template = "fill_data_template2.xlsx";// 准备工作簿ExcelWriterBuilder excelWriterBuilder= EasyExcel.write("填充-多个数据.xlsx", FillData.class).withTemplate(template);// 准备单个工作表ExcelWriterSheetBuilder sheet = excelWriterBuilder.sheet();List<FillData> fillData = initFillData();// 填充数据sheet.doFill(fillData);}private static List<FillData> initFillData() {ArrayList<FillData> fillDatas = new ArrayList<FillData>();for (int i = 0; i < 10; i++) {FillData fillData = new FillData();fillData.setName("杭州黑马0" + i);fillData.setAge(10 + i);fillDatas.add(fillData);}return fillDatas;}
方式2 手动关闭输出流
java">@Testvoid testMoreThanOne(){// 加载模板String template = "fill_data_template2.xlsx";// 准备工作簿ExcelWriter workBook = EasyExcel.write("填充-多个数据.xlsx", FillData.class).withTemplate(template).build();// 准备单个工作表WriteSheet writeSheet = EasyExcel.writerSheet().build();List<FillData> fillData = initFillData();// 填充数据workBook.fill(fillData, writeSheet);// 关闭流workBook.finish();}private static List<FillData> initFillData() {ArrayList<FillData> fillDatas = new ArrayList<FillData>();for (int i = 0; i < 10; i++) {FillData fillData = new FillData();fillData.setName("杭州黑马0" + i);fillData.setAge(10 + i);fillDatas.add(fillData);}return fillDatas;}
2.3 测试
成功
3 填充一组和多组数据(组合数据)
3.1 准备模板
3.2 填充
注意!
这里创建工作簿和工作表对象发生了变化。因为我们需要分布去填充数据。上面两个例子使用的方法 dofill ,只要前缀是do开头,都是默认自动关闭流的。我们写入,也就是填充操作是依靠输出流的。当完成一个填充操作后输出流自动关闭,就进行不了下一步的填充。所以我们不能使用上面两个用的dofill方法。我们需要自己手动去关闭输出流。
另外,组合填充时,因为多组填充的数据量不确定,需要在多组填充完之后另开一行。如果不手动开一行,那么单行和多行就会混在一起。
java">@Testvoid testMoreAndOne(){// 加载模板String template = "fill_data_template3.xlsx";// 准备工作簿ExcelWriter workBook = EasyExcel.write("填充-组合数据.xlsx", FillData.class).withTemplate(template).build();// 准备单个工作表WriteSheet writeSheet = EasyExcel.writerSheet().build();// 准备数据填充List<FillData> fillDatas = initFillData();HashMap<String, String> fillDate = new HashMap<>();fillDate.put("date", String.valueOf(new Date()));fillDate.put("total", "10");// 组合填充时,因为多组填充的数据量不确定,需要在多组填充完之后另起一行FillConfig fillConfig = FillConfig.builder().forceNewRow(true).build();// 填充数据workBook.fill(fillDatas, fillConfig, writeSheet);workBook.fill(fillDate, writeSheet);// 手动关闭流workBook.finish();}private static List<FillData> initFillData() {ArrayList<FillData> fillDatas = new ArrayList<FillData>();for (int i = 0; i < 10; i++) {FillData fillData = new FillData();fillData.setName("杭州黑马0" + i);fillData.setAge(10 + i);fillDatas.add(fillData);}return fillDatas;}
3.3 测试
4 水平填充
4.1 准备模板
水平,顾名思义是横着来填写数据的。也是封装多组数据
4.2 填充
这里通过调整方向来填充。自己手动关闭流,因为要传入fillConfig对象
java">@Testvoid HORIZONTAL(){// 加载模板String template = "fill_data_template4.xlsx";// 准备工作簿ExcelWriter workBook = EasyExcel.write("填充-水平数据.xlsx", FillData.class).withTemplate(template).build();// 准备单个工作表WriteSheet writeSheet = EasyExcel.writerSheet().build();// 准备数据填充List<FillData> fillDatas = initFillData();// 这里设置一下填充方向,水平填充,通过WriteDirectionEnum来设置FillConfig fillConfig = FillConfig.builder().direction(WriteDirectionEnum.HORIZONTAL).build();// 填充数据workBook.fill(fillDatas, fillConfig, writeSheet);// 手动关闭流workBook.finish();}private static List<FillData> initFillData() {ArrayList<FillData> fillDatas = new ArrayList<FillData>();for (int i = 0; i < 10; i++) {FillData fillData = new FillData();fillData.setName("杭州黑马0" + i);fillData.setAge(10 + i);fillDatas.add(fillData);}return fillDatas;}
可以设置水平和垂直填充
4.3 测试
5 总结
我们填充数据有两种代码实现方式,精确的来说就是我们有两种不一样的创建工作簿和工作表的方法
方式1
这一种在填充数据的时候是调用工作表对象的填充方法,自动关闭输出流
java">// 准备工作簿ExcelWriterBuilder excelWriterBuilder= EasyExcel.write("填充-单个数据.xlsx", FillData.class).withTemplate(template);// 准备单个工作表ExcelWriterSheetBuilder sheet = excelWriterBuilder.sheet();
方式2
这一种是在填充数据的时候调用工作簿对象的方法,需要手动关闭输出流。
java">// 准备工作簿ExcelWriter workBook = EasyExcel.write("填充-水平数据.xlsx", FillData.class).withTemplate(template).build();// 准备单个工作表WriteSheet writeSheet = EasyExcel.writerSheet().build();