EasyExcel 快速入门

news2024/12/23 22:27:21

目录

一、 EasyExcel简介 

官网链接:

代码链接:

二、 EasyExcel快速上手 

引入依赖:

设置Excel相关注解

编写对应的监听类:

简单写入数据: 

简单读取数据:

不需要使用监听器:

需要使用监听器:

三、EasyExcel进阶操作

批量写入数据:

 批量写入不同的sheet的不同对象:

填充数据:

四、实战EasyExcel(Excel表格的导入和导出)


一、 EasyExcel简介 

EasyExcel 是一个基于 Java 的简单、高效的 Excel 处理工具。它由阿里巴巴开源,主要解决了在 Java 应用中处理 Excel 文件时内存溢出的问题。

EasyExcel 和 Apache POI 都是 Java 生态中处理 Excel 文件的库,但它们在设计理念、性能、使用复杂度等方面有所不同。以下是 EasyExcel 相比于 Apache POI 的主要优势和一些差异:

性能:

  • 内存占用:EasyExcel 是为低内存占用而设计的。在处理大型 Excel 文件时,EasyExcel 可以实现按行读取和写入,而不需要将整个文件加载到内存中,从而显著降低内存使用。而 Apache POI 在处理大型文件时,可能会因为将整个文件加载到内存而导致内存溢出。

  • 处理速度:EasyExcel 对读取和写入操作进行了优化,通常在处理速度上比 Apache POI 更快。

使用复杂度:

  • API 设计:EasyExcel 提供了更为简洁的 API,使得读取和写入操作更加直观和方便。而 Apache POI 提供了丰富的 API,但这也使得它的使用相对复杂。

  • 模型映射:EasyExcel 支持使用注解直接将 Excel 的列映射到 Java 实体的字段上,简化了数据转换的过程。Apache POI 需要手动处理每一行和每一列的数据。

官网链接:

EasyExcel官方文档 - 基于Java的Excel处理工具 | Easy Excel 官网 (alibaba.com)

代码链接:

 https://gitee.com/seniorGitee/easy-excel

二、 EasyExcel快速上手 

引入依赖:

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

设置Excel相关注解

 以员工实体类为例:

@ExcelIgnore设置忽略导出的字段信息

@ExcelProperty设置导出的字段名,导出的字段默认按照顺序从0开始排序,如果想指定导出字段的在第几列的话,可以设置对应的index,index的值:字段所在列数-1,类似数组下标索引

@DateTimeFormat定义日期格式

@ColumnWidth设置字段宽度

其实@ExcelProperty还有很多复杂的操作,具体请查看官网文档,这里只教会大家快速入门使用


@Data
@AllArgsConstructor
@NoArgsConstructor
public class Employee implements Serializable {

    /**
     * 忽略这个字段
     */
    @ExcelIgnore
    private Long id;

    @ExcelProperty("员工名")
    private String name;

    @ExcelProperty("员工年龄")
    private Integer age;

    @ExcelProperty(value = "员工工资",index = 3)
    private BigDecimal salary;

    @ColumnWidth(15)
    @DateTimeFormat("yyyy年MM月dd日")
    @ExcelProperty(value = "入职时间",index = 2)
    private Date entryTime;

}

编写对应的监听类:

编写Employee对应的监听类EmployeeListener

注意:有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去


@Slf4j
public class EmployeeListener implements ReadListener<Employee> {

    /**
     * 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 100;
    /**
     * 缓存的数据
     */
    private List<Employee> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

    private IEmployeeService employeeService;


    public EmployeeListener(IEmployeeService employeeService){
        this.employeeService = employeeService;
    }

    //每一条数据解析都会进行调用
    @Override
    public void invoke(Employee employee, AnalysisContext analysisContext) {
        log.info("解析到一条数据:{}", JSON.toJSONString(employee));
        cachedDataList.add(employee);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (cachedDataList.size() >= BATCH_COUNT) {
            saveData();
            // 存储完成清理 list
            cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }

    //所有的数据解析完后进行调用
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        log.info("所有数据解析完成!");
    }

    /**
     * 加上存储数据库
     */
    private void saveData() {
        log.info("{}条数据,开始存储数据库!", cachedDataList.size());
        employeeService.save(cachedDataList);
        log.info("存储数据库成功!");
    }
}

简单写入数据: 

注意:simpleWrite在数据量不大的情况下可以使用(5000以内,具体也要看实际情况),数据量大参照 重复多次写入(可以查看EasyExcel进阶操作:批量写入数据)

@SpringBootTest
class EasyExcelApplicationTests {

    @Autowired
    private IEmployeeService employeeService;

    @Test
    void simpleWrite() {
        String fileName = ".\\src\\main\\resources\\static\\"+"simpleWrite" + System.currentTimeMillis() + ".xlsx";
        EasyExcel.write(fileName, Employee.class).sheet("模板").doWrite(employeeService.getData());
    }

}

在resources/static中可以看到导出数据的Excel表格 

简单读取数据:

读取数据有两种方式,分别是使用监听器和不使用监听器的方式进行读取数据

不需要使用监听器:

这里的fileName需要修改成读取Excel文件对应的路径

@SpringBootTest
@Slf4j
class EasyExcelApplicationTests {

    @Autowired
    private IEmployeeService employeeService;

    @Test
    void simpleRead(){
        String fileName = ".\\src\\main\\resources\\static\\"+"simpleWrite1726145097517.xlsx";
        // 这里默认每次会读取100条数据 然后返回过来 直接调用使用数据就行
        // 具体需要返回多少行可以在`PageReadListener`的构造函数设置
        EasyExcel.read(fileName, Employee.class, new PageReadListener<Employee>(employeeList -> {
            for (Employee employee : employeeList) {
                log.info("读取到一条数据{}", JSON.toJSONString(employee));
            }
        })).sheet().doRead();
    }

}

控制台输出的结果:

需要使用监听器:

这里的EmployListener对一个之前写的监听类,读取Excel文件的数据并将数据存储到数据库中

@SpringBootTest
@Slf4j
class EasyExcelApplicationTests {

    @Autowired
    private IEmployeeService employeeService;

    @Test
    void simpleReadByListener(){
        String fileName = ".\\src\\main\\resources\\static\\"+"simpleWrite1726145097517.xlsx";
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
        EasyExcel.read(fileName, Employee.class, new EmployeeListener(employeeService)).sheet().doRead();
    }
    
}

控制台输出的结果:

三、EasyExcel进阶操作

批量写入数据:

批量写入通一个sheet同一对象:


@SpringBootTest
@Slf4j
class EasyExcelApplicationTests {

    @Autowired
    private IEmployeeService employeeService;

    @Test
    void batchWriteOneSheep(){
        // 方法1: 如果写到同一个sheet
        String fileName = ".\\src\\main\\resources\\static\\"+"simpleWrite" + System.currentTimeMillis() + ".xlsx";
        // 这里 需要指定写用哪个class去写
        try (ExcelWriter excelWriter = EasyExcel.write(fileName, Employee.class).build()) {
            // 这里注意 如果同一个sheet只要创建一次
            WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();

            Long total = employeeService.total();
            Integer pageSize = 10;
            // 实际使用时根据数据库分页的总的页数来,这里批量插入,每次插入10条数据
            for (int i = 1; i <= Math.ceil((double) total /pageSize); i++) {
                // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
                PageBean pageBean = employeeService.pageEmployee(i,pageSize);
                excelWriter.write(pageBean.getRows(), writeSheet);
            }
        }
    }

}

批量写入不同的sheet同一对象:


@SpringBootTest
@Slf4j
class EasyExcelApplicationTests {

    @Autowired
    private IEmployeeService employeeService;

    @Test
    void batchWriteDifferentSheep(){
        // 方法2: 如果写到不同的sheet 同一个对象
        String fileName = ".\\src\\main\\resources\\static\\"+"simpleWrite" + System.currentTimeMillis() + ".xlsx";
        // 这里 指定文件
        try (ExcelWriter excelWriter = EasyExcel.write(fileName, Employee.class).build()) {
            Long total = employeeService.total();
            Integer pageSize = 10;
            // 实际使用时根据数据库分页的总的页数来。这里最终会将数据写到多个sheet里面
            for (int i = 1; i <= Math.ceil((double) total /pageSize); i++) {
                // 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样
                WriteSheet writeSheet = EasyExcel.writerSheet(i, "员工表" + i).build();
                // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
                PageBean pageBean = employeeService.pageEmployee(i,pageSize);
                excelWriter.write(pageBean.getRows(), writeSheet);
            }
        }
    }

}

 批量写入不同的sheet的不同对象:


@SpringBootTest
@Slf4j
class EasyExcelApplicationTests {

    @Autowired
    private IEmployeeService employeeService;

    @Test
    void batchWriteDifferentSheepAndObject(){
        // 方法3 如果写到不同的sheet 不同的对象
        String fileName = ".\\src\\main\\resources\\static\\"+"simpleWrite" + System.currentTimeMillis() + ".xlsx";
        // 这里 指定文件
        try (ExcelWriter excelWriter = EasyExcel.write(fileName).build()) {

            Long total = employeeService.total();
            Integer pageSize = 10;
            // 实际使用时根据数据库分页的总的页数来。这里最终会将数据写到多个sheet里面
            for (int i = 1; i <= Math.ceil((double) total /pageSize); i++) {
                // 每次都要创建writeSheet 这里注意必须指定sheetNo 而且sheetName必须不一样。这里注意Employee.class 可以每次都变,我这里为了方便 所以用的同一个class
                // 实际上可以一直变
                WriteSheet writeSheet = EasyExcel.writerSheet(i, "模版表" + i).head(Employee.class).build();
                // 分页去数据库查询数据 这里可以去数据库查询每一页的数据
                PageBean pageBean = employeeService.pageEmployee(i,pageSize);
                excelWriter.write(pageBean.getRows(), writeSheet);
            }
        }
    }

}

填充数据:

例如我们想将员工表填充到如下的Excel表格中

先对Excel表格模版填写占位符

执行填充Excel表格的代码


@SpringBootTest
@Slf4j
class EasyExcelApplicationTests {

    @Autowired
    private IEmployeeService employeeService;


    @Test
    void fillTemplateData(){
        //需要填充模版
        String templateFileName = ".\\src\\main\\resources\\static\\"+"fillTemplate.xlsx";

        //模版填充后的文件
        String fileName = ".\\src\\main\\resources\\static\\"+"fillTemplateComplete.xlsx";
        // 这里 会填充到第一个sheet, 然后文件流会自动关闭
        EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(employeeService.getData());
    }

}

四、实战EasyExcel(Excel表格的导入和导出)

web中进行Excel表格数据的导入和导出,以员工表为例:

@RestController
@RequestMapping("/employee")
public class EmployeeController {

    @Autowired
    private IEmployeeService employeeService;

    @PostMapping("/upload")
    public void upload(MultipartFile file,HttpServletResponse response) throws IOException{
        long begin = System.currentTimeMillis();
        EasyExcel.read(file.getInputStream(), Employee.class, new EmployeeListener(employeeService)).sheet().doRead();
        long end = System.currentTimeMillis();
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().println("导出数据成功,耗时:"+(end-begin));

    }

    @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("导出的Excel数据", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), Employee.class).sheet("员工表").doWrite(employeeService.getData());
    }

}

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

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

相关文章

U盘一打开就让格式化怎么办?教你快速解决方法

在日常生活和工作中&#xff0c;U盘已成为我们存储和传输数据的重要工具。然而&#xff0c;有时我们会遇到一个令人头疼的问题&#xff1a;当插入U盘后&#xff0c;电脑提示需要格式化才能使用。这时&#xff0c;我们该如何应对呢?本文将为大家详细介绍U盘提示格式化的原因及解…

野生动物检测系统源码分享

野生动物检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

时序必读论文06|PITS : 基于非依赖策略学习时序patch特征表示

论文标题&#xff1a;LEARNING TO EMBED TIME SERIES PATCHES INDEPENDENTLY 下载地址&#xff1a;https://arxiv.org/pdf/2312.16427v1.pdf 开源代码&#xff1a;https://github.com/seunghan96/pits 前言 之前的文章我们读了Patch TST&#xff0c;建议大家阅读原论文&…

数据结构修炼——顺序表和链表的OJ题练习

目录 一、顺序表相关OJ题1 移除元素题目解析 2 合并两个有序数组题目解析 二、链表相关OJ题1 移除链表元素题目解析 2 反转链表题目解析 3 链表的中间结点题目解析 4 合并两个有序链表题目解析 5 链表的回文结构题目解析 6 相交链表题目解析 7 环形链表的判断题目解析 8 环形链…

共享单车轨迹数据分析:以厦门市共享单车数据为例(四)

副标题&#xff1a;共享单车与地铁接驳距离探究——以厦门市为例 关于轨道交通站点接驳范围的研究早已屡见不鲜&#xff0c;通常认为以站点为圆心、800米作为地铁站直接的服务范围是合理的。近年来&#xff0c;随着轨道、公交和慢行交通三网融合概念的提出&#xff0c;慢行交通…

9.第二阶段x86游戏实战2-初识易语言

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 工具下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd6tw3 提…

喜报 | 大势智慧荣获国家级专精特新重点“小巨人”企业荣誉称号

近日&#xff0c;湖北省经济和信息化厅发布了《关于2024年拟支持专精特新重点“小巨人”企业名单的公示》。武汉大势智慧科技有限公司&#xff08;后简称“大势智慧”&#xff09;凭借在实景三维AI领域的卓越技术表现和创新能力&#xff0c;成功上榜并通过公示期&#xff0c;荣…

预算不多怎么选一款开放式耳机?四款亲测好用的蓝牙耳机推荐

挑选开放式耳机可以从以下几个方面入手&#xff1a; 关注佩戴舒适度&#xff1a; 外观设计&#xff1a;开放式耳机有耳挂式、夹耳式等多种设计。耳挂式耳机通常佩戴较为稳固&#xff0c;适合运动时使用&#xff1b;夹耳式耳机相对轻便&#xff0c;但可能需要一定时间适应其佩…

多核DSP(6000系列)设计与调试技巧培训

​课程介绍&#xff1a; 为帮助从事DSP开发工程师尽快将DSP技术转化为产品&#xff0c;在较短时间内掌握DSP设计技术和问题的解决方法&#xff0c;缩短产品开发周期、增强产品竞争力、节省研发经费。我们特组织了工程实践和教学经验丰富的专家连续举办了多期DSP C6000的培训&a…

六氟化硫密度微水在线监测配套5孔M12格兰头航空插头插座

我们将为大家介绍如何使用六氟化硫密度微水在线监测配套5孔M12格兰头连接器。在本教程中&#xff0c;我们将向您展示简单易懂的步骤&#xff0c;让您轻松掌握。 所需材料&#xff1a; 1. 六氟化硫密度微水在线监测器 2. 5孔M12格兰头连接器 3. 电源线 4. 符合要求的电缆 5…

批量视频压缩需要怎么压缩?2024帮助你快速进行视频压缩的软件

批量视频压缩需要怎么压缩&#xff1f;2024帮助你快速进行视频压缩的软件 批量视频压缩是处理大量视频文件时常见的需求&#xff0c;特别是当你需要减小视频大小以便存储或上传时。以下是5款帮助你快速进行视频压缩的软件&#xff0c;它们操作简单&#xff0c;功能强大&#x…

三、k8s中的控制器的使用

一 什么是控制器 官方文档&#xff1a; 工作负载管理 | Kubernetes 控制器也是管理pod的一种手段 自主式pod&#xff1a;pod退出或意外关闭后不会被重新创建 控制器管理的 Pod&#xff1a;在控制器的生命周期里&#xff0c;始终要维持 Pod 的副本数目 Pod控制器是管理pod…

Java高级Day41-反射入门

115.反射 反射机制 1.根据配置文件re.properties指定信息&#xff0c;创建Cat对象并调用hi方法 SuppressWarnings({"all"}) public class ReflectionQuestion {public static void main(String[] args) throws IOException {//根据配置文件 re.properties 指定信息…

最新热点!结合创新!小样本学习+CLIP:超好上手的思路,爽发顶会顶刊

今天给大家推荐一个很好上手的创新思路&#xff1a;小样本学习CLIP。 这个思路的优势在于&#xff1a;通过利用CLIP模型强大的跨模态表征能力&#xff0c;再结合小样本学习技术&#xff0c;我们就可以在仅提供少量标注样本的情况下&#xff0c;快速适应新的任务&#xff0c;在…

elementui组件el-upload实现批量文件上传

el-upload组件上传文件时&#xff0c;每传一个文件会调一次接口&#xff0c;所以当上传多个文件的时候&#xff0c;有 n 个文件就要调 n 次接口。 刚好之前工作中遇到使用el-upload组件批量上传文件的需求&#xff0c;来看看怎么实现。 思路&#xff1a; 1.取消组件的自动上…

【C++】vector常见用法

&#x1f525;个人主页&#x1f525;&#xff1a;孤寂大仙V &#x1f308;收录专栏&#x1f308;&#xff1a;C从小白到高手 &#x1f339;往期回顾&#x1f339;&#xff1a;[C]string类 &#x1f516; 流水不争&#xff0c;争的是滔滔不息。 文章目录 一、vector的介绍vector…

KubeCon China 回顾|快手的 100% 资源利用率提升:从裸机迁移大规模 Redis 到 Kubernetes

大家下午好&#xff0c;我是来自 ApeCloud 的吴学强&#xff0c;非常高兴能够在 KubeCon 做分享。今天的分享由我和来自快手的刘裕惺同学共同完成&#xff0c;我们分享的主题是将大规模的 Redis 实例从裸机迁移到 Kubernetes 上来提高资源的利用率。 我们今天的议题包括几个方…

价值流与核心理论框架对比解析:企业业务架构优化的全景指南

企业架构优化中的理论框架选择 随着数字化转型和全球竞争的加剧&#xff0c;企业管理者越来越意识到优化业务流程以提升竞争力的重要性。然而&#xff0c;在众多优化方法中&#xff0c;企业如何选择最适合自己的理论框架成为一大挑战。由The Open Group发布的《价值流指南》系…

配电房监控 配电柜监测系统方案简介@卓振思众

在当今迅速发展的电力行业中&#xff0c;配电柜监测系统的作用越来越受到重视。作为配电系统的核心组件&#xff0c;配电柜不仅承担着电力分配的关键任务&#xff0c;还面临着安全性和稳定性的重要挑战。为了确保电力供应的连续性和可靠性&#xff0c;配电柜监测系统应运而生&a…

鼎捷新一代PLM 荣膺维科杯 “2023年度行业优秀产品奖”

近日&#xff0c;由中国高科技行业门户OFweek维科网主办的“全数会2024&#xff08;第五届&#xff09;中国智能制造数字化转型大会暨维科杯工业自动化及数字化行业年度评选颁奖典礼”在深圳隆重举办。这不仅是中国工业自动化及数字化行业的一大品牌盛会&#xff0c;亦是高科技…