EasyPoi导出 导入(带校验)简单示例 EasyExcel

news/2024/7/21 5:01:32 标签: excel

官方文档 : http://doc.wupaas.com/docs/easypoi

pom的引入:

<!--        easyPoi-->
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-spring-boot-starter</artifactId>
            <version>4.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.4.1.Final</version>
        </dependency>
<!--        hutool-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-core</artifactId>
            <version>5.7.7</version>
        </dependency>

1.建立一个对象体

@Data
public class EasyPoiEntity {
    @Excel(name = "姓名")
    private String name;
    @Excel(name = "年龄")
    private int age;
    @Excel(name = "地址")
    private String addr;

}

2.导出代码

    @GetMapping("/exportExcel")
    public void test(HttpServletRequest request, HttpServletResponse response)throws IOException {
    //模拟数据  实际基本查数据
        EasyPoiEntity easyPoiEntity = new EasyPoiEntity();
        easyPoiEntity.setName("张三");
        easyPoiEntity.setAddr("中国");
        easyPoiEntity.setAge(18);
        List<EasyPoiEntity> list = new ArrayList<>();
        list.add(easyPoiEntity);
        //2.封装成表格
        //参数1:表格标题,参数2:sheet名称
//        ExportParams exportParams = new ExportParams("学生信息", "1班学生信息");
        ExportParams exportParams = new ExportParams();
        exportParams.setSheetName("学生信息");
        exportParams.setStyle(EasyExcelStyleType.ONE.getCla());
        //参数1:表格参数  参数2:实体类  参数3:数据
        Workbook sheets = ExcelExportUtil.exportExcel(exportParams, EasyPoiEntity.class, list);

        //3.返回表格
        //设置表格文件名字
        // 生成时间戳
        String timestamp = DateUtil.format(LocalDateTime.now(), "yyyyMMddHHmmss");
        String fileName = "一班学生数据-"+timestamp;
        fileName = URLEncoder.encode(fileName,"UTF8");
        //设置返回数据类型
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xls");

        //将表格输出
        sheets.write(response.getOutputStream());

    }

导出Excel
在这里插入图片描述

导入例子

1.对象加上校验注解 实现 IExcelDataModel, IExcelModel

@Data
public class EasyPoiEntity implements IExcelDataModel, IExcelModel {
    @Excel(name = "姓名")
    @Pattern(regexp = "[\u4E00-\u9FA5]*", message = "不是中文")
    private String name;
    @Max(value = 15,message = "max 最大值不能超过15")
    @Excel(name = "年龄")
    private int age;
    @NotNull(message = "地址不能为空")
    @Excel(name = "地址")
    private String addr;

    /**
     * 行号
     */
    private int rowNum;

    /**
     * 错误消息
     */
    private String errorMsg;

}

导入代码 params.setVerifyHandler(excelVerifyInfo);看后面

    @PostMapping("/importExcel")
    @ResponseBody
    public Object importUser(@RequestParam("uploadFile") MultipartFile multipartFile,HttpServletResponse resp) {
        ImportParams params = new ImportParams();

        /**
         * 这里需要注意表头的行数设置一定要正确!否则集合数据将无法读取,
         * 可以通过WPS或者office查看实际表头所占用的行数,
         * 一定要区分表头与标题的区别,表头是列名称,标题是表头上面的文字,
         * 本文示例文件中没有标题,所以setTitleRows为0
         */
        // 设置表头行数
        params.setHeadRows(1);
        // 标题行设置为0行,默认是0,可以不设置
        params.setTitleRows(0);
//        代表导入这里是需要验证的(根据字段上的注解校验)
        params.setNeedVerify(true);
        //设及一个自定义校验 (自定义校验名字不可重复)
        params.setVerifyHandler(excelVerifyInfo);
        try {
            ExcelImportResult<EasyPoiEntity> importResult = ExcelImportUtil.importExcelMore(multipartFile.getInputStream(), EasyPoiEntity.class, params);
            boolean verfiyFail = importResult.isVerfiyFail();
            System.out.println(verfiyFail);
            System.out.println(importResult.getFailList().toString());
            System.out.println(importResult.getList().toString());

            //验证是否有失败的数据
            if (importResult.isVerfiyFail()) {
                ServletOutputStream fos = resp.getOutputStream();
                //mime类型
                resp.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
                // 生成时间戳
                String timestamp = DateUtil.format(LocalDateTime.now(), "yyyyMMddHHmmss");

                resp.setHeader("Content-disposition", "attachment;filename=" + timestamp + "-error.xlsx");
                importResult.getFailWorkbook().write(fos);
                fos.close();
            }
            return importResult.getList();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

导入Excel例子
在这里插入图片描述
返回的异常Excel
在这里插入图片描述
对于想自定义异常的 自己写一个实现类实现 IExcelVerifyHandler<>即可
代码如下:

@Component
public class  ExcelVerifyInfo implements IExcelVerifyHandler<EasyPoiEntity> {
    private final ThreadLocal<List<EasyPoiEntity>> threadLocal = new ThreadLocal<>();
    @Override
    public ExcelVerifyHandlerResult verifyHandler(EasyPoiEntity easyPoiEntity) {
        StringJoiner joiner = new StringJoiner(",");
        List<EasyPoiEntity> threadLocalVal = threadLocal.get();
        if (threadLocalVal == null) {
            threadLocalVal = new ArrayList<>();
        }

        /**
         * 所有的自定义校验 可以再这里写 比如查数据 比较之类
         */
//        if (easyPoiEntity.getName().equals("张三")){
//            joiner.add("eeeeee");
//        }


        threadLocalVal.forEach(e -> {
            if (e.getName().equals(easyPoiEntity.getName())) {
                int lineNumber = e.getRowNum() + 1;
                joiner.add("名字与" + lineNumber + "行重复");
            }
        });
        // 添加本行数据对象到ThreadLocal中
        threadLocalVal.add(easyPoiEntity);
        threadLocal.set(threadLocalVal);
        if (!Objects.equals(joiner.length(),0)) {
            return new ExcelVerifyHandlerResult(false, joiner.toString());
        }
        return new ExcelVerifyHandlerResult(true);
    }
}

关于空行问题

Excel经常会有空行但是有格式的行 我们读取的时候 会读到这些行 然后对象就都是空的 这可能会影响到数据的处理 我是在校验类里面做了判断 如下:

@Component
public class  ExcelVerifyInfo implements IExcelVerifyHandler<EasyPoiEntity> {
    private final ThreadLocal<List<EasyPoiEntity>> threadLocal = new ThreadLocal<>();
    @Override
    public ExcelVerifyHandlerResult verifyHandler(EasyPoiEntity easyPoiEntity) {
        if ( StringUtils.isAllBlank(easyPoiEntity.getName(), easyPoiEntity.getAddr()) && Objects.equals(easyPoiEntity.getAge(),0)) {
            // 空行数据,返回false表示无效,EasyPoi会过滤掉该行数据
            return new ExcelVerifyHandlerResult(false);
        } else {
            // 非空行数据,返回true表示有效
            StringJoiner joiner = new StringJoiner(",");
            List<EasyPoiEntity> threadLocalVal = threadLocal.get();
            if (threadLocalVal == null) {
                threadLocalVal = new ArrayList<>();
            }

            /**
             * 所有的自定义校验 可以再这里写 比如查数据 比较之类
             */
//        if (easyPoiEntity.getName().equals("张三")){
//            joiner.add("eeeeee");
//        }


            threadLocalVal.forEach(e -> {
                if (e.getName().equals(easyPoiEntity.getName())) {
                    int lineNumber = e.getRowNum() + 1;
                    joiner.add("名字与" + lineNumber + "行重复");
                }
            });
            // 添加本行数据对象到ThreadLocal中
            threadLocalVal.add(easyPoiEntity);
            threadLocal.set(threadLocalVal);
            if (!Objects.equals(joiner.length(),0)) {
                return new ExcelVerifyHandlerResult(false, joiner.toString());
            }
            return new ExcelVerifyHandlerResult(true);
        }

    }
}

假如你对象属性多 不用全都判断是都空 只要找几个必填属性 然后判断为空就认为是空行就行了

数据翻译

1.简单的方式 直接用replace 会在导出导入进行翻译 比如你导出 一般状态是数字 会翻译成中文 导入则相反

    @Excel(name = "状态",replace = {"进行中_1", "完成_2","结束_3"})
    private String status;

Excel导入校验并返回异常Excel

    @PostMapping("/importExcel")
    @ResponseBody
    public void importUser(@RequestParam("uploadFile") MultipartFile multipartFile, HttpServletResponse response) {
        try {
        //自己找一个读的utlis
            List<User> read = EasyExcelUtil.read(multipartFile.getInputStream(), User.class);
            //拿到数据 校验数据 有问题就set导msg 然后把流写出
            List<User> errList = new ArrayList<>();
            for (User user : read) {
                if (user.getName().equals("张三")){
                    user.setMsg("这是一个错误数据");
                    errList.add(user);
                }
            }
            if (CollectionUtil.isNotEmpty(errList)){
                // 生成时间戳
                String timestamp = DateUtil.format(LocalDateTime.now(), "yyyyMMddHHmmss");
                EasyExcelUtil.write(response,"err_"+timestamp,errList,"test");
            }
            System.out.println(read);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

对象

@Data
public class User {
    private String name;
    private String phone;
    private String addr;

    @ContentFontStyle(color = Font.COLOR_RED)
    @ColumnWidth(value = 25)
    private String msg;

}

http://www.niftyadmin.cn/n/4928275.html

相关文章

深入JVM - JIT分层编译技术与日志详解

深入JVM - JIT分层编译技术与日志详解 文章目录 深入JVM - JIT分层编译技术与日志详解1. 背景简介2. JIT 编译器2.1. 客户端版本的编译器: C12.2. 服务端版本的编译器: C22.3. Graal JIT 编译器 3. 分层编译技术(Tiered Compilation)3.1. 汇聚两种编译器的优点3.2. 精准优化(Ac…

基于STM32设计的口罩识别和无线测温系统

一、设计需求 基于STM32设计的口罩识别和无线测温系统 1.1 项目背景 随着深度学习和计算机视觉的快读发展,与此有关的技术设备已经被大幅度的使用,并且不仅仅在这两个方面,更在许许多多的领域都有使用。众所周知,图像理解之中的最重要的一个步骤即为目标检测,和为目标检测…

基于MATLAB实现小波算法仿真(附上多个完整源码+数据集)

小波变换是一种常用的信号处理技术&#xff0c;广泛应用于图像处理、音频处理、压缩等领域。本文将介绍MATLAB中小波变换的基本原理和实现方法&#xff0c;并给出一个示例来说明如何使用MATLAB进行小波变换和逆变换。 文章目录 1. 引言2. 小波变换的基本原理3. MATLAB中的小波变…

docker 部署 xxl-job-admin

1、先安装mysql docker pull mysql 2、运行mysql 容器 &#xff08; 端口 3306 容器名称 mysql 密码 123456 &#xff09; docker run -d --name mysql -e MYSQL_ROOT_PASSWORD123456 -p 3306:3306 mysql 3、将tables_xxl_job.sql文件&#xff08;官网地址&#xff1a;http…

免费小程序商城搭建之b2b2c o2o 多商家入驻商城 直播带货商城 电子商务b2b2c o2o 多商家入驻商城 直播带货商城 电子商务 bbc

1. 涉及平台 平台管理、商家端&#xff08;PC端、手机端&#xff09;、买家平台&#xff08;H5/公众号、小程序、APP端&#xff08;IOS/Android&#xff09;、微服务平台&#xff08;业务服务&#xff09; 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前端…

C++ 多态性——纯虚函数与抽象类

抽象类是一种特殊的类&#xff0c;它为一个类族提供统一的操作界面。抽象类是为了抽象和设计的目的而建立的。可以说&#xff0c;建立抽象类&#xff0c;就是为了通过它多态地使用其中的成员函数。抽象类处于类层次的上层&#xff0c;一个抽象类自身无法实例化&#xff0c;也就…

深度思考mysql面经

推荐 1 索引下推 Mysql性能优化&#xff1a;什么是索引下推&#xff1f; 1.1 定义 索引下推&#xff08;Index Condition Pushdown&#xff0c;简称 ICP&#xff09;是一种数据库优化技术。在传统的数据库查询中&#xff0c;数据库首先使用索引检索来找到符合索引条件的行&…

QGIS开发五:使用UI文件

前面我们说了在创建项目时创建的是一个空项目&#xff0c;即不使用 Qt 提供的综合开发套件 Qt Creator&#xff0c;也不使用 Qt Visual Studio Tools 这类工具。 但是后面发现&#xff0c;如果我想要有更加满意的界面布局&#xff0c;还是要自己写一个UI文件&#xff0c;如果不…