前言
这个方式说起来比较麻烦,主要就是实体类,所以本文章包含实体类部分,要仔细看一下
实体类说明:
- No2数据库实体类
- up是导入时用的,里面的字段要对应Excel表格,包括顺序也要对应
- 导入时,表格的顺序必须要对应实体类顺序,或者实体类顺序对应表格顺序(重要)
准备
1.依赖
之前我们想到Excel解析一般是使用POI,但POI存在一个严重的问题,就是非常消耗内存。所以阿里人员对它进行了重写从而诞生了easyexcel
,它解决了过于消耗内存问题,也对它进行了封装让使用者使用更加便利
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.6</version>
</dependency>
因为本文章使用的是mybatis-plus对数据库进行操作,所以还需要一个mybatis-plus依赖
代码语言:javascript复制<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
2.导入需要的根据类
如果你不需要把Excel里面的数据导入到数据库,就不需要这个工具类
24行,有个ExcelDataListener<T extends No2,E>,No2是数据库实体类 意思是Excel导入时,对应那个数据库实体类
代码语言:javascript复制package com.zb.config;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.zb.entity.No2;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;
/**
* Excel解析批量存储
* @param <T>
*/
@Slf4j
/**
* 下面一行里面有一个No2,这是个实体类
* No2的实体类是: 是数据库的,意思是Excel导入时,对应那个数据库实体类
*/
public class ExcelDataListener<T extends No2,E> extends AnalysisEventListener<E> {
private Class<T> clazz;
/**
* 每隔500条存储数据库
*/
private static final int BATCH_COUNT = 500;
//存储的具体操作
private Function<Collection<T>,Boolean> saveFunc;
//批量存储的数据
private List<T> list = new ArrayList<>();
/**
* 通过 AnalysisContext 对象还可以获取当前 sheet,当前行等数据
*/
@Override
public void invoke(E e, AnalysisContext analysisContext) {
try {
T t = clazz.getDeclaredConstructor(null).newInstance();
BeanUtils.copyProperties(e,t);
list.add(t);
if (list.size() >= BATCH_COUNT) {
this.saveFunc.apply(list);
// 存储完成清理 list
list.clear();
}
} catch (Exception ex) {
log.error("出现错误:",ex);
}
}
/**
* 读取完之后的操作
*/
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
this.saveFunc.apply(list);
}
/**
*
* @param saveFunc 持久化数据到数据库的方法
* @param clazz 对应的实体类类型
*/
public ExcelDataListener(Function<Collection<T>,Boolean> saveFunc,Class<T> clazz){
this.saveFunc = saveFunc;
this.clazz = clazz;
}
}
数据导出到Excel
1.实体类准备
将要导出的实体类上面加
@ContentRowHeight(15) | @HeadRowHeight(20) | @ColumnWidth(25) |
---|---|---|
设置表体行高15 | 表头行高15 | 设置列宽列宽25 |
字段上面加
@ExcelProperty(value = “分账日期”,index = 0) | @ColumnWidth(30) |
---|---|
名字/第几个 | 如果有公司名字之类,太长,就单独给字段设置宽30 |
@Data
@ContentRowHeight(15)
@HeadRowHeight(20)
@ColumnWidth(25)
public class BillExportDataVO {
@DateTimeFormat("yyyy年MM月dd日")
@ExcelProperty(value = "分账日期",index = 0)
private Date date;
@ColumnWidth(30)
@ExcelProperty(value = "分账点位",index = 1)
private String nodeName;
@ExcelProperty(value = "订单数",index = 2)
private Integer orderCount;
@ExcelProperty(value = "分账金额",index = 3)
private Integer amount;
}
2.控制器代码
注意:29行和40行,注意看注释
代码语言:javascript复制 @RequestMapping("/excel")
public void excel(HttpServletResponse response){
//查询所有数据
List<No2> testex = no.list();
//设置头部
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
//设置导出的表格名字叫: test.xlsx
response.setHeader("Content-disposition", "attachment;filename=test.xlsx");
try {
//No2.class: 数据库实体类
//分账数据: 表格底部的页名
//testex: 要导出的数据来自那个变量
EasyExcel.write(response.getOutputStream(), No2.class).sheet("分账数据").doWrite(testex);
} catch (IOException e) {
e.printStackTrace();
}
}
Excel数据导入到数据库
它的大概逻辑就是:
- 接收实体类就是:对应Excel的实体类
- 将表格里面的数据,全部读取出来,然后映射到接收实体类里面,接受实体类再对照 数据库实体 类进行批量插入到数据库
1.实体类准备
需要准备一个对应Excel的接受实体类,我准备的名字叫up
例如:我的表格
对应的实体类
@ExcelProperty(“编号2”) |
---|
对应表格里面的名字 |
需要注意: 必须对应表格里面顺序,如果你的数据库id是自增的,就把数据库实体类里面的id先删除,就可以正常导入了
2.控制器代码
不多bb no.saveBatch(list):mybatis-plus的批量插入方法,no是我变量名 No2:数据库实体类 up:接受实体类(对应Excel的)
代码语言:javascript复制 @PostMapping("/upload")
public String upload(@RequestParam("fileName") MultipartFile file) throws IOException {
Function<List<No2>,Boolean> insertFunc = list-> no.saveBatch(list);
ExcelDataListener<No2, up> dataListener = new ExcelDataListener(insertFunc,No2.class);
EasyExcel.read(file.getInputStream(), No2.class,dataListener).sheet().doRead();
return "上传成功";
}