EasyExcel使用,实体导入导出

简介

Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在一个严重的问题就是非常的耗内存,poi有一套SAX模式的API可以一定程度的解决一些内存溢出的问题,但POI还是有一些缺陷,比如07版Excel解压缩以及解压后存储都是在内存中完成的,内存消耗依然很大。
easyexcel重写了poi对07版Excel的解析,一个3M的excel用POI sax解析依然需要100M左右内存,改用easyexcel可以降低到几M,并且再大的excel也不会出现内存溢出;03版依赖POI的sax模式,在上层做了模型转换的封装,让使用者更加简单方便

网站

  • 官方网站:EasyExcel官方文档 - 基于Java的Excel处理工具 | Easy Excel
  • github地址:GitHub - alibaba/easyexcel: 快速、简洁、解决大文件内存溢出的java处理Excel工具
  • gitee地址:easyexcel: 快速、简洁、解决大文件内存溢出的java处理Excel工具。

16M内存23秒读取75M(46W行25列)的Excel(3.2.1+版本)

当然还有极速模式能更快,但是内存占用会在100M多一点 

img

快速开始​

读Excel​

DEMO代码地址:https://github.com/alibaba/easyexcel/blob/master/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/demo/read/ReadTest.java

    /**
     * 最简单的读
     * <p>1. 创建excel对应的实体对象 参照{@link DemoData}
     * <p>2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoDataListener}
     * <p>3. 直接读即可
     */
    @Test
    public void simpleRead() {
        String fileName = TestFileUtil.getPath() + "demo" + File.separator + "demo.xlsx";
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
        EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();
    }

写Excel​

DEMO代码地址:https://github.com/alibaba/easyexcel/blob/master/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/demo/write/WriteTest.java

    /**
     * 最简单的写
     * <p>1. 创建excel对应的实体对象 参照{@link com.alibaba.easyexcel.test.demo.write.DemoData}
     * <p>2. 直接写即可
     */
    @Test
    public void simpleWrite() {
        String fileName = TestFileUtil.getPath() + "write" + System.currentTimeMillis() + ".xlsx";
        // 这里 需要指定写用哪个class去读,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
        // 如果这里想使用03 则 传入excelType参数即可
        EasyExcel.write(fileName, DemoData.class).sheet("模板").doWrite(data());
    }

web上传、下载​

DEMO代码地址:https://github.com/alibaba/easyexcel/blob/master/easyexcel-test/src/test/java/com/alibaba/easyexcel/test/demo/web/WebTest.java

   /**
     * 文件下载(失败了会返回一个有部分数据的Excel)
     * <p>
     * 1. 创建excel对应的实体对象 参照{@link DownloadData}
     * <p>
     * 2. 设置返回的 参数
     * <p>
     * 3. 直接写,这里注意,finish的时候会自动关闭OutputStream,当然你外面再关闭流问题不大
     */
    @GetMapping("download")
    public void download(HttpServletResponse response) throws IOException {
        // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), DownloadData.class).sheet("模板").doWrite(data());
    }

    /**
     * 文件上传
     * <p>1. 创建excel对应的实体对象 参照{@link UploadData}
     * <p>2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器,参照{@link UploadDataListener}
     * <p>3. 直接读即可
     */
    @PostMapping("upload")
    @ResponseBody
    public String upload(MultipartFile file) throws IOException {
        EasyExcel.read(file.getInputStream(), UploadData.class, new UploadDataListener(uploadDAO)).sheet().doRead();
        return "success";

实体中的使用

1.集成easyExcel

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

2定义导入导出实体:

实体与excel列的映射
创建实体类使用 @ExcelProperty、@ExcelIgnore 等注解标识导出列;
@ExcelIgnore 表示忽略此字段
@ExcelProperty 用于标识列 value属性设置列的名称,index属性设置设置列的序号 从 0 开始
 

@Data
@NoArgsConstructor
@AllArgsConstructor
public class GamesExcelVO {

    /**
     *  @description: 使用@ExcelIgnore注解忽略此字段
     **/
    @ExcelIgnore
    private String id;

    /**
     * @description: 使用@ExcelProperty标识列
     * value属性设置列的名称,index属性设置设置列的序号 从  0 开始
     **/
    @ExcelProperty(value = "名称",index = 0)
    private String name;

    @ExcelProperty(value = "类型",index = 1)
    private String type;

    @ExcelProperty(value = "价格",index = 2)
    private BigDecimal price;


}

导出excel的代码:

@GetMapping("/excelExport")
    public void excelExport(HttpServletResponse response) throws IOException {
        try{
            //导出数据(这里使用假数据用来测试)
            List<GamesExcelVO> list = Arrays.asList(
                    new GamesExcelVO(
                            UUID.randomUUID().toString().replace("-", ""),
                            "荒野大镖客:救赎2",
                            "开放世界、剧情",
                            new BigDecimal("299.5")
                    ),
                    new GamesExcelVO(
                            UUID.randomUUID().toString().replace("-", ""),
                            "上古卷轴5:天际",
                            "开放世界、冒险",
                            new BigDecimal("199.5")
                    ),
                    new GamesExcelVO(
                            UUID.randomUUID().toString().replace("-", ""),
                            "塞尔达传说:王国之泪",
                            "开放世界、冒险",
                            new BigDecimal("399.5")
                    )
            );
            //使用easyExcel导出表格
            EasyExcel.write(response.getOutputStream(),GamesExcelVO.class)
                    .sheet("游戏价格") //sheet页名称
                    .doWrite(list); //将要导出的数据
        }catch (Exception e){
            log.error("导出失败",e);
        }finally {
            //关闭流
            response.flushBuffer();
        }
    }

导出的文件:

3.Excel复杂表头导出

可将@ExcelProperty注解的value属性指定为一个数组来实现复杂表头的导出

与实体的映射

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ClassesExcelVO {


    /**
     * @description: 可将@ExcelProperty注解的value属性指定为一个数组来实现复杂表头的导出
     **/
    @ExcelProperty(value = {"1级表头","2"},index = 0)
    private Integer title1;

    @ExcelProperty(value = {"1级表头","3"},index = 1)
    private Integer title2;

    @ExcelProperty(value = {"1级表头","4"},index = 2)
    private Integer title3;

    @ExcelProperty(value = {"1级表头","5"},index = 3)
    private Integer title4;

    @ExcelProperty(value = {"1级表头","2级表头","6"},index = 4)
    private Integer title5;

    @ExcelProperty(value = {"1级表头","2级表头","7"},index = 5)
    private Integer title6;

    @ExcelProperty(value = {"1级表头","8"},index = 6)
    private Integer title7;

    @ExcelProperty(value = {"1级表头","9"},index = 7)
    private Integer title8;

}

导出代码

/**
     * @description: easyExcel复杂表头导出
     * @author: Vinci
     * @date: 2023/8/18 13:04
     **/
    @GetMapping("/complexExcelExport")
    public void complexExcelExport(HttpServletResponse response) throws IOException {
        try{
            //与简单easyExcel导出的方式一样,仅导出对象方式发生变化
            //创建用于测试的假数据
            ArrayList<ClassesExcelVO> list = new ArrayList<>();
            for (int i = 0; i < 1000; i++) {
                list.add(new ClassesExcelVO(i,i,i,i,i,i,i,i));
            }
            //使用easyExcel导出表格
            EasyExcel.write(response.getOutputStream(),ClassesExcelVO.class)
                    .sheet("复杂表头导出测试") //sheet页名称
                    .doWrite(list); //将要导出的数据
        }catch (Exception e){
            log.error("导出失败",e);
        }finally {
            //关闭流
            response.flushBuffer();
        }
    }

导出的文件:

4.Excel导入

我们使用 标题3 excel复杂表头导出的excel文件来进行测试,代码如下:

@GetMapping("/excelImport")
    public void excelImport(@RequestParam("file") MultipartFile file){
        //使用刚刚的复杂导入模板来测试easyExcel导入
        try {
            List<ClassesExcelVO> datas = EasyExcel.read(file.getInputStream(), ClassesExcelVO.class, null)
                    .excelType(ExcelTypeEnum.XLSX) //可指定文件的导入类型
                    .sheet(0)//读取sheet页码,读取多个sheet页可利用循环来进行读取,页码从0开始
                    .headRowNumber(4) //设置表头,可理解为 读取行 - 1
                    .autoTrim(false) //读取数据时忽略空格,默认忽略
                    .doReadSync();
            //读取到的数据
            datas.forEach(System.out::println);
        } catch (Exception e) {
            log.error("导入失败:",e);
        }
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/363782.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

@JsonProperty(“xx“)的使用

JsonProperty(“xx”) 指定JSON字段的名称 常见的场景 1、第三方调用本系统&#xff0c;参数接收不到 &#xff0c;没有使用驼峰命名&#xff0c;或者传参格式不一致问题 2、前后端调试&#xff0c;接收不到个别参数 遇到的场景描述&#xff1a; 1&#xff0c;项目提供ope…

Vue中的指令修饰符计算属性和方法的区别

一、指令修饰符 1.什么是指令修饰符&#xff1f; 所谓指令修饰符就是通过“.”指明一些指令后缀 不同的后缀封装了不同的处理操作 —> 简化代码 2.按键修饰符 keyup.enter —>当点击enter键的时候才触发 代码演示&#xff1a; <!DOCTYPE html> <html lang…

【ChatGPT】文本向量化与余弦相似度:揭开文本处理的神秘面纱(5)

1、引言 在这个数字化的时代&#xff0c;我们每天都会面对大量的文本信息&#xff0c;从社交媒体到新闻报道&#xff0c;文本无处不在。但是&#xff0c;计算机要如何理解和处理这些文字呢&#xff1f;本文将为大家揭开其中的一些奥秘&#xff0c;详细解释文本向量化的概念&am…

C++ hash—unordered_mapset

目录 一. unordered系列关联式容器 1、文档说明 2、接口说明 1. 构造 2. 容量 3. 迭代器 4. 元素访问 5. 查询 6. 修改 7. 桶操作 8. 测试 二、unordered_set 1、​​​​​​​文档说明 2、接口说明 1. 构造 2. 容量 3. 迭代器 4. 元素访问 5. 插入和删除…

【脑电信号处理与特征提取】P7-贾会宾:基于EEG/MEG信号的大尺度脑功能网络分析

基于EEG/MEG信号的大尺度脑功能网络分析 Q: 什么是基于EEG/MEG信号的大尺度脑功能网络分析&#xff1f; A: 基于脑电图&#xff08;EEG&#xff09;或脑磁图&#xff08;MEG&#xff09;信号的大尺度脑功能网络分析是一种研究大脑活动的方法&#xff0c;旨在探索脑区之间的功能…

Win11系统连接带HDMI接口的显示器后,电脑没有声音如何调试

解决这个问题的方法很简单&#xff0c;没有那么复杂。之所以使用HDMI接口连接了显示器后没声音&#xff0c;原因就是HDMI接口是包含音频视频两种信号的接口。当电脑的HDMI接口被使用时&#xff0c;系统就会默认从HDMI设备输出声音信号了&#xff0c;而此时如果HDMI设备没有声音…

vivado里的LUT、LUTRAM、FF、BRAM、DSP、IO、BUFG、MMCM资源介绍

vivado里的LUT、LUTRAM、FF、BRAM、DSP、IO、BUFG、MMCM资源介绍 提示&#xff1a;以下是本篇文章正文内容&#xff0c;写文章实属不易&#xff0c;希望能帮助到各位&#xff0c;转载请附上链接。 vivado实现电路用到的资源类型 LUT&#xff08;Look-Up Table&#xff09;&am…

文心一言APP上线新功能,一张照片、三句话即可生成专属数字分身

只需一张照片、录制三句话&#xff0c;就能拥有一个自己的数字分身&#xff1f;这不是科幻电影&#xff0c;而是文心一言APP上线的新功能 - 数字分身。 目前&#xff0c;文心一言APP正在内测数字分身新功能&#xff0c;明天起&#xff0c;iOS和Android用户升级新版本后&#xf…

给定长度为n的递增数组a,进行n - 1次操作:求当前a数组的差分数组,然后使a为差分数组,继续进行操作。求最后数组的元素是什么

题目 思路: #include <bits/stdc++.h> using namespace std; #define int long long typedef long long ll; #define pb push_back #define lson p << 1 #define rson p << 1 | 1 #define fi first #define se second const int maxn = 1e6 + 5, maxm = 5e…

java之基础知识、零碎知识

MENU java学习路程之篇一、知识点、path环境变量、计算机发展史、数据的存储和运算、人机交互、计算机语言java学习路程之篇二、知识点、JAVA背景介绍、配置JAVA_HOME、跨平台、JVM、JRE、JDKjava学习路程之篇三、知识点、类、模块、项目、操作、下载、安装、IDEA、开发工具jav…

Vue-49、Vue技术实现动画效果

1、首先&#xff0c;在Vue项目中的src/components文件夹下创建一个名为AnimatedBox.vue的文件。 2、编辑AnimatedBox.vue文件&#xff0c;添加以下代码&#xff1a; <template><div class"animated-box" click"toggle"><transition name&q…

Excel没有内置统计字数功能,但可以用一些变通的方法

是否需要计算Excel工作簿中某个单元格或单元格范围内的单词数? 出于多种原因,你可能需要计算文本数据中的字数。也许你有逗号分隔的列表,需要计算每个列表中的项目数。 不幸的是,Excel没有内置的单词计数方法。但是有一些聪明的方法可以得到你需要的结果。 这篇文章将向…

【Docker】【深度学习算法】在Docker中使用gunicorn启动多个并行算法服务,优化算法服务:从单进程到并行化

文章目录 优化算法服务&#xff1a;从单进程到并行化单个服务架构多并行服务架构Docker化并指定并行服务数量 扩展知识 优化算法服务&#xff1a;从单进程到并行化 在实际应用中&#xff0c;单个算法服务的并发能力可能无法满足需求。为了提高性能和并发处理能力&#xff0c;我…

OpenHarmony—开发及引用静态共享包(API 9)

HAR(Harmony Archive&#xff09;是静态共享包&#xff0c;可以包含代码、C库、资源和配置文件。通过HAR可以实现多个模块或多个工程共享ArkUI组件、资源等相关代码。HAR不同于HAP&#xff0c;不能独立安装运行在设备上&#xff0c;只能作为应用模块的依赖项被引用。 接下来&a…

Matlab图像模拟加噪——高斯噪声、椒盐噪声、泊松噪声、乘性噪声、均匀噪声、指数噪声

1.高斯噪声 (1)通过均值和方差来产生 Jimnoise(I, gaussian, 0, 0.01);%高斯噪声&#xff0c;均值为0&#xff0c;方差为0.01(2)通过位置信息来产生 Iim2double(I); Vzeros(size(I)); %建立矩阵V for i1:size(V, 1)V(i,:)0.02*i/size(V,1); end Jimnoise(I, localvar, V); …

Android Jetpack Compose之底部导航栏的实现

目录 1.概述2. 效果展示3. 代码实现3.1 定义底部导航栏的tab项3.2 整体页面架构搭建3.3 底部导航栏的实现3.4 所有代码 4.总结 1.概述 写过一段Android jetpack compose 界面的小伙伴应该都用过Compose的脚手架Scaffold&#xff0c;利用它我们可以很快的实现一个现代APP的主流…

android开发---简单购物商城(JAVA) (一)

包括&#xff1a;商品展示&#xff0c;商品详情&#xff0c;购物车&#xff0c;删除&#xff0c;一键清除&#xff0c;返回 运用sqllist 另外因为一篇写不下 继续可看 源码二 下面是目录 运行样子 下面是源码 AndroidManifest.xml <?xml version"1.0" e…

路由重定向和别名

聚沙成塔每天进步一点点 本文内容 ⭐ 专栏简介1. 路由重定向实例场景&#xff1a;路由重定向的应用场景&#xff1a; 2. 路由别名实例场景&#xff1a;路由别名的应用场景&#xff1a; ⭐ 写在最后 ⭐ 专栏简介 Vue学习之旅的奇妙世界 欢迎大家来到 Vue 技能树参考资料专栏&…

(1)从 AGP 4.1.2 升级到 7.5.1 我遇到了什么问题

AGP 升级问题 &#xff08;1&#xff09;Could not get unknown property ‘project’ for settings&#xff0c;on project.buildscript 问题 Could not get unknown property ‘project’ for settings ‘AGP1’ of type org.gradle.initialization.DefaultSettings. agp4 …

数组与字符串深度巩固

经过再三思考觉得今天就写一篇关于数组与字符串相关的文章吧&#xff01;其中字符串主要通过练习来巩固知识亦或是获得新知识。好接下来将进行我们的学习时刻了。 首先我们来思考一个问题&#xff0c;你真的了解数组的数组名吗&#xff1f;数组名真的就单单一个名字而已吗&…