使用Easy Excel对excel的读写
目录
Easy Excel
EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。
他能让你在不用考虑性能、内存的等因素的情况下,快速完成Excel的读、写等功能。
所需依赖
<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>
<!--lombok依赖可以不加,只是之后要手动的写get,set方法-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
<!--easyexcel-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.6</version>
</dependency>
<!--slf4j 日志-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.30</version>
</dependency>
</dependencies>
准备一个excel文件
内容如下:
id | 姓名 | 年龄 |
1 | 小明 | 12 |
2 | 小红 | 13 |
3 | 小刚 | 13 |
4 | 小美 | 11 |
5 | 小智 | 10 |
对excel的读取
创建对应的实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String id;
private String name;
private Integer age;
}
如果没有导入lombok依赖需要手动加入get,set方法和构造方法
创建EasyExcelUtil类
package com.li.utils;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.SyncReadListener;
import com.li.pojo.DemoData;
import com.li.pojo.User;
import java.util.ArrayList;
import java.util.List;
public class EasyExcelUtil {
public static void main(String[] args) {
EasyExcelUtil.read1();
}
private static void read1() {
final List list = new ArrayList();
//使用EasyExcel读取test1.xlsx文件
EasyExcel.read("C:\\Users\\lenovo\\Desktop\\user.xlsx", User.class, new SyncReadListener() {
//EasyExcel在读取excel表格时,每读取到一行,就会调用一次这个方法,
//并且将读取到的行数据,封装到指定类型(User)的对象中,传递给我们(Object object)
/*
此问题可能出现在低版本的easyExcel中,出现时可以按照下列方式解决
如果表格数据不是顶行写的,需要通过headRowNumber指定表头行的数量
如果表格数据不是顶列写的,需要在封装的实体属性上通过@ExcelProperty将实体属性和表格列名进行对应
*/
@Override
public void invoke(Object object, AnalysisContext context) {
System.out.println(object);
list.add(object);
}
}).doReadAll();
//获取读取到的数据
for (Object object : list) {
User user = (User) object;
System.out.println(user);
}
}
}
运行main后效果如下:
添加一个方法后再次运行
package com.li.utils;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.event.SyncReadListener;
import com.li.pojo.DemoData;
import com.li.pojo.User;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class EasyExcelUtil {
public static void main(String[] args) {
EasyExcelUtil.read2();
}
private static void read1() {
final List list = new ArrayList();
//使用EasyExcel读取test1.xlsx文件
EasyExcel.read("C:\\Users\\lenovo\\Desktop\\user.xlsx", User.class, new SyncReadListener() {
//EasyExcel在读取excel表格时,每读取到一行,就会调用一次这个方法,
//并且将读取到的行数据,封装到指定类型(User)的对象中,传递给我们(Object object)
/*
此问题可能出现在低版本的easyExcel中,出现时可以按照下列方式解决
如果表格数据不是顶行写的,需要通过headRowNumber指定表头行的数量
如果表格数据不是顶列写的,需要在封装的实体属性上通过@ExcelProperty将实体属性和表格列名进行对应
*/
@Override
public void invoke(Object object, AnalysisContext context) {
System.out.println(object);
list.add(object);
}
}).doReadAll();
//获取读取到的数据
for (Object object : list) {
User user = (User) object;
System.out.println(user);
}
}
private static void read2() {
final List list = new ArrayList();
//使用EasyExcel读取test1.xlsx文件
EasyExcel.read("C:\\Users\\lenovo\\Desktop\\user.xlsx", User.class, new AnalysisEventListener<User>() {
//重写子类方法
@Override
public void invoke(User user, AnalysisContext analysisContext) {
list.add(user);
}
//重写子类方法
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
@Override
public void invokeHeadMap(Map headMap, AnalysisContext context) {
System.out.println(headMap);
}
}
).doReadAll();
//获取读取到的数据
for (Object o : list) {
User user = (User) o;
System.out.println(user);
}
}
}
运行效果如下:
这次的方法可以获取到表头
修改实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
@ExcelProperty(index = 0)
private String id;
@ExcelProperty("姓名")
private String name;
@ExcelProperty(index = 3)
private Integer age;
}
@ExcelProperty注解中的index表示excel表中的列,默认是0,下标从0开始。默认的name,也就是名字,表示该列的表头。
不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去匹配。
用名字去匹配,需要注意,如果名字重复,会导致只有一个字段读取到数据。
如果有一个index的列向后移动了一列,那么之后的属性默认会获取向后移动一列的数据
修改好后运行结果如下
这里可以看到age没有获取到值,因为我们将他的index设置的3,是没有值的列。
将其修改为2后就会恢复正常
对excel的写入
在EasyExcelUtil类中加入写方法
private static void write1() {
List list = new ArrayList();
list.add(new User("1", "大明", 1));
list.add(new User("2", "大红", 1));
list.add(new User("3", "大刚", 1));
//1.
EasyExcel
.write("C:\\Users\\lenovo\\Desktop\\user.xlsx", User.class)
.sheet(1)//可以在其中写入数字,将其设置为sheet页的名称,不写默认是0
.doWrite(list);
}
public static void write2(){
List list = new ArrayList();
list.add(new User("1", "大明", 1));
list.add(new User("2", "大红", 1));
list.add(new User("3", "大刚", 1));
//2.
ExcelWriter excelWriter = null;
try {
excelWriter = EasyExcel.write("C:\\Users\\lenovo\\Desktop\\user.xlsx", User.class).build();
WriteSheet writeSheet = EasyExcel.writerSheet("sheet名称").build();
excelWriter.write(list, writeSheet);
} finally {
// 千万别忘记finish 会帮忙关闭流
if (excelWriter != null) {
excelWriter.finish();
}
}
}
然后在main方法中运行后查看excel表
运行write2()效果
在对表进行写的时候,表头默认是属性名,也可以使用注解进行更改。
对excel的填充
在EasyExcelUtil类中加入填充方法
private static void write_template_multi() {
List list = new ArrayList();
/*list.add(new User("1", "大明", 1));
list.add(new User("2", "大红", 1));
list.add(new User("3", "大刚", 1));*/
EasyExcel
.write("C:\\Users\\lenovo\\Desktop\\user.xlsx", User.class)
.withTemplate("C:\\Users\\lenovo\\Desktop\\user_template.xlsx")
.sheet()
.doFill(list);
}
该方法会将user_template.xlsx中的内容复制到user.xlsx中
创建一个user_template.xlsx文件,内容如下:
id | 姓名 | age |
1 | name | 18 |
然后在main中运行方法结果如下
user.xlsx的内容和user_template.xlsx一样了。
可以通过修改实体类的注解来改变表格中的样式
@Data
@AllArgsConstructor
@NoArgsConstructor
@HeadRowHeight(30) //表头行高
@ContentRowHeight(20) //数据行高
@ColumnWidth(25) //列宽
public class User {
@ExcelProperty("id")
private String id;
@ExcelProperty({"个人信息","姓名"})
private String name;
@ExcelProperty({"个人信息","年龄"})
private Integer age;
}
重新创建表格后的结果如下
整合为工具类
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.event.SyncReadListener;
import com.alibaba.excel.write.metadata.WriteSheet;
import java.io.File;
import java.util.*;
public class EasyExcelUtil {
/**
* 读取excel表格
* @param file 目标文件
* @param head 文件读出后所对应的类
* @return 返回读出数据的集合
*/
private static List readExcel(File file,Class head) {
final List list = new ArrayList();
//使用EasyExcel读取.xlsx文件
EasyExcel.read(file, head, new SyncReadListener() {
@Override
public void invoke(Object object, AnalysisContext context) {
list.add(object);
}
}).doReadAll();
return list;
}
/**
* 读取excel表格
* @param file 目标文件
* @param head 文件读出后所对应的类
* @return 返回一个Map,其中有数据的集合list,还有一个表格中的标题map
*/
private static Map<String, Object> readExcelTitle(File file, Class head){
//使用EasyExcel读取.xlsx文件
List list=new ArrayList();
Map<String,Object> map=new HashMap<>();
EasyExcel.read(file,head, new AnalysisEventListener<Object>() {
//重写子类方法
@Override
public void invoke(Object object, AnalysisContext analysisContext) {
list.add(object);
}
//重写子类方法
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
@Override
public void invokeHeadMap(Map headMap, AnalysisContext context) {
//headMap,中存放着表格标题
map.put("title",headMap);//将标题存放到定义的map中
System.out.println(headMap);
}
}
).doReadAll();
map.put("data",list);//将数据存放到定义的map中
return map;
}
/**
* 将数据写入到表格中,如果不存在则会创建一个表格
* @param file 目标文件
* @param list 要写入的数据
* @param head 数据对应的实体类
*/
private static void writeExcel(File file, List list, Class head) {
EasyExcel
.write(file, head)
.sheet()
.doWrite(list);
}
/**
* 将数据写入到表格中,如果不存在则会创建一个表格
* @param file 目标文件
* @param list 要写入的数据
* @param head 数据对应的实体类
* @param sheetName sheet页的名字
*/
private static void writeExcel(File file, List list, Class head,String sheetName) {
ExcelWriter excelWriter = null;
try {
excelWriter = EasyExcel.write(file, head).build();
WriteSheet writeSheet = EasyExcel.writerSheet(sheetName).build();
excelWriter.write(list, writeSheet);
} finally {
// 千万别忘记finish 会帮忙关闭流
if (excelWriter != null) {
excelWriter.finish();
}
}
}
/**
* 将模板数据写入到表格中
* @param file 对应的表格文件
* @param fileTemplate 模板文件
* @param head 对应的实体类
*/
private static void write_template_multi(File file,File fileTemplate,Class head) {
List list = new ArrayList();
EasyExcel
.write(file, head)
.withTemplate(fileTemplate)
.sheet()
.doFill(list);
}
}
以上就是使用Easy Excel对excel的快速读写