easyexcel文件上传

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

 @Override
    public 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
     */
    @Override
    public 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
     */
    @Override
    public 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<>();
    ......
}
 @Override
    public void importxxxRoster(MultipartFile file, HttpServletResponse response) {
        try {
  			.....
            // 获取错误信息集合
            List<DutyRosterErrorData> errorDataList = listener.getErrorDataList();
            if (!CollectionUtils.isEmpty(errorDataList)) {
				// 导出Excel
            }
        } catch (IOException e) {
			// 抛异常 ...
        }
    }

喜欢我的文章的话,点个阅读或者点个点赞,是我编写博客的动力,持续更新中 ing…

  • 8
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值