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

news2024/11/25 11:04:45

官方文档 : 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.coloradmin.cn/o/855814.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

分布式协调组件Zookeeper

Zookeeper介绍 什么是Zookeeper ZooKeeper 是⼀种分布式协调组件&#xff0c;用于管理大型主机。在分布式环境中协调和管理服务是一个复杂的过程。ZooKeeper 通过其简单的架构和 API 解决了这个问题。ZooKeeper 允许开发人员专注于核心应用程序逻辑&#xff0c;而不必担心应用…

【Linux】多线程——线程引入 | 线程控制

文章目录 一、Linux多线程1. 线程概念2. 线程创建3. 线程和进程4. 线程的优缺点 二、线程控制1. 线程创建2. 线程终止3. 线程等待4. 线程分离5. 线程局部存储 三、线程封装 一、Linux多线程 一级页表和二级页表都是key/val模型&#xff0c;一级页表的key是第一份的10个比特位&a…

(统计学习方法|李航)第一章统计学习方法概论——四五六节模型评估与模型选择,正则化与交叉验证,泛化能力

一&#xff0c;模型评估与模型选择 1.训练误差与测试误差 假如我们有100个数据。80条记录给训练集&#xff0c;10条记录给测试集&#xff0c;10条记录给验证集 先在训练集中训练模型&#xff0c; 再在验证集上测试看哪种模型更拟合 最后用测试集算出成绩 表示决策函数 模型…

数据清理在数据科学中的重要性

什么是数据清理&#xff1f; 推荐&#xff1a;使用 NSDT场景编辑器 助你快速搭建可编辑的3D应用场景 在数据科学中&#xff0c;数据清理是识别不正确数据并修复错误的过程&#xff0c;以便最终数据集可供使用。错误可能包括重复字段、格式不正确、字段不完整、数据不相关或不准…

基于kettle实现pg数据定时转存mongodb

mogodb 待创建 基于kettle实现pg数据定时转存mongodb_kettle 实时迁移 mongodb_呆呆的私房菜的博客-CSDN博客

链表和哈希Set

1 LinkedList集合类 LinkedList集合类底层是使用双向链表实现的&#xff0c;相较于ArrayList&#xff0c;更方便进行增删操作。 在增删查改方面&#xff0c;新增了头尾操作&#xff0c;比如从头部插入、尾部插入、头部删除、尾部删除、头部查询和尾部查询等操作。由于有头尾的…

SpringCloud实用篇3----Docker

1.初识Docker 1.1 什么是Docker 微服务虽然具备各种各样的优势&#xff0c;但服务的拆分通用给部署带来了很大的麻烦。 分布式系统中&#xff0c;依赖的组件非常多&#xff0c;不同组件之间部署时往往会产生一些冲突。在数百上千台服务中重复部署&#xff0c;环境不一定一致…

gitblit windows部署

1.官网下载 往死慢&#xff0c;我是从百度找的1.9.1&#xff0c;几乎就是最新版 http://www.gitblit.com/ 2.解压 下载下来是一个zip压缩包&#xff0c;直接解压即可 3.配置 3.1.配置资源库路径 找到data文件下的gitblit.properties文件&#xff0c;用Notepad打开 **注意路…

云原生可观测框架 OpenTelemetry 基础知识(架构/分布式追踪/指标/日志/采样/收集器)...

什么是 OpenTelemetry&#xff1f; OpenTelemetry 是一个开源的可观测性框架&#xff0c;由云原生基金会(CNCF)托管。它是 OpenCensus 和 OpenTracing 项目的合并。旨在为所有类型的可观测信号(如跟踪、指标和日志)提供单一标准。 https://opentelemetry.iohttps://www.cncf.io…

微服务Eureka注册中心

目录 一、Eureka的结构和作用 二、搭建eureka-server 三、服务注册 四、服务发现 假如我们的服务提供者user-service部署了多个实例&#xff0c;如图&#xff1a; 存在的问题&#xff1a; order-service在发起远程调用的时候&#xff0c;该如何得知user-service实例的ip地址…

SpringCloud 尚硅谷 微服务简介以及Eureka使用

写在前面 该系列博客仅用于本人学习尚硅谷课程SpringCloud笔记&#xff0c;其中的错误在所难免&#xff0c;如有错误恳请指正。 官方源码地址&#xff1a;https://github.com/zzyybs/atguigu_spirngcloud2020 什么是SpringCloud Spring Cloud是微服务一站式服务解决方案&…

芒果 TV 基于 Flink 的实时数仓建设实践

公司简介&#xff1a;芒果 TV 作为湖南广电旗下互联网视频平台&#xff0c;在“一云多屏&#xff0c;多元一体”的战略指导下&#xff0c;通过内容自制&#xff0c;培植核心竞争力&#xff0c;从独播、独特走向独创&#xff0c;并通过市场化运作完成 A 轮、B 轮融资&#xff0c…

数据库活动监控(DAM)

在当今数据驱动的世界中&#xff0c;组织在保护存储在数据库中的机密数据并确保其完整性方面面临着越来越多的挑战。数据库审计通过提供全面的数据库活动监控方法&#xff0c;在应对这些挑战方面发挥着至关重要的作用。 数据库活动监控&#xff08;Database Activity Monitori…

【Redis】初学Redis

目录 使用Redisyum安装redis启动redis操作redis设置远程连接 Redis路线Redis 使用Redis yum安装redis 使用命令&#xff0c;直接将Redis安装到linux服务器&#xff1a; yum -y install redis启动redis redis-server /etc/redis.conf &操作redis redis-cli设置远程连接…

最新AI创作系统ChatGPT程序源码+详细搭建部署教程+微信公众号版+H5源码/支持GPT4.0+GPT联网提问/支持ai绘画+MJ以图生图+思维导图生成!

使用Nestjs和Vue3框架技术&#xff0c;持续集成AI能力到系统&#xff01; 新增 MJ 官方图片重新生成指令功能同步官方 Vary 指令 单张图片对比加强 Vary(Strong) | Vary(Subtle)同步官方 Zoom 指令 单张图片无限缩放 Zoom out 2x | Zoom out 1.5x新增GPT联网提问功能、手机号注…

集合Collection-List-ArrayList学习

一、集合 集合是数据容器。相较于数组集合具有以下几个特点&#xff1a; 数组一旦创建&#xff0c;长度不可改变。集合的长度会自动扩容。集合具有很多数组没有的功能函数API数组元素的存储特点单一&#xff0c;不同的集合有不同的存储特点。 1. Collection顶层接口 Collect…

Python-OpenCV中的图像处理-图像梯度

Python-OpenCV中的图像处理-图像梯度 图像梯度Sobel 算子和 Scharr 算子Laplacian 算子 图像梯度 图像梯度&#xff0c;图像边界等使用到的函数有&#xff1a; cv2.Sobel()&#xff0c; cv2.Scharr()&#xff0c; cv2.Laplacian() 等原理&#xff1a;梯度简单来说就是求导。Op…

Kotlin反射访问androidx.collection.LruCache类私有变量

Kotlin反射访问androidx.collection.LruCache类私有变量 androidx.collection.LruCache类中定义了一个名为map的LinkedHashMap&#xff0c;map存储了所有LruCache的数据&#xff0c;有时候需要遍历访问该LinkedHashMap&#xff0c;取出里面的值&#xff0c;但是LruCache代码实…

Jenkins+Docker+SpringCloud微服务持续集成

JenkinsDockerSpringCloud微服务持续集成 JenkinsDockerSpringCloud持续集成流程说明SpringCloud微服务源码概述本地运行微服务本地部署微服务 Docker安装和Dockerfile制作微服务镜像Harbor镜像仓库安装及使用在Harbor创建用户和项目上传镜像到Harbor从Harbor下载镜像 微服务持…

SQL SERVER 异地备份到远程共享文件夹异常处理

SQL SERVER 异地备份到远程共享文件夹异常处理 SQL Server 异地备份到远程共享文件夹异常处理 - 灰信网&#xff08;软件开发博客聚合&#xff09; -- 允许配置高级选项 EXEC sp_configure show advanced options, 1 GO -- 重新配置 RECONFIGURE GO -- 启用xp_cmdshell EXEC sp…