Excel大数据量导入导出

github源码 地址(更详细) : https://github.com/alibaba/easyexcel

文档:读Excel(文档已经迁移)

B 站视频 : https://www.bilibili.com/video/BV1Ff4y1U7Qc

一、JAVA解析EXCEL工具EasyExcel

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

64M内存1分钟内读取75M(46W行25列)的Excel

二、EasyExcel的使用

EasyExcel的相关依赖

添加 maven 依赖
<!-- Alibaba Excel 依赖 -->
<!--它提供了高性能的读写功能,特别适合处理大型 Excel 文件 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.3.4</version>
</dependency>
<!-- Apache POI 依赖 -->
<!--poi 是 Apache POI 项目的核心库,提供了读写 Microsoft Office 格式文件的基础功能,包括 .xls 文件 -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>4.1.2</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>4.1.2</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml-schemas</artifactId>
    <version>4.1.2</version>
</dependency>
<!-- SLF4J 和 Logback 依赖 -->
<!-- 日志 -->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.11</version>
</dependency>

三、Excel

创建实体类
@ExcelProperty 注解的 value 属性是一个数组类型 , 设置多个 head 时会自动合并,用于指定Excel表格中该字段的显示名称(起名字)
@NoArgsConstructor @AllArgsConstructor Lombok 库提供的注解
@NoArgsConstructor 生成一个无参构造函数(即没有参数的构造函数)
@AllArgsConstructor 生成一个全参构造函数(即包含类中所有字段的构造函数)
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
public class User {
    @ExcelProperty(value = "用户编号")
    private Integer userId;
    @ExcelProperty(value = "姓名")
    private String userName;
    @ExcelProperty(value = "性别")
    private String gender;
    @ExcelProperty(value = "工资")
    private Double salary;
    @ExcelProperty(value = "入职时间")
    private Date hireDate;
    // lombok 会生成getter/setter方法
}
1.简单写入方法一
    /**
     * 简单写方法一
     */
  @Test
  public void text01(){
      //创建一个Excel文档
      String fileName = "D:\\excel\\user1.xlsx";
     //根据user模板构建数据
      List<User> users = new ArrayList<>();
      User user1 = new User(1,"张三","男",666.66,new Date());
      User user2 = new User(2,"张三","男",666.66,new Date());
      User user3 = new User(3,"张三","男",666.66,new Date());
      User user4 = new User(4,"张三","男",666.66,new Date());
      users.add(user1);
      users.add(user2);
      users.add(user3);
      users.add(user4);
      //向Excel表格中写数据
      EasyExcel.write(fileName,User.class).sheet("用户信息").doWrite(users);
  }
2.简单写入方法二
 /**
     * 简单写方法二
     */
    @Test
    public void text02(){
        //创建一个Excel文档
        String fileName = "D:\\excel\\user2.xlsx";
        //根据user模板构建数据
        List<User> users = new ArrayList<>();
        User user1 = new User(1,"张三","男",666.66,new Date());
        User user2 = new User(2,"张三","男",666.66,new Date());
        User user3 = new User(3,"张三","男",666.66,new Date());
        User user4 = new User(4,"张三","男",666.66,new Date());
        users.add(user1);
        users.add(user2);
        users.add(user3);
        users.add(user4);
        //向Excel表格中写数据
      //创建ExcelWriter对象
        ExcelWriter excelWriter = EasyExcel.write(fileName, User.class).build();
        //创建sheet对象
        WriteSheet writeSheet = EasyExcel.writerSheet("用户信息").build();
        excelWriter.write(users,writeSheet);
        //关闭ExcelWriter对象(一定要关闭,不然会导致内存溢出)
        excelWriter.finish();
    }
 3.排除掉某些不想添加的字段
   /**
     * 排除掉模板中的某几项属性
     */
    @Test
    public void text03(){
        //创建一个Excel文档
        String fileName = "D:\\excel\\user3.xlsx";
        //根据user模板构建数据
        List<User> users = new ArrayList<>();
        User user1 = new User(1,"张三","男",666.66,new Date());
        User user2 = new User(2,"张三","男",666.66,new Date());
        User user3 = new User(3,"张三","男",666.66,new Date());
        User user4 = new User(4,"张三","男",666.66,new Date());
        users.add(user1);
        users.add(user2);
        users.add(user3);
        users.add(user4);
        //设置排除的属性
        Set<String> set = new HashSet<>();
        set.add("salary");
        set.add("hireDate");
        //向Excel表格中写数据
        EasyExcel.write(fileName, User.class).excludeColumnFiledNames(set).sheet("用户信息").doWrite(users);
    }
4.复杂头数据写入
@ExcelProperty 注解的 value 属性是一个数组类型 , 设置多个 head 时会自动合并
/**
 * 复杂头实体类
 */
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
public class ComplexHeadUser {
    @ExcelProperty(value = {"group1", "用户编号"}, index = 0)
    private Integer userId;
    @ExcelProperty(value = {"group1", "姓名"}, index = 1)
    private String userName;
    @ExcelProperty(value = {"group2", "入职时间"}, index = 2)
    private Date hireDate;
}
  /**
     * 复杂头
     */
    @Test
    public void text05(){
        //创建一个Excel文档
        String fileName = "D:\\excel\\user5.xlsx";
        //根据user模板构建数据
        List<ComplexHeadUser> users = new ArrayList<>();
        ComplexHeadUser user1 = new ComplexHeadUser(1,"张三",new Date());
        ComplexHeadUser user2 = new ComplexHeadUser(2,"张三",new Date());
        ComplexHeadUser user3 = new ComplexHeadUser(3,"张三",new Date());
        users.add(user1);
        users.add(user2);
        users.add(user3);
        //向Excel表格中写数据
        EasyExcel.write(fileName, ComplexHeadUser.class).sheet("用户信息").doWrite(users);
    }
//或
@Test
public void testWriteExcel6() {
    String filename = "D:\\study\\user6.xlsx";
    List<ComplexHeadUser> users = new ArrayList<>();
    for (int i = 1; i <= 10; i++) {
        ComplexHeadUser user = ComplexHeadUser.builder()
        .userId(i)
        .userName("大哥" + i)
        .hireDate(new Date())
        .build();
        users.add(user);
    }
    // 向Excel中写入数据
    EasyExcel.write(filename, ComplexHeadUser.class)
    .sheet("用户信息")
    .doWrite(users);
}
处理百万级批量数据
处理百万级批量数据时,性能和内存管理是关键问题。 EasyExcel 提供了一些优化策略来处理大规模数据,包括分页读取和分批写入。下面是一些常用的优化技巧:
1. 分批写入
对于写操作,可以使用 EasyExcel 的分批写入功能,这样可以避免一次性加载大量数据导致的内存溢 出问题。
假设您有一个 User 类,定义如下:
/**
 * 创建User类模板,通过User类模板向Excel表格中写数据
 *  @ExcelProperty这个注解用于指定Excel表格中该字段的显示名称(起名字)
 */
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
public class User {

        @ExcelProperty(value = "用户编号")
        private Integer userId;
        @ExcelProperty(value = "姓名")
        private String userName;
        @ExcelProperty(value = "性别")
        private String gender;
        @ExcelProperty(value = "工资")
        private Double salary;
        @ExcelProperty(value = "入职时间")
        private Date hireDate;
        // lombok 会生成getter/setter方法

}
 /**
     * 处理百万级批量数据
     */
    @Test
    public void text06(){
        //创建一个Excel文档
        String fileName = "D:\\excel\\user6.xlsx";
        // 确保目录存在
        File directory = new File("D:\\excel");
        if (!directory.exists()) {
            directory.mkdirs();
        }
        // 分批大小
        int batchSize = 10000;
        // 创建 ExcelWriter 对象
        ExcelWriter excelWriter = EasyExcel.write(fileName, User.class).build();
        for (List<User> data : dataList(batchSize)) {
            // 创建 sheet 对象
            WriteSheet writeSheet = EasyExcel.writerSheet("用户信息").build();
            // 写数据
            excelWriter.write(data, writeSheet);
        }
        excelWriter.finish();
        
        System.out.println("Excel文件已成功创建!");
    }
    private List<List<User>> dataList(int batchSize) {
        List<List<User>> allData = new ArrayList<>();
        int totalRecords = 1000000; // 假设有 100 万条记录
        for (int i = 0; i < totalRecords; i += batchSize) {
            List<User> batch = new ArrayList<>();
            for (int j = 0; j < batchSize && i + j < totalRecords; j++) {
                User user = User.builder()
                        .userId(i + j + 1)
                        .userName("用户" + (i + j + 1))
                        .gender(j % 2 == 0 ? "男" : "女")
                        .salary(10000.0 + (i + j) * 1000.0)
                        .hireDate(new Date())
                        .build();
                batch.add(user);
            }
            allData.add(batch);
        }
        return allData;
    }
解释
1. 分批大小 batchSize 定义了每批写入的数据量。可以根据实际需求调整这个值。
2. 创建 ExcelWriter 对象 :使用 EasyExcel.write 方法创建 ExcelWriter 对象,并指定文件路径和数据模型类。
3. 分批写入数据 dataList 方法生成分批的数据列表,每次调用 doWrite 方法写入一批数据。

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

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

相关文章

Coze(扣子)+ Deepseek:多Agents智能体协作开发新范式

前言 在当今数字化浪潮中&#xff0c;人工智能&#xff08;AI&#xff09;技术的迅猛发展正深刻改变着我们的生活和工作方式。从智能语音助手到自动化流程机器人&#xff0c;AI 的应用无处不在&#xff0c;为我们提供了更加便捷、高效的服务。然而&#xff0c;对于非专业人士来…

Spring AI -使用Spring快速开发ChatGPT应用

前言 Spring在Java生态中一直占据大半江山。最近我发现Spring社区推出了一个Spring AI项目&#xff0c;目前该项目还属于Spring实验性项目&#xff0c;但是我们可以通过该项目&#xff0c;可以非常快速的开发出GPT对话应用。 本篇文章将会对SpringAI进行简单的介绍和使用&#…

Unity项目接入xLua的一种流程

1. 导入xlua 首先导入xlua&#xff0c;这个不用多说 2. 编写C#和Lua交互脚本 基础版本&#xff0c;即xlua自带的版本 using System.Collections; using System.Collections.Generic; using UnityEngine; using XLua; using System; using System.IO;[Serializable] public…

LM Studio 部署本地大语言模型

一、下载安装 1.搜索&#xff1a;lm studio LM Studio - Discover, download, and run local LLMs 2.下载 3.安装 4.更改成中文 二、下载模型(软件内下载) 1.选择使用代理&#xff0c;否则无法下载 2.更改模型下载目录 默认下载位置 C:\Users\用户名\.lmstudio\models 3.搜…

route 与 router 之间的差别

简述&#xff1a; router&#xff1a;主要用于处理一些动作&#xff0c; route&#xff1a;主要获得或处理一些数据&#xff0c;比如地址、参数等 例&#xff1a; videoInfo1.vue&#xff1a; <template><div class"video-info"><h3>二级组件…

DeepSeek-V2 论文解读:混合专家架构的新突破

论文链接&#xff1a;DeepSeek-V2: A Strong, Economical, and Efficient Mixture-of-Experts Language Model 目录 一、引言二、模型架构&#xff08;一&#xff09;多头部潜在注意力&#xff08;MLA&#xff09;&#xff1a;重塑推理效率&#xff08;二&#xff09;DeepSeekM…

Android修行手册-五种比较图片相似或相同

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资源分享(网站、工具、素材…

力扣--链表

相交链表 法一&#xff1a; 把A链表的节点都存HashSet里&#xff0c;遍历B链表找相同的节点 法二&#xff1a; 把A、B指针都移到末尾&#xff0c;再同时往回走&#xff0c;每次往回走都比较 当前节点的下一节点&#xff08;a.next b.next ?)是否相同&#xff0c;当不相同…

只需两步,使用ollama即可在本地部署DeepSeek等常见的AI大模型

只需两步&#xff0c;使用ollama即可在本地部署DeepSeek等常见的AI大模型 1.下载ollama,进入ollama官网即可将ollama下载到本地&#xff0c;之后按照提示安装ollama。 https://ollama.com/download/windows 2.安装大模型 进入ollama官网模型页面&#xff0c;找到所需的模型及版…

Qt修仙之路2-1 仿QQ登入 法宝初成

widget.cpp #include "widget.h" #include<QDebug> //实现槽函数 void Widget::login1() {QString userusername_input->text();QString passpassword_input->text();//如果不勾选无法登入if(!check->isChecked()){qDebug()<<"xxx"&…

大模型deepseek-r1 本地Open WebUI部署详解

一、Open WebUI简介 Open WebUI是一个用户友好的Web界面&#xff0c;专为本地大语言模型&#xff08;LLMs&#xff09;设计。它支持多种模型&#xff0c;包括Ollama和OpenAI兼容的API&#xff0c;并允许用户通过图形界面轻松调试和调用模型。Open WebUI的功能丰富&#xff0c;…

免费windows pdf编辑工具Epdf

Epdf&#xff08;完全免费&#xff09; 作者&#xff1a;不染心 时间&#xff1a;2025/2/6 Github: https://github.com/dog-tired/Epdf Epdf Epdf 是一款使用 Rust 编写的 PDF 编辑器&#xff0c;目前仍在开发中。它提供了一系列实用的命令行选项&#xff0c;方便用户对 PDF …

大模型训练(7):集合通信与通信原语

0 背景 分布式训练过程中设计到许多通信上的操作&#xff0c; 每个操作有其不同的术语并且有所区别&#xff0c;这里将其用简单的例子和描述总结一下&#xff0c;方便理解。 集合通信&#xff08;Collective Communications&#xff09;是一个进程组的所有进程都参与的全局通…

线程上下文-ThreadLocal原理

ThreadLocal主要作用&#xff1a;为每个线程提供独立的变量副本&#xff0c;实现线程间的数据隔离&#xff0c;从而避免多线程环境下的资源共享冲突。 原理 ThreadLocal有个内部类 ThreadLocalMap&#xff0c;顾名思义是个Map结构&#xff1a;key为 ThreadLocal实例&#xff0…

第31周:文献阅读

目录 摘要 Abstract 文献阅读 问题引入 研究背景 研究动机 创新点 动态预训练方法&#xff08;DynPT&#xff09; 深度循环神经网络&#xff08;DRNN&#xff09; 传感器选择 方法论 时间序列的动态预训练 异构传感器数据的DRNN 基于稀疏度的传感器过滤 实验研…

Yolo图片标注的一些问题

1.标注工具的选择 在img.net和瑞芯微的双重加持下&#xff0c;现在的计算机视觉识别已经在各行业快速推进。进行自行标注时&#xff0c;首先遇到的问题就是标注工具的选择问题&#xff0c;标注工具不需要自己手工完成——也没有必要。类似这样的通用需求&#xff0c;交给专业…

排错 -- 用React.js,Solidity,智能合约构建最新区块链应用

真枪实弹:第一个Web3项目【上集】用React.js,Solidity,智能合约构建最新区块链应用详细教程 构建web跟随b站教程中遇到了很多错误&#xff0c;从今天开始构建完整的应用&#xff0c;在此记录一些排错。 问题情况1&#xff1a;跟随视频后无Src文件 问题情况1解决方法&#xff1…

杂记:下载了BootLoader和APP到程序中无反应

杂记&#xff1a;下载了BootLoader和APP到程序中无反应 是因为采用了printf输出打印。占用了大量堆栈导致程序运行异常。并且没有打开Use MicroLIB库的话会导致无法启动程序。 解决办法&#xff1a; 1、关闭printf打印。 2、如果不关闭printf打印&#xff0c;则加大Heap_Size…

Unet 改进:引入残差模块ResidualBlock

目录 1. ResidualBlock 2. UNet 引入残差模块 Tips:融入模块后的网络经过测试,可以直接使用,设置好输入和输出的图片维度即可 1. ResidualBlock 残差连接(Residual Connection)是深度学习中一种重要的技术,主要用于解决深层网络训练中的梯度消失和网络退化问题。它首次…

对接DeepSeek

其实&#xff0c;整个对接过程很简单&#xff0c;就四步&#xff0c;获取key&#xff0c;找到接口文档&#xff0c;接口测试&#xff0c;代码对接。 获取 KEY https://platform.deepseek.com/transactions 直接付款就是了&#xff08;现在官网暂停充值2025年2月7日&#xff0…