easy-excel 导入数据校验 不正确则导出excel并提示错误信息

需求 : 导入excel 校验第二列 数据格式 不正确则导出excel并提示错误信息
导入图:
在这里插入图片描述
预期效果:
在这里插入图片描述

引入依赖

		<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.2.6</version>
        </dependency>

二 :创建读监听器 继承 AbstractEasyExcelDataListener 并重写 validator, save 方法 校验数据和保存数据库操作 到此就大功告成

package com.example.jddemo.excel.upload.excellistener;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@Scope("prototype")// 开启多例   单例存在并发安全问题 [使用如下]
/**
 *     @Resource
 *     private ObjectFactory<MyDataEasyExcelListener> obj;
 *
 *     使用: AbstractEasyExcelDataListener listener=obj.getObject();
 */
public class MyDataEasyExcelListener extends AbstractEasyExcelDataListener {

    @Override
    protected void validator(List<Object> row, StringBuilder msg) {
        // 数据校验
        Object number = row.get(1);
        if (!isNumber(number.toString(), 2)) {
            // System.out.println(number + "不是数字");
            msg.append(number + "不是数字");
            excelDto.setHaveError(true);
        }
        //校验 。。。。。。。。。
        if (true) {

        }
    }

    /**
     * 保存数据库
     *
     * @param excelDto
     */
    @Override
    protected void save(ExcelDto excelDto) {
        if(excelDto.isHaveError()){
            System.out.println("校验数据有错误信息  不执行数据库操作");
            return;
        }
        List<List<Object>> content = excelDto.getContent();
        System.out.println("保存的数据:"+content);
    }

    /**
     * 数字类型  最多保留两位小数
     *
     * @param str   校验的字符串
     * @param scale 保留小数位
     * @return
     */
    public static boolean isNumber(String str, int scale) {
        String reg = "^(\\d{1,8})(\\.\\d{1," + scale + "})?$";
        return str.matches(reg);

    }
}

三 :AbstractEasyExcelDataListener 为抽象公共类 用户只需要继承它 重写 validator, save 方法


package com.example.jddemo.excel.upload.excellistener;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.write.metadata.WriteSheet;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.IOException;
import java.util.*;

public abstract class AbstractEasyExcelDataListener extends AnalysisEventListener<Map<Integer, String>> {

    protected ExcelDto excelDto = null;

    private File tempFile = null;//临时文件
    private ExcelWriter excelWriter = null;
    private WriteSheet writeSheet = null;
    private StringBuilder msg = null;// 行数据校验 提示信息
    private List<List<String>> head =null;//生成动态表头

    public AbstractEasyExcelDataListener() {

    }
    public AbstractEasyExcelDataListener buildSheetName(String sheetName){
        excelDto.setSheetName(sheetName);
        return this;
    }
    public AbstractEasyExcelDataListener buildFileName(String  fileName){
        excelDto.setFileName(fileName);
        return this;
    }

    public void open() {
        //生成临时文件
        try {
            excelDto = new ExcelDto();
            head = new ArrayList<>();
            tempFile = File.createTempFile("tmp", ".xlsx");
            writeSheet = EasyExcel.writerSheet(StringUtils.isBlank(excelDto.getSheetName())?"模板":excelDto.getSheetName()).sheetNo(0).build();
            //写入临时文件
            //excelWriter = EasyExcel.write(tempFile).head(head).build();
            excelWriter = EasyExcel.write("D:\\abc.xlsx").head(head).build();
            excelDto.setHead(head);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        List<String> list = new ArrayList<>(headMap.values());
        //初始化表头
        if (head.size() == 0) {
            head.add(new ArrayList<String>(Collections.singleton("错误列信息提示")));
            list.forEach(item -> {
                head.add(new ArrayList<String>(Collections.singleton(item)));
            });
            return;
        }
        for (int i = 0; i < list.size(); i++) {
            String str = list.get(i);
            List<String> headI = this.head.get(i + 1);
            headI.add(str);
        }
    }

    @Override
    public void invoke(Map<Integer, String> row, AnalysisContext context) {
        List<Object> responseRow = new ArrayList<>(row.values());
        Integer rowIndex = context.readRowHolder().getRowIndex();
        System.out.println("读取行" + rowIndex + "数据");
        msg = new StringBuilder("");
        //校验数据
        this.validator(responseRow, msg);
        responseRow.add(0, msg.toString());
        excelDto.getTmpContent().add(responseRow);
        //保存全量数据  高并发或者数据量较大时不建议使用
        if (this.enableContent()) {
            excelDto.getContent().add(responseRow);
        }
        // 三千条数据 写入一次
        if (excelDto.getTmpContent().size() >= excelDto.getCount()) {
            if (!enableContent()) {
                excelDto.setContent(excelDto.getTmpContent());
                this.save(excelDto);//数据落库
            }
            excelWriter.write(excelDto.getTmpContent(), writeSheet);//写入新文件
            excelDto.getTmpContent().clear();
        }
    }

    /**
     * 返回 true  ExcelDto content 会保存excel 中全量数据
     * 返回 false ExcelDto content 不会保存数据
     *
     * @return
     */
    protected boolean enableContent() {
        return false;
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        System.out.println("数据读取完毕");
        if (!enableContent()) {
            excelDto.setContent(excelDto.getTmpContent());
        }
        excelWriter.write(excelDto.getTmpContent(), writeSheet);//写入新文件
        // 千万别忘记finish 会帮忙关闭流
        if (excelWriter != null) {
            excelWriter.finish();
        }
        this.save(excelDto);//数据落库
        this.saveFile(tempFile);// 保存临时文件 到服务器
        excelDto.getTmpContent().clear();//清除临时数据
    }

    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        //手动抛出异常 读操作终止
        throw new RuntimeException("excel处理数据监听异常:" + exception.getMessage());
    }

    /**
     * 保存附件到服务器
     *
     * @param tempFile
     */
    protected void saveFile(File tempFile) {
        System.out.println("保存文件到文件服务器");
        this.excelDto.setUrl("url://文件服务器地址");
    }

    public void close() {
        // 千万别忘记finish 会帮忙关闭流
        if (excelWriter != null) {
            excelWriter.finish();
        }
        if (tempFile != null && tempFile.exists()) {
            tempFile.delete();
        }

    }

    /**
     * 行数据校验
     *
     * @param row
     * @param msg
     */
    protected abstract void validator(List<Object> row, StringBuilder msg);

    /**
     * 数据库操作  保存数据
     *
     * @param excelDto
     */
    protected abstract void save(ExcelDto excelDto);

    public ExcelDto getExcelDto() {
        return excelDto;
    }

    public void setExcelDto(ExcelDto excelDto) {
        this.excelDto = excelDto;
    }

}

四: 实体类

package com.example.jddemo.excel.upload.excellistener;

import java.util.ArrayList;
import java.util.List;

public class ExcelDto {

    private List<List<String>> head        = new ArrayList<>();//表头
    private List<List<Object>> tmpContent  = new ArrayList<>();//临时数据
    private List<List<Object>> content     = new ArrayList<>();//保存全量数据  高并发或者数据量较大时不建议使用  [如需开启  重写 enableContent()方法 返回true]
    private boolean            isHaveError;//默认false
    private int                count       = 3000;//三千条数据 提交一次
    private String             url;//文件上传后的地址

    public List<List<String>> getHead() {
        return head;
    }
    public void setHead(List<List<String>> head) {
        this.head = head;
    }
    public List<List<Object>> getTmpContent() {
        return tmpContent;
    }
    public void setTmpContent(List<List<Object>> tmpContent) {
        this.tmpContent = tmpContent;
    }
    public boolean isHaveError() {
        return isHaveError;
    }
    public void setHaveError(boolean haveError) {
        isHaveError = haveError;
    }
    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count = count;
    }
    public String getUrl() {
        return url;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public List<List<Object>> getContent() {
        return content;
    }
    public void setContent(List<List<Object>> content) {
        this.content = content;
    }
    @Override
    public String toString() {
        return "ExcelDto{" +
                "head=" + head +
                ", tmpContent=" + tmpContent +
                ", saveContent=" + content +
                ", isHaveError=" + isHaveError +
                ", count=" + count +
                ", url='" + url + '\'' +
                '}';
    }
}

测试:

package com.example.jddemo.excel.upload;

import com.alibaba.excel.EasyExcel;
import com.example.jddemo.excel.upload.excellistener.AbstractEasyExcelDataListener;
import com.example.jddemo.excel.upload.excellistener.ExcelDto;
import com.example.jddemo.excel.upload.excellistener.MyDataEasyExcelListener;
import com.example.jddemo.response.ResponseEntity;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.annotation.Resource;

/**
 * 程序员  by dell
 * time  2020-12-09
 **/
@Controller
public class AppController {

    @Resource
    private ObjectFactory<MyDataEasyExcelListener> obj;

   @RequestMapping(value = "/excel")
   public  void exce(String file){
       AbstractEasyExcelDataListener listener=obj.getObject();

       System.out.println("对象:"+listener);

       ResponseEntity<String> response = new ResponseEntity<>();
       response.setCode(ResponseEntity.CODE_NORMAL);
       ExcelDto excelDto = null;

       try {
           listener.open();//1606185114659.xlsx
           listener.buildFileName("文件名")
                   .buildSheetName("shee名");
           EasyExcel.read("D:\\"+file).sheet().headRowNumber(1)
                   .registerReadListener(listener).doRead();
           excelDto = listener.getExcelDto();
           if (excelDto.isHaveError()) {
               throw new RuntimeException("校验数据不通过 请更改数据后重新导入");
           }
           System.out.println(excelDto);
       } catch (RuntimeException e) {
           e.printStackTrace();
           response.setCode(ResponseEntity.CODE_WARN);
           response.setMessage(e.getMessage());
           response.setData(excelDto.getUrl());
       }finally {
           listener.close();
       }
   }


}

在这里插入图片描述

文件默认导出D盘 也可上传文件服务器

如果帮到你点个赞关注下!!! O(∩_∩)O哈哈~

  • 12
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值