easyexcel文件上传
前言:功能开发中,难免碰到数据上传下载功能,excel上传常见用于报表上传,绩效上传,考勤上传…
使用步骤:
1,编写业务层:
1,添加easyexcel依赖
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.2.0</version></dependency>
2,导入模板excel下载
通常有个模版下载功能,在模板里面添加表头,以及数据格式…
3,在导入Excel模版中添加导入数据
4,导入
controller
@PostMapping("/importxxxRoster")@ApiOperation("导入xxx信息")public void importxxxRoster(MultipartFile file, HttpServletResponse response) {dutyRosterService.importDutyRoster(file, response);}
service
/*** 导入xxx信息** @param file* 文件* @param response* 响应*/void importxxxRoster(MultipartFile file, HttpServletResponse response);
serviceImpl
@Overridepublic void importxxxRoster(MultipartFile file, HttpServletResponse response) {try {InputStream is = file.getInputStream();// 监听器不能放在容器里面,要通过构造器的方式,放入监听器使用xxxxRosterDataListener listener = new xxxxRosterDataListener(this.baseMapper);// xxxRosterData 接收导入Excel 实体类EasyExcel.read(is, xxxRosterData.class, listener).doReadAll();// 获取错误信息集合List<xxxRosterErrorData> errorDataList = listener.getErrorDataList();if (!CollectionUtils.isEmpty(errorDataList)) {response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");String fileName = URLEncoder.encode("xxx导入错误详情", "UTF-8");response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");// 导出错误Excel数据EasyExcel.write(response.getOutputStream(), xxxRosterErrorData.class).sheet("错误详情").doWrite(errorDataList);}} catch (IOException e) {log.error("导入xxexcel异常:{}", e);// 编写异常信息}}
接收导入Excel 数据实体
xxxRosterData
package com.xx.xx.xx.entity.excel;import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;/*** @author psd xxx导入excel 接收数据实体**/
@Data
public class xxxRosterData {/*** 值班时间str*/@ExcelProperty(value = "日期",order = 0)private String dutyTimeStr;/*** 人员名称*/@ExcelProperty(value = "人员名称",order = 1)private String person;}
2,编写监听器
package com.xxx.xx.xx.listener;import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.xx.xx.common.result.ResultCodeEnum;
import com.xx.xx.common.utils.DateUtils;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;import java.util.*;
import java.util.stream.Collectors;/*** @author psd 创建xx信息导入监听器*/
@Data
public class xxxRosterDataListener extends AnalysisEventListener<xxxRosterData> {XXXRosterMapper xxxRosterMapper;/*** 记录批量导入数据*/private List<xxxRosterEntity> batchInsertDutyList = new ArrayList<>();/*** 记录需要更新的数据*/private List<xxxRosterEntity> batchUpdateDutyList = new ArrayList<>();/*** 记录错误的数据*/private List<xxxRosterErrorData> errorDataList = new ArrayList<>();/*** 记录没有问题的数据集合*/private List<xxxxRosterEntity> normalData = new ArrayList<>();// 创建构造器 引入用到的service mapper...public xxRosterDataListener(xxxRosterMapper dutyRosterMapper) {this.xxRosterMapper = xxxRosterMapper;}/*** 每一条数据都会解析* * @param data* 每行数据* @param analysisContext*/@Overridepublic void invoke(xxxRosterData data, AnalysisContext analysisContext) {// 1、添加常见的行数校验// 2、参数校验if (validateData(data)) {// 说明没有问题// 3、编写要导入的数据对象信息放入normalData.add(xxx);}}/*** 常见的数据校验* * @param data* 每一行的数据集* @return 是否异常 true 数据基本判断没有问题,false 说明有异常*/private boolean validateData(xxxxRosterData data) {StringBuffer errorMsg = new StringBuffer();// 清空字符串errorMsg.setLength(ConstantUtils.ZERO);// 添加数据校验if (StringUtils.isBlank(errorMsg)) {// 说明没有问题 return true;} else {// 记录错误信息 errorDataList.add();return false;}}/*** 所有数据执行完才会调用* * @param analysisContext*/@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {// 1、获取没有问题的数据// 2、判断哪些是新增的 哪些是需要修改的// 3、批量入库。。。}
}
常见遇到的问题:
问题一:
下载模板导入Excel时候明明写了数据,但是错误数据还是为空的问题,或者导入不成功?
原因是:
1,Excel的表头字段名字要和接收的数据Vo对象里面的字段名称一致
比如:
Excel模板中的表头为:
数据接收对象的字段名称为
导致接收不到
2,有可能是排序的问题,比如上图日期在第一位,但是数据xxxData实体类接收对象
order = 不是0,也会导致没有接收到数据
问题二:
在监听器添加注解比如@Component … 或者其他注解,使用@Autowired 、或者@Resources注解引入xxxService 、xxxMapper ,引入的service和mapper无法使用
这个是因为监听器不支持这种引入,可以通过构造器方式将数据传递过去,监听器不是放在spring容器中【这点是自己的理解,可能有误】
问题三:
错误信息如何导出?
我们可以在监听器添加@Data注解通过getxxx()方式获取错误数据,可以做成导出Excel功能。
@Data
public class xxxRosterDataListener extends AnalysisEventListener<xxxRosterData> {/*** 记录错误的数据*/private List<xxxRosterErrorData> errorDataList = new ArrayList<>();......
}
@Overridepublic void importxxxRoster(MultipartFile file, HttpServletResponse response) {try {.....// 获取错误信息集合List<DutyRosterErrorData> errorDataList = listener.getErrorDataList();if (!CollectionUtils.isEmpty(errorDataList)) {// 导出Excel}} catch (IOException e) {// 抛异常 ...}}
喜欢我的文章的话,点个阅读或者点个点赞,是我编写博客的动力,持续更新中 ing…