SpringBoot实现Excel自由导入导出,性能强的离谱,用起来还特优雅

一、简介

在实际的业务系统开发过程中,操作 Excel 实现数据的导入导出基本上是个非常常见的需求。

之前,我们有介绍一款非常好用的工具:EasyPoi,有读者提出在数据量大的情况下,EasyPoi 会占用内存大,性能不够好,严重的时候,还会出现内存异常的现象。

今天我给大家推荐一款性能更好的 Excel 导入导出工具:EasyExcel,希望对大家有所帮助!

easyexcel 是阿里开源的一款 Excel导入导出工具,具有处理速度快、占用内存小、使用方便的特点,底层逻辑也是基于 apache poi 进行二次开发的,目前的应用也是非常广!

相比 EasyPoi,EasyExcel 的处理数据性能非常高,读取 75M (46W行25列) 的Excel,仅需使用 64M 内存,耗时 20s,极速模式还可以更快!

废话也不多说了,下面直奔主题!

二、实践

在 SpringBoot 项目中集成 EasyExcel 其实非常简单,仅需一个依赖即可。



com.alibaba
easyexcel
3.0.5


EasyExcel 的导出导入支持两种方式进行处理

  • 第一种是通过实体类注解方式来生成文件和反解析文件数据映射成对象
  • 第二种是通过动态参数化生成文件和反解析文件数据

下面我们以用户信息的导出导入为例,分别介绍两种处理方式。

简单导出

首先,我们只需要创建一个UserEntity用户实体类,然后添加对应的注解字段即可,示例代码如下:

public class UserWriteEntity {

@ExcelProperty(value = "姓名")
private String name;

@ExcelProperty(value = "年龄")
private int age;

@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
@ExcelProperty(value = "操作时间")
private Date time;

//set、get...
}

然后,使用 EasyExcel 提供的EasyExcel工具类,即可实现文件的导出。

public static void main(String[] args) throws FileNotFoundException {
List dataList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
UserWriteEntity userEntity = new UserWriteEntity();
userEntity.setName("张三" + i);
userEntity.setAge(20 + i);
userEntity.setTime(new Date(System.currentTimeMillis() + i));
dataList.add(userEntity);
}
//定义文件输出位置
FileOutputStream outputStream = new FileOutputStream(new File("/Users/panzhi/Documents/easyexcel-export-user1.xlsx"));
EasyExcel.write(outputStream, UserWriteEntity.class).sheet("用户信息").doWrite(dataList);
}

运行程序,打开文件内容结果!

简单导入

这种简单固定表头的 Excel 文件,如果想要读取文件数据,操作也很简单。

以上面的导出文件为例,使用 EasyExcel 提供的EasyExcel工具类,即可来实现文件内容数据的快速读取,示例代码如下:

首先创建读取实体类

/**
* 读取实体类
*/
public class UserReadEntity {

@ExcelProperty(value = "姓名")
private String name;
/**
* 强制读取第三个 这里不建议 index 和 name 同时用,要么一个对象只用index,要么一个对象只用name去匹配
*/
@ExcelProperty(index = 1)
private int age;

@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
@ExcelProperty(value = "操作时间")
private Date time;

//set、get...
}

然后读取文件数据,并封装到对象里面

public static void main(String[] args) throws FileNotFoundException {
//同步读取文件内容
FileInputStream inputStream = new FileInputStream(new File("/Users/panzhi/Documents/easyexcel-user1.xls"));
List list = EasyExcel.read(inputStream).head(UserReadEntity.class).sheet().doReadSync();
System.out.println(JSONArray.toJSONString(list));
}

运行程序,输出结果如下:

[{"age":20,"name":"张三0","time":1616920360000},{"age":21,"name":"张三1","time":1616920360000},{"age":22,"name":"张三2","time":1616920360000},{"age":23,"name":"张三3","time":1616920360000},{"age":24,"name":"张三4","time":1616920360000},{"age":25,"name":"张三5","time":1616920360000},{"age":26,"name":"张三6","time":1616920360000},{"age":27,"name":"张三7","time":1616920360000},{"age":28,"name":"张三8","time":1616920360000},{"age":29,"name":"张三9","time":1616920360000}]

动态自由导出导入

在实际使用开发中,我们不可能每来一个 excel 导入导出需求,就编写一个实体类,很多业务需求需要根据不同的字段来动态导入导出,没办法基于实体类注解的方式来读取文件或者写入文件。

因此,基于EasyExcel提供的动态参数化生成文件和动态监听器读取文件方法,我们可以单独封装一套动态导出导出工具类,省的我们每次都需要重新编写大量重复工作,以下就是小编我在实际使用过程,封装出来的工具类,在此分享给大家!

  • 首先,我们可以编写一个动态导出工具类
public class DynamicEasyExcelExportUtils {

private static final Logger log = LoggerFactory.getLogger(DynamicEasyExcelExportUtils.class);

private static final String DEFAULT_SHEET_NAME = "sheet1";

/**
* 动态生成导出模版(单表头)
* @param headColumns 列名称
* @return excel文件流
*/
public static byte[] exportTemplateExcelFile(List headColumns){
List> excelHead = Lists.newArrayList();
headColumns.forEach(columnName -> { excelHead.add(Lists.newArrayList(columnName)); });
byte[] stream = createExcelFile(excelHead, new ArrayList<>());
return stream;
}

/**
* 动态生成模版(复杂表头)
* @param excelHead 列名称
* @return
*/
public static byte[] exportTemplateExcelFileCustomHead(List> excelHead){
byte[] stream = createExcelFile(excelHead, new ArrayList<>());
return stream;
}

/**
* 动态导出文件(通过map方式计算)
* @param headColumnMap 有序列头部
* @param dataList 数据体
* @return
*/
public static byte[] exportExcelFile(LinkedHashMap headColumnMap, List> dataList){
//获取列名称
List> excelHead = new ArrayList<>();
if(MapUtils.isNotEmpty(headColumnMap)){
//key为匹配符,value为列名,如果多级列名用逗号隔开
headColumnMap.entrySet().forEach(entry -> {
excelHead.add(Lists.newArrayList(entry.getValue().split(",")));
});
}
List> excelRows = new ArrayList<>();
if(MapUtils.isNotEmpty(headColumnMap) && CollectionUtils.isNotEmpty(dataList)){
for (Map dataMap : dataList) {
List rows = new ArrayList<>();
headColumnMap.entrySet().forEach(headColumnEntry -> {
if(dataMap.containsKey(headColumnEntry.getKey())){
Object data = dataMap.get(headColumnEntry.getKey());
rows.add(data);
}
});
excelRows.add(rows);
}
}
byte[] stream = createExcelFile(excelHead, excelRows);
return stream;
}


/**
* 生成文件(自定义头部排列)
* @param rowHeads
* @param excelRows
* @return
*/
public static byte[] customerExportExcelFile(List> rowHeads, List> excelRows){
//将行头部转成easyexcel能识别的部分
List> excelHead = transferHead(rowHeads);
return createExcelFile(excelHead, excelRows);
}

/**
* 生成文件
* @param excelHead
* @param excelRows
* @return
*/
private static byte[] createExcelFile(List> excelHead, List> excelRows){
try {
if(CollectionUtils.isNotEmpty(excelHead)){
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
EasyExcel.write(outputStream).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.head(excelHead)
.sheet(DEFAULT_SHEET_NAME)
.doWrite(excelRows);
return outputStream.toByteArray();
}
} catch (Exception e) {
log.error("动态生成excel文件失败,headColumns:" + JSONArray.toJSONString(excelHead) + ",excelRows:" + JSONArray.toJSONString(excelRows), e);
}
return null;
}

/**
* 将行头部转成easyexcel能识别的部分
* @param rowHeads
* @return
*/
public static List> transferHead(List> rowHeads){
//将头部列进行反转
List> realHead = new ArrayList<>();
if(CollectionUtils.isNotEmpty(rowHeads)){
Map> cellMap = new LinkedHashMap<>();
//遍历行
for (List cells : rowHeads) {
//遍历列
for (int i = 0; i < cells.size(); i++) {
if(cellMap.containsKey(i)){
cellMap.get(i).add(cells.get(i));
} else {
cellMap.put(i, Lists.newArrayList(cells.get(i)));
}
}
}
//将列一行一行加入realHead
cellMap.entrySet().forEach(item -> realHead.add(item.getValue()));
}
return realHead;
}

/**
* 导出文件测试
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//导出包含数据内容的文件(方式一)
LinkedHashMap headColumnMap = Maps.newLinkedHashMap();
headColumnMap.put("className","班级");
headColumnMap.put("name","学生信息,姓名");
headColumnMap.put("sex","学生信息,性别");
List> dataList = new ArrayList<>();
for (int i = 0; i < 5; i++) {
Map dataMap = Maps.newHashMap();
dataMap.put("className", "一年级");
dataMap.put("name", "张三" + i);
dataMap.put("sex", "男");
dataList.add(dataMap);
}
byte[] stream1 = exportExcelFile(headColumnMap, dataList);
FileOutputStream outputStream1 = new FileOutputStream(new File("/Users/panzhi/Documents/easyexcel-export-user5.xlsx"));
outputStream1.write(stream1);
outputStream1.close();


//导出包含数据内容的文件(方式二)
//头部,第一层
List head1 = new ArrayList<>();
head1.add("第一行头部列1");
head1.add("第一行头部列1");
head1.add("第一行头部列1");
head1.add("第一行头部列1");
//头部,第二层
List head2 = new ArrayList<>();
head2.add("第二行头部列1");
head2.add("第二行头部列1");
head2.add("第二行头部列2");
head2.add("第二行头部列2");
//头部,第三层
List head3 = new ArrayList<>();
head3.add("第三行头部列1");
head3.add("第三行头部列2");
head3.add("第三行头部列3");
head3.add("第三行头部列4");

//封装头部
List> allHead = new ArrayList<>();
allHead.add(head1);
allHead.add(head2);
allHead.add(head3);

//封装数据体
//第一行数据
List data1 = Lists.newArrayList(1,1,1,1);
//第二行数据
List data2 = Lists.newArrayList(2,2,2,2);
List> allData = Lists.newArrayList(data1, data2);

byte[] stream2 = customerExportExcelFile(allHead, allData);
FileOutputStream outputStream2 = new FileOutputStream(new File("/Users/panzhi/Documents/easyexcel-export-user6.xlsx"));
outputStream2.write(stream2);
outputStream2.close();


}
}

  • 然后,编写一个动态导入工具类
/**
* 创建一个文件读取监听器
*/
public class DynamicEasyExcelListener extends AnalysisEventListener> {
private static final Logger LOGGER = LoggerFactory.getLogger(UserDataListener.class);
/**
* 表头数据(存储所有的表头数据)
*/
private List> headList = new ArrayList<>();
/**
* 数

当前名称:SpringBoot实现Excel自由导入导出,性能强的离谱,用起来还特优雅
新闻来源:http://www.hantingmc.com/qtweb/news20/415470.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联