EasyExcel

embedded/2024/11/21 17:34:34/

一  简介

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  最简单的读

调用EasyExcelAPI读取的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 指定需要读表格的 列头行数。默认有一行头,也就是认为第二行开始起为数据。

  • headclazz二选一。读取文件头对应的列表,会根据列表匹配数据。建议使用clas,就是文件中每一行数据对应的代码中的实体类型。

  • clazzhead二选一。读取文件的头对应的class,也可以使用注解。如果两个都不指定,则会读取全部数据。

  • autoTrim 字符串、表头等数据自动trim

  • password 读的时候是否需要使用密码

4  ReadWorkbook(工作簿对象)参数

  • excelType 当前excel的类型,读取时会自动判断,无需设置。

  • inputStreamfile二选一。建议使用file。

  • fileinputStream二选一。读取文件的文件。

  • autoCloseStream 自动关闭流。

  • readCache 默认小于5M用 内存,超过5M会使用 EhCache,不建议使用这个参数。

  • useDefaultListener @since 2.1.4 默认会加入ModelBuildEventListener 来帮忙转换成传入class的对象,设置成false后将不会协助转换对象,自定义的监听器会接收到Map<Integer,CellData>对象,如果还想继续接听到class对象,请调用readListener方法,加入自定义的beforeListenerModelBuildEventListener、 自定义的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();


http://www.ppmy.cn/embedded/139389.html

相关文章

Java基础知识(五)

文章目录 ObjectObject 类的常见方法有哪些&#xff1f; 和 equals() 的区别hashCode() 有什么用&#xff1f;为什么要有 hashCode&#xff1f;为什么重写 equals() 时必须重写 hashCode() 方法&#xff1f; 参考链接 Object Object 类的常见方法有哪些&#xff1f; Object 类…

【uni-app多端】修复stmopjs下plus-websocket无心跳的问题

从这篇文章接着向下看&#xff1a; uniapp plus-websocket 和stompjs连接教程 安卓ios手机端有效 - 简书 按照文章的方式&#xff0c;能够实现APP下stmopjs长连接。但是有一个问题&#xff0c;就是会频繁输出 res-创建连接-1- 跟踪连接&#xff0c;会发现连接都会在大约40s后…

推荐一款流程图和图表绘制工具:WizFlow Flowcharter Pro

WizFlow Flowcharter是一款易于使用、功能丰富的Windows流程图和图表绘制工具。它允许用户使用超过一百种预定义的形状和箭头定义形状“样式”。您可以将自己的样式保存在图表模板中&#xff0c;以建立自己的绘图方法。WizFlow附带了完整的流程图模板&#xff0c;以帮助您入门。…

网络安全等级测评师

安全通信网络 概述&#xff1a;安全通信网络针对网络架构和通信传输提出了安全控制要求&#xff0c;主要对象为广域网、城域网、局域网的通信传输及网络架构等&#xff0c;涉及的安全控制点包括网络架构、通信传输、可信验证。 1.网络架构 1&#xff09;应保证网络设备的业务处…

【Linux驱动开发】irq中断配置API及中断应用 阻塞休眠和非阻塞的驱动操作

【Linux驱动开发】irq中断配置API及中断应用 阻塞休眠和非阻塞的驱动操作 文章目录 中断操作注册和释放中断中断服务函数使能和禁止上半部和下半部软中断tasklet工作队列 设备节点中的中断中断号API函数获取中断号获取中断信息 中断应用读取设备树节点获取中断号获取中断触发方…

Linux下多线程

在Linux下的底层里并没有多线程这个概念&#xff0c;取而代之的是轻量级进程的概念。应为在Llinu下内核下并没有TCB,而只有PCB。 线程是什么 在⼀个程序⾥的⼀个执⾏路线就叫做线程&#xff08;thread&#xff09;。更准确的定义是&#xff1a;线程是“⼀个进程内部 的控制序…

【Git从入门到精通】——Git分支介绍与GitHub相关知识总结

&#x1f3bc;个人主页&#xff1a;【Y小夜】 &#x1f60e;作者简介&#xff1a;一位双非学校的大二学生&#xff0c;编程爱好者&#xff0c; 专注于基础和实战分享&#xff0c;欢迎私信咨询&#xff01; &#x1f386;入门专栏&#xff1a;&#x1f387;【MySQL&#xff0…

C++中的组合模式

组合模式&#xff08;Composite Pattern&#xff09; 组合模式是一种结构型设计模式&#xff0c;它将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得客户端可以统一地处理单个对象和对象组合。这个模式特别适用于需要表示层次结构的场景&#xff0c;例如文件…