EasyExcel 的简单使用(读取写入)

news2024/12/24 0:36:08

文章目录

  • 前言
  • 一、创建项目
  • 二、核心代码
    • 2.1 org.feng.bean包中的类
      • 2.1.1 Sex类
      • 2.1.2 User类
    • 2.2 org.feng.constant包中的类
      • 2.2.1 Constant类
    • 2.3 org.feng.converter包中的类
      • 2.3.1 ListDataConverter类
      • 2.3.2 SexConverter类
    • 2.4 org.feng.listener包中的类
      • 2.4.1 UserReadListener类
    • 2.5 org.feng.client包中的类
      • 2.6.1 ExcelClient 类
  • 三、测试
    • 3.1 表格写入后的内容
    • 3.2 控制台的日志

前言

我们的业务场景中可能经常遇到需要保存数据到表格,或者从表格读取到数据,随后做一些操作。

本文将在Spring项目中做写入和读取操作。

一、创建项目

项目结构如下:
在这里插入图片描述
其中test.xlsx文件是一个新创建的表格文件,里边是空的。
执行操作是,先给该表格写入内容,随后从中读取。

引入Maven依赖:

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>3.3.2</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.28</version>
            <optional>true</optional>
        </dependency>

二、核心代码

2.1 org.feng.bean包中的类

2.1.1 Sex类

package org.feng.bean;

import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * 性别枚举
 */
@Getter
@AllArgsConstructor
public enum Sex {
    /**
     * 男
     */
    MALE(1),
    /**
     * 女
     */
    FEMALE(0);

    /**
     * 性别标识
     */
    private final Integer sexFlag;
}

2.1.2 User类

需要使用EasyExcel中的注解进行标注属性。
集合,枚举等类型的属性还需要设置转换器。

package org.feng.bean;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import lombok.Data;
import org.feng.constant.Constant;
import org.feng.converter.ListDataConverter;
import org.feng.converter.SexConvert;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 用户
 *
 * @author fengjinsong
 * @date 2023-06-30 14:35:15
 * @version: 1.0
 */
@Data
public class User {

    @ExcelProperty(value = "编号", index = 0)
    private String id;

    @ExcelProperty(value = "姓名", index = 1)
    private String name;

    @ExcelProperty(value = "年龄", index = 2)
    private Integer age;

    @ExcelProperty(value = "性别", index = 3, converter = SexConvert.class)
    private Sex sex;

    @DateTimeFormat(Constant.TIME_FORMAT)
    @ExcelProperty(value = "生日", index = 4)
    private LocalDateTime birthday;

    @ExcelProperty(value = "电话", index = 5)
    private String phone;

    @ExcelProperty(value = "爱好", index = 6, converter = ListDataConverter.class)
    private List<String> hobbies;
}

2.2 org.feng.constant包中的类

2.2.1 Constant类

package org.feng.constant;

/**
 * 常量类
 *
 * @author fengjinsong
 * @date 2023-06-30 14:55:22
 * @version: 1.0
 */
public interface Constant {

    /**
     * 时间格式:写入到excel时的格式
     */
    String TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
}

2.3 org.feng.converter包中的类

这里定义的是转换器,目前需要转换的有集合类型,枚举类型。

2.3.1 ListDataConverter类

package org.feng.converter;

import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;

import java.util.List;

/**
 * list数据转字符串的转换器
 *
 * @author fengjinsong
 * @date 2023-06-30 14:57:50
 * @version: 1.0
 */
public class ListDataConverter implements Converter<List<String>> {

    @Override
    public Class<?> supportJavaTypeKey() {
        return List.class;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }

    @Override
    public WriteCellData<String> convertToExcelData(List<String> value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        return new WriteCellData<>(String.valueOf(value));
    }

    @Override
    public List<String> convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        String stringValue = cellData.getStringValue();

        // 去除中括号,并按照逗号切割
        String[] split = stringValue.substring(1, stringValue.length() - 1).split(", ");
        return List.of(split);
    }
}

2.3.2 SexConverter类

package org.feng.converter;

import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import org.feng.bean.Sex;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Arrays;

/**
 * 性别转换
 *
 * @author fengjinsong
 * @date 2023-06-30 15:13:57
 * @version: 1.0
 */
public class SexConvert implements Converter<Sex> {

    @Override
    public Class<?> supportJavaTypeKey() {
        return Sex.class;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.NUMBER;
    }

    @Override
    public WriteCellData<BigDecimal> convertToExcelData(Sex value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        return new WriteCellData<>(BigDecimal.valueOf(value.getSexFlag()).setScale(0, RoundingMode.HALF_UP));
    }

    @Override
    public Sex convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        int sexFlag = cellData.getNumberValue().intValue();

        return Arrays.stream(Sex.values())
                .filter(sex -> sex.getSexFlag().equals(sexFlag))
                .findAny()
                .orElse(Sex.MALE);
    }
}

2.4 org.feng.listener包中的类

2.4.1 UserReadListener类

package org.feng.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import lombok.extern.slf4j.Slf4j;
import org.feng.bean.User;

/**
 * 对读表格时进行监听
 *
 * @author fengjinsong
 * @date 2023-06-30 15:59:01
 * @version: 1.0
 */
@Slf4j
public class UserReadListener implements ReadListener<User> {
    @Override
    public void invoke(User data, AnalysisContext context) {
        log.info("正在读取User数据的编号是:{}", data.getId());
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        log.info("表格读取完毕!");
    }
}

2.5 org.feng.client包中的类

也是执行的位置

2.6.1 ExcelClient 类

package org.feng.client;

import com.alibaba.excel.EasyExcel;
import org.feng.bean.Sex;
import org.feng.bean.User;
import org.feng.listener.UserReadListener;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.FileNotFoundException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 执行读、写表格
 *
 * @author fengjinsong
 * @date 2023-06-30 15:18:25
 * @version: 1.0
 */
public class ExcelClient {

    public static void main(String[] args) throws FileNotFoundException {
        writeUser();

        readUser();
    }

    public static void readUser() throws FileNotFoundException {
        File file = ResourceUtils.getFile("classpath:excels/test.xlsx");
        List<User> users = EasyExcel.read(file, new UserReadListener())
                .head(User.class)
                .doReadAllSync();
        // 打印结果
        users.forEach(System.out::println);
    }

    public static void writeUser() throws FileNotFoundException {
        File file = ResourceUtils.getFile("classpath:excels/test.xlsx");

        List<User> users = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            User user = new User();
            users.add(user);

            user.setAge(ThreadLocalRandom.current().nextInt(18, 40));
            user.setName("冯" + i);
            user.setSex(i % 2 == 0 ? Sex.FEMALE : Sex.MALE);
            user.setId(String.valueOf(i));
            user.setPhone("1811243556" + i);
            user.setBirthday(LocalDateTime.now());
            user.setHobbies(List.of("唱", "跳", "rap"));
        }

        EasyExcel.write(file, User.class)
                .sheet("用户信息")
                .doWrite(users);
    }
}

三、测试

3.1 表格写入后的内容

在这里插入图片描述

3.2 控制台的日志

16:24:19.543 [main] INFO org.feng.listener.UserReadListener - 正在读取User数据的编号是:0
16:24:19.545 [main] INFO org.feng.listener.UserReadListener - 正在读取User数据的编号是:1
16:24:19.546 [main] INFO org.feng.listener.UserReadListener - 正在读取User数据的编号是:2
16:24:19.547 [main] INFO org.feng.listener.UserReadListener - 正在读取User数据的编号是:3
16:24:19.548 [main] INFO org.feng.listener.UserReadListener - 正在读取User数据的编号是:4
16:24:19.549 [main] INFO org.feng.listener.UserReadListener - 表格读取完毕!
User(id=0, name=冯0, age=35, sex=FEMALE, birthday=2023-06-30T16:24:18, phone=18112435560, hobbies=[唱, 跳, rap])
User(id=1, name=冯1, age=26, sex=MALE, birthday=2023-06-30T16:24:18, phone=18112435561, hobbies=[唱, 跳, rap])
User(id=2, name=冯2, age=19, sex=FEMALE, birthday=2023-06-30T16:24:18, phone=18112435562, hobbies=[唱, 跳, rap])
User(id=3, name=冯3, age=20, sex=MALE, birthday=2023-06-30T16:24:18, phone=18112435563, hobbies=[唱, 跳, rap])
User(id=4, name=冯4, age=36, sex=FEMALE, birthday=2023-06-30T16:24:18, phone=18112435564, hobbies=[唱, 跳, rap])

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

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

相关文章

android用java生成crc校验位

在串口通信中&#xff0c;经常会用到后两位生成crc校验位的情况。 下面是校验位生成方法&#xff1a; public static String getCRC(String data) {data data.replace(" ", "");int len data.length();if (!(len % 2 0)) {return "0000";}in…

Springboot集成mybatisplus的问题处理

文章目录 前言一个接口多个实现解决方案 Invalid bound statement (not found)解决方案 总结 前言 新接触mybatisPlus的小伙伴可能会遇到各种各样的问题&#xff0c;尤其是mybatis的xml文件及类的注入问题&#xff0c;下面我们就看一下常见的问题吧。 一个接口多个实现 报错…

python numpy 多维数据广播

广播规则&#xff1a;从最右侧开始广播。 Broadcasting — NumPy v1.25 Manual 截图 下面给出一些样例&#xff1a; 三维矩阵广播 a np.array([[[0,0],[0,0]],[[0, 0],[0, 0]]])print(-*10, a, -*10) print(a.shape) print(a)b np.array([[[1]],[[2]]]) print(-*10, b, -*…

AIGC 3D引擎-LayaAir3.0正式版发布了

2016年6月30日&#xff0c;LayaAir引擎1.0正式版首次发布&#xff0c;今天迎来了它的7周岁生日。 7年&#xff0c;3个大版本&#xff0c;代表着引擎不同阶段、不同的时代、不同的定位。 2016年6月的第1代引擎版本定位是极致性能&#xff0c;支持2D与3D游戏开发&#xff0c; 满足…

【C/C++实现进程间通信 三】管道通信机制

文章目录 前情回顾思路源码Publisher.cppSubscriber.cpp 效果 前情回顾 上一期已经讲解过了进程的相关概念以及进程间通信的实现原理&#xff0c;下面仅展示管道通信机制实现进程间通信的相关代码。 思路 /*本项目主要用于以管道通信的方式进行进程间通信的测试。1.主要包含…

Java面试Day17

1.什么是 Java 内部类&#xff1f; 内部类的分类有哪些 &#xff1f;内部类有哪些优点和应用场景&#xff1f; 顾名思义&#xff0c;内部类是指定义在某一个类中的类&#xff0c;主要分为成员内部类&#xff0c;静态内部类&#xff0c;局部内部类和匿名内部类四种。 创建与获取…

(五)python实战——使用sqlalchemy完成Sqlite3数据库表的增、删、查、改操作案例

前言 本节内容我们使用sqlalchemy框架完成Sqlite3数据库表的增删查改等常规操作&#xff0c;相较于原生Sqlite的数据库操作&#xff0c;sqlalchemy通过ORM映射完成实体对象的映射&#xff0c;通过映射关系完成对象和数据的转换&#xff0c;完成数据的操作。 正文 ①在项目中…

基于Tars高并发IM系统的设计与实现-基础篇

基于Tars高并发IM系统的设计与实现–基础篇 作者简介 兰怀玉 毕业于中央民族大学计算机专业 先后供职国内外多家公司软件研发设计岗位&#xff0c;有丰富的软件研发经验。 从事IM领域设计研发十余年&#xff0c;先后领衔多个IM通讯系统设计与研发发&#xff0c;拥有丰富的IM系…

算法:哲学家就餐问题

问题描述 由Dijkstra提出并解决的哲学家就餐问题是典型的同步问题。该问题描述的是五个哲学家共用一张圆桌&#xff0c;分别坐在周围的五张椅子上&#xff0c;在圆桌上有五个碗和五只筷子&#xff0c;他们的生活方式是交替的进行思考和进餐。平时&#xff0c;一个哲学家进行思考…

大语言模型微调和PEFT高效微调

目录标题 1 解释说明1.1 预训练阶段1.2 微调阶段2 几种微调算法2.1 在线微调2.2 高效微调2.2.1 RLHF2.2.2 LoRA2.2.3 Prefix Tuning2.2.4 Prompt Tuning2.2.5 P-Tuning v21 解释说明 预训练语言模型的成功,证明了我们可以从海量的无标注文本中学到潜在的语义信息,而无需为每一…

信号链噪声分析11

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 提示&#xff1a;这里可以添加技术概要 如今的射频(RF)系统变得越来越复杂。高度的复杂性要求所有系统指标&#xff08;例如严格的 链接和噪声预算&#xff09;达到最佳性能。确保整个信号链的正确设计至关重要。而信…

深入乳腺癌谜团:无监督学习与R语言的勘探之旅

一、引言 乳腺癌作为全球常见的恶性肿瘤&#xff0c;给患者和医学界带来了巨大的挑战。据世界卫生组织的数据显示&#xff0c;乳腺癌是妇女中最常见的癌症之一&#xff0c;并且是全球癌症相关死亡的主要原因之一[1]。因此&#xff0c;研究乳腺癌&#xff0c;并努力提高其早期检…

1085会议桌牌

机种名 蓝牙会议桌牌 型号 PE1085R_D_BLE 外观尺寸 280x58x129.9mm 可视区域 258.7690.68mm 外观颜色 银色 工作电源 3.7V锂电池供电&#xff0c;Type C充电口 显示技术 E-INK电子纸&#xff0c;双屏 像素 1360x480 像素颜色 黑/白/红 视角 约180 适用温度 …

【Java】直接return 会触发try-catch 里面的finally的方法么

&#x1f431;‍&#x1f680;/背景 try-catch 主要的作用是捕获异常&#xff0c;那么程序没有异常&#xff0c;finally里面代码能否执行&#xff1f; 特别是如果我们前面进行了加锁等操作&#xff0c;没有释放锁&#xff0c;那不是会造成业务逻辑问题, 先说结论&#xff1a;…

Eclipse成立新工作组,华为和谷歌等是初始成员

日前一个供应商中立&#xff0c;并由社区支持的Visual Studio第三方开源市场Open VSX Registry迎来新工作组的成立。根据了解&#xff0c;开发者可以在Open VSX Registry当中的市场中自由上架、下载安装Visual Studio的各种第三方扩展。 随即Eclipse基金会宣告成立了Open VSX工…

前缀迷宫:解密力扣统计包含给定前缀的字符串

本篇博客会讲解力扣“2185. 统计包含给定前缀的字符串”的解题思路&#xff0c;这是题目链接。 本题的思路是&#xff1a;遍历字符串数组&#xff0c;判断遍历到的字符串是否包含给定前缀。 判断的方法是&#xff1a;使用strncmp函数&#xff0c;比较该字符串的前strlen(pref)…

【Linux】工具介绍——vim及gcc

前言 在Linux操作系统之中有很多使用的工具&#xff0c;我们可以用vim来进行程序的编写&#xff0c;然后用gcc来生成可执行文件&#xff0c;最终运行程序。本文来带大家了解vim和gcc&#xff0c;以及自动化构建工具Makefile&#xff0c;这三个工具的使用方法。 一、vim 1.vi…

Webpack打包arcgis js api 3.x纯html+JS+CSS项目

需求 小项目。纯HTMLJSCSS已经部署上线&#xff0c;但是没有做混淆加密&#xff0c;需要进行混淆加密 分析 目前代码里面需要混淆加密的有main.js&#xff0c;其他的不用混淆加密。所以只需要对main.js进行混淆加密就可&#xff0c;但是要保证混淆加密之后能够访问方法。由于…

C#中的自定义组件(单一组件和复杂组件)

简单的应用程序开发可能不必要制作组件&#xff0c;C#中丰富的组件足以应对绝大多数的开发设想。 稍微复杂一些的应用开发&#xff0c;或者平台开发&#xff0c;或者团队开发&#xff0c;不可避免地要涉及到基础库的搭建&#xff0c;其中会有很多用户组件的设计与开发。 组件分…

计算机视觉 - 理论 - 从卷积到识别

计算机视觉 - 理论入门 前言一&#xff0c;导论&#xff1a;二&#xff0c;卷积&#xff1a;图像去噪&#xff1a;常值卷积&#xff1a;高斯卷积&#xff1a;椒盐去噪&#xff1a;锐化程度&#xff1a; 三&#xff0c;边缘检测&#xff1a;图像信号导数&#xff1a;求导算子:图…