注解 | 类型 | 描述 |
---|---|---|
ExcelProperty | 导入 | 指定当前字段对应excel中的那一列。可以根据名字或者Index去匹配。当然也可以不写,默认第一个字段就是index=0,以此类推。千万注意,要么全部不写,要么全部用index,要么全部用名字去匹配。千万别三个混着用,除非你非常了解源代码中三个混着用怎么去排序的。 |
ExcelIgnore | 导入 | 默认所有字段都会和excel去匹配,加了这个注解会忽略该字段 |
DateTimeFormat | 导入 | 日期转换,用String 去接收excel日期格式的数据会调用这个注解。里面的value 参照java.text.SimpleDateFormat |
NumberFormat | 导入 | 数字转换,用String 去接收excel数字格式的数据会调用这个注解。里面的value 参照java.text.DecimalFormat |
ExcelIgnoreUnannotated | 导入 | 默认不加ExcelProperty 的注解的都会参与读写,加了不会参与 |
导入方法参数:ReadWorkbook
,ReadSheet
都会有的参数,如果为空,默认使用上级。
converter
转换器,默认加载了很多转换器。也可以自定义。readListener
监听器,在读取数据的过程中会不断的调用监听器。headRowNumber
需要读的表格有几行头数据。默认有一行头,也就是认为第二行开始起为数据。head
与clazz
二选一。读取文件头对应的列表,会根据列表匹配数据,建议使用class。clazz
与head
二选一。读取文件的头对应的class,也可以使用注解。如果两个都不指定,则会读取全部数据。autoTrim
字符串、表头等数据自动trim- password 读的时候是否需要使用密码
ReadWorkbook(理解成excel对象)参数
-
excelType
当前excel的类型 默认会自动判断 -
inputStream
与file
二选一。读取文件的流,如果接收到的是流就只用,不用流建议使用file
参数。因为使用了inputStream
easyexcel会帮忙创建临时文件,最终还是file
-
file
与inputStream
二选一。读取文件的文件。 -
autoCloseStream
自动关闭流。 -
readCache
默认小于5M用 内存,超过5M会使用EhCache
,这里不建议使用这个参数。 -
useDefaultListener@since 2.1.4默认会加入ModelBuildEventListener来帮忙转换成传入class的对象,设置成false后将不会协助转换对象,自定义的监听器会接收到Map<Integer,CellData>对象,如果还想继续接听到
class对象,请调用readListener方法,加入自定义的beforeListener、ModelBuildEventListener、 自定义afterListener即可。
ReadSheet(就是excel的一个Sheet)参数
sheetNo
需要读取Sheet的编码,建议使用这个来指定读取哪个SheetsheetName
根据名字去匹配Sheet,excel 2003不支持根据名字去匹配
添加pom依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.6</version>
</dependency>
<!--工具类-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.23</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.21</version>
</dependency>
<!--commons依赖 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
第一种:简单导入
实体类
package com.example.mybatismysql8demo.excel;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
import java.math.BigDecimal;
@Data
//忽视无注解的字段
@ExcelIgnoreUnannotated
public class GoodsImportExcel {
/**
* 用名字去匹配,这里需要注意,如果名字重复,会导致只有一个字段读取到数据
*/
@ExcelProperty(value = {
"商品信息","商品名称"},index = 0)
public String goodsName;
@ExcelProperty(value = {
"商品信息","商品价格"},index = 1)
public BigDecimal price;
@ExcelProperty(value = {
"商品信息","商品数量"},index = 2)
public Integer num;
}
监听器
package com.example.mybatismysql8demo.handler;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.example.mybatismysql8demo.excel.GoodsImportExcel;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import java.util.List;
import java.util.function.Consumer;
/**
* 读取excel数据
*/
public class DemoDataListener extends AnalysisEventListener<GoodsImportExcel> {
/**临时存储正常数据集合,最大存储100*/
private List<GoodsImportExcel> successDataList = Lists.newArrayListWithExpectedSize(100);
/**自定义消费者函数接口用于自定义监听器中数据组装*/
private final Consumer<List<GoodsImportExcel>> successConsumer;
public DemoDataListener(Consumer<List<GoodsImportExcel>> successConsumer) {
this.successConsumer = successConsumer;
}
@Override
public void invoke(GoodsImportExcel goodsImportExcel, AnalysisContext analysisContext) {
successDataList.add(goodsImportExcel);
System.out.println("数据:"+goodsImportExcel);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
if (CollectionUtils.isNotEmpty(successDataList)) {
successConsumer.accept(successDataList);
}
}
}
执行方法
package com.example.mybatismysql8demo.controller;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.fastjson.JSONObject;
import com.example.mybatismysql8demo.excel.GoodsImportExcel;
import com.example.mybatismysql8demo.handler.DemoDataListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.*;
@Slf4j
@RestController
public class EasyExcelController {
@PostMapping("/easyExcelImport")
public void importExcel(MultipartFile file,Integer type) {
if (!file.isEmpty()) {
//文件名称
int begin = Objects.requireNonNull(file.getOriginalFilename()).indexOf(".");
//文件名称长度
int last = file.getOriginalFilename().length();
//判断文件格式是否正确
String fileName = file.getOriginalFilename().substring(begin, last);
if (!fileName.endsWith(".xls") && !fileName.endsWith(".xlsx")) {
throw new IllegalArgumentException("上传文件格式错误");
}
} else {
throw new IllegalArgumentException("文件不能为空");
}
try (InputStream inputStream = file.getInputStream()) {
if (type == 1){
simpleRead(inputStream);
}else if (type == 2){
synchronousRead(inputStream);
}else {
repeatedRead(inputStream);
}
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
/**
* 最简单的读的监听器
*/
public void simpleRead(InputStream inputStream){
//获取正确数据
ArrayList<GoodsImportExcel> successArrayList = new ArrayList<>();
EasyExcel.read(inputStream)
.head(GoodsImportExcel.class)
.registerReadListener(new DemoDataListener(
// 监听器中doAfterAllAnalysed执行此方法;所有读取完成之后处理逻辑
successArrayList::addAll))
// 设置sheet,默认读取第一个
.sheet()
// 设置标题(字段列表)所在行数
.headRowNumber(2)
.doRead();
System.out.println(successArrayList);
}
/**
* 同步的返回,不推荐使用,如果数据量大会把数据放到内存里面
*/
public void synchronousRead(InputStream inputStream){
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 同步读取会自动finish
List<GoodsImportExcel> batchGoodsImportModels = EasyExcel.read(inputStream)
.head(GoodsImportExcel.class)
// 设置sheet,默认读取第一个
.sheet()
// 设置标题(字段列表)所在行数
.headRowNumber(2)
.doReadSync();
System.out.println(JSONObject.toJSONString(batchGoodsImportModels));
}
/**
* 同步的返回,不指定class,返回一个list
*/
public void synchronousReadNoClass(InputStream inputStream){
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 同步读取会自动finish
List<Map<Integer, String>> batchGoodsImportModels = EasyExcel.read(inputStream)