EasyExcel动态映射Excel数据到任意实体类教程

news2024/9/21 2:43:23

在使用EasyExcel进行Excel导入时,我们经常需要将Excel中的数据映射到Java实体类中。如果Excel的列名是固定的,我们可以通过@ExcelProperty("列名")注解直接在实体类中指定列名。但如果Excel的列名不固定,或者我们希望根据Excel的第一行来动态确定映射关系,我们就需要一种更灵活的方法。本教程将介绍如何使用EasyExcel创建一个工具类,以支持动态映射Excel数据到任意实体类。

步骤1:添加EasyExcel依赖

首先,确保你的项目中已经添加了EasyExcel的依赖。如果使用Maven,可以在pom.xml中添加如下依赖:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>3.x.x</version> <!-- 使用最新版本 -->
</dependency>

步骤2:创建动态映射工具类

创建一个工具类DynamicExcelUtil,它将负责读取Excel文件,并根据第一行的列名动态映射数据到实体类。

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import lombok.var;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class ExcelUtil {

    /**
     * 读取 Excel 文件并返回数据模型列表。
     *
     * @param fileName Excel 文件的路径。
     * @param clazz    数据模型类。
     * @param <T>      数据模型的类型。
     * @return 数据模型列表。
     */
    public static <T> List<T> readExcel(String fileName, Class<T> clazz) {
        ExcelDataListener<T> listener = new ExcelDataListener<>();
        List<T> dataModels = new ArrayList<>();

        try {
            EasyExcel.read(fileName, clazz, listener).sheet().doRead();
            dataModels = listener.getDataModels();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return dataModels;
    }

    /**
     * Excel 数据读取监听器。
     *
     * @param <T> 数据模型的类型。
     */
    public static class ExcelDataListener<T> implements ReadListener<T> {
        private List<T> dataModels = new ArrayList<>();

        @Override
        public void invoke(T dataModel, AnalysisContext context) {
            dataModels.add(dataModel);
        }

        @Override
        public void doAfterAllAnalysed(AnalysisContext context) {
            // 所有数据解析完成后的操作
        }

        public List<T> getDataModels() {
            return dataModels;
        }
    }



    /**
     * 将 MultipartFile 转换为 File 对象。
     *
     * @param file MultipartFile 对象。
     * @return 转换后的 File 对象。
     * @throws IOException 如果文件写入失败。
     */
    public static File convert(MultipartFile file) throws IOException {
        if (!file.isEmpty()) {
            File convFile = new File(Objects.requireNonNull(file.getOriginalFilename()));
            try (var fos = new FileOutputStream(convFile)) {
                fos.write(file.getBytes());
            }
            return convFile;
        }
        throw new IOException("Could not convert the uploaded file.");
    }

}

如果我们现在有一个实体类,如下:

package com.xiaobai.easyexceldemo.domain;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import lombok.Data;

/**
 * 
 * @TableName easy_demo
 */
@TableName(value ="easy_demo")
@Data
public class EasyDemo implements Serializable {
    /**
     * 
     */
    @TableId
    private Integer id;

    /**
     * 
     */
    private String name;

    /**
     * 
     */
    private String password;

    /**
     * 
     */
    private String email;

    /**
     * 
     */
    private String qq;

    /**
     * 
     */
    private String address;

    /**
     * 
     */
    private String nameSpace;

    @TableField(exist = false)
    private static final long serialVersionUID = 1L;
}

 此时我们我们有一个表格,数据如下:

测试:方式一,直接映射

此时我们映射的时候,需要按照表格的列新创建一个中间类。

@Data
public class EasyDemoDto {

    /**
     *
     */
    private String name;

    /**
     *
     */
    private String password;

    /**
     *
     */
    private String email;

    /**
     *
     */
    private String qq;

    /**
     *
     */
    private String address;

    /**
     *
     */
    private String nameSpace;
}

这个类需要按照表格的列进行按照顺序排列,才可以映射上。

 

现在我们调换一下(name,password)字段的顺序,看一下结果:

所以直接映射的时候一定要注意,字段和excel表格列顺序一致

测试:方式二,注解映射

在实体中添加注解@ExcelProperty("列名"),映射excel表中的列名,进行映射数据。

@Data
public class EasyDemoDto {

    /**
     *
     */
    @ExcelProperty("密码")
    private String password;

    /**
     *
     */
    @ExcelProperty("名称")
    private String name;



    /**
     *
     */
    @ExcelProperty("邮箱")
    private String email;

    /**
     *
     */
    @ExcelProperty("qq")
    private String qq;

    /**
     *
     */
    @ExcelProperty("地址")
    private String address;

    /**
     *
     */
    @ExcelProperty("空间")
    private String nameSpace;
}

EasyExcel中注解说明 

@ExcelProperty: 用于指定实体类属性与 Excel 列的映射关系。

public class Student {
    @ExcelProperty("学生姓名")
    private String name;
    // 其他属性和getter/setter方法
}

@DateTimeFormat: 用于指定日期时间格式,与@ExcelProperty一起使用。

@ExcelProperty("出生日期")
@DateTimeFormat("yyyy-MM-dd")
private Date birthDate;

@NumberFormat: 用于指定数字格式,与@ExcelProperty一起使用。

@ExcelProperty("分数")
@NumberFormat("#.##")
private double score;

@ColumnWidth: 用于指定列宽。

public class Product {
    @ExcelProperty("产品名称")
    @ColumnWidth(20)
    private String name;
    // 其他属性和getter/setter方法
}

@ContentFontStyle: 用于定义内容单元格的字体样式。

@ExcelProperty("备注")
@ContentFontStyle(name = "微软雅黑", size = 12, isBold = true)
private String comment;

@ContentLoopMerge: 用于在循环写入时合并单元格。

public class SalesRecord {
    @ExcelProperty("产品名称")
    @ContentLoopMerge(startRow = 1, endRow = 3)
    private String productName;
    // 其他属性和getter/setter方法
}

@ContentRowHeight: 用于设置内容行高。

@ExcelProperty("详细描述")
@ContentRowHeight(value = 50)
private String description;

@ContentStyle: 用于定义内容单元格的样式。

@ExcelProperty("数值")
@ContentStyle(fillForegroundColor = 3, fillPatternType = FillPatternType.SOLID_FOREGROUND)
private double value;

@HeadFontStyle: 用于定义表头单元格的字体样式。

public class Employee {
    @ExcelProperty("工号")
    @HeadFontStyle(name = "宋体", size = 14, isBold = true)
    private String employeeId;
    // 其他属性和getter/setter方法
}

@HeadRowHeight: 用于设置表头行高。

@ExcelProperty("姓名")
@HeadRowHeight(value = 30)
private String name;

@HeadStyle: 用于定义表头单元格的样式。

@ExcelProperty("部门")
@HeadStyle(fillForegroundColor = 4, fillPatternType = FillPatternType.SOLID_FOREGROUND)
private String department;

@OnceAbsoluteMerge: 用于绝对合并单元格一次。

public class Summary {
    @ExcelProperty("总计")
    @OnceAbsoluteMerge(merge = {@ExcelColIndex(1), @ExcelColIndex(2)}, row = 1)
    private double total;
    // 其他属性和getter/setter方法
}

@ExcelIgnore: 用于忽略不映射到 Excel 的实体类属性。

private String internalUseOnly;

@ExcelIgnoreUnannotated: 类级别的注解,指定只有使用了@ExcelProperty注解的字段才会写入 Excel。

@ExcelIgnoreUnannotated
public class Product {
    private String id;
    @ExcelProperty("产品名称")
    private String name;
    // 只有name属性会写入Excel
}

@ExcelColIndex: 用于指定列的索引。

@ExcelProperty("价格")
@ExcelColIndex(2)
private double price;

至此,已经结束啦,获取有不对的地方,还请提出,共勉。

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

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

相关文章

NS2582 同步升压双节锂电池充电管理 IC

1 特性  最大 2A 输出同步开关型升压充电器  升压效率可高达 90% 以上  内置电池短路 / 涓流 / 恒流 / 恒压模式  0.5% 电池恒压模式电压精度  支持 LED 充电状态指示  支持充电电流外部可调  支持输入适配器 DPM 功能  外置 EN 使能…

SQL语法:create、insert、update、

1.create创建表 创建表时&#xff0c;通常会有如下设置&#xff1a;主键、非空、取值唯一、使用自动增长等。 根据如图创建表名为userinfo的数据表&#xff1a; create table userinfo(id int not null primary key auto_increment,username varchar(50) not null unique,cre…

java框架第二课(Reflection反射机制)

一.关于反射 (1)使用场景介绍 平常我们写代码时&#xff0c;都是已知类名&#xff0c;类的属性&#xff0c;构造方法&#xff0c;其他方法等信息&#xff0c;然后根据类名new对象&#xff0c;这个过程称为正向操作(例如&#xff1a;有一个管理员类&#xff0c;有账号和密码属…

WEB渗透Win提权篇-BypassUAC

提权工具合集包&#xff08;免费分享&#xff09;&#xff1a; 夸克网盘分享 往期文章 WEB渗透Win提权篇-提权工具合集-CSDN博客 WEB渗透Win提权篇-RDP&Firewall-CSDN博客 WEB渗透Win提权篇-MSSQL-CSDN博客 WEB渗透Win提权篇-MYSQL-udf-CSDN博客 WEB渗透Win提权篇-Acc…

大模型基础环境部署之一:安装 Nvidia 的驱动(详细实操版)

一、系统准备前置条件 1、更新软件包列表 sudo apt-get update2、安装编译工具和依赖项 sudo apt-get install gcc sudo apt-get install make sudo apt-get install g注&#xff1a;如果在安装 g 时遇到错误消息&#xff1a;“***you do not appear to have libc header fi…

【C++ Primer Plus习题】6.2

问题: 解答: #include <iostream> #include <array> using namespace std;#define MAX 10int main() {array<float, MAX> arr;float sum0;float average0;int i 0;int count0;int bigger 0;for (i 0; i < MAX; i){cout << "请输入donation…

大数据技术之Flume 企业开发案例——聚合(7)

目录 聚合 1&#xff09;案例需求&#xff1a; 2&#xff09;需求分析 3&#xff09;实现步骤&#xff1a; 准备工作 创建 flume1-logger-flume.conf 创建 flume2-netcat-flume.conf 创建 flume3-flume-logger.conf 执行配置文件 聚合 1&#xff09;案例需求&#x…

华为eNSP:路由器子接口配置

一、拓扑图 二、 路由器配置 [R1]int g0/0/0.1#进入子接口 [R1-GigabitEthernet0/0/0.1]ip add 192.168.1.254 24#配置子接口地址 [R1-GigabitEthernet0/0/0.1]dot1q termination vid 10#标记终止的vid编号 [R1-GigabitEthernet0/0/0.1]arp broadcast enable #开启子接口的arp…

Keilv5 逻辑分析仪的使用

声明&#xff1a;基于视频【事件驱动型编程和 QP/C 框架】所做的笔记 Keilv5逻辑分析仪是Keil MDK集成开发环境&#xff08;IDE&#xff09;中的一个工具&#xff0c;用于帮助开发人员进行嵌入式系统的调试和分析。 它的作用主要有&#xff1a; 监测信号&#xff1a;Keilv5逻…

DBSCAN算法详解

1. 算法原理 DBSCAN&#xff08;Density-Based Spatial Clustering of Applications with Noise&#xff09;是一种基于密度的聚类算法&#xff0c;主要用于发现数据中的任意形状的簇&#xff0c;并能够有效地识别噪声点。它的基本思想是通过密度来定义簇&#xff0c;即在数据…

Python -- GUI图形界面编程—GUI编程实例 博主也在持续学习中[ 持续更新中!!! 欢迎白嫖 ]

本文继上篇文章http://t.csdnimg.cn/mJlmW继续介绍GUI的图形界面编程&#xff08;相关视频是哔站上的应该搜这个题目就能找到&#xff09;&#xff0c;文章还是很基础的&#xff0c;目前博主处于有一点基础的状态。 文章的主要介绍了依旧非常重要的结构tinkter库、常见的三种布…

Patch-Package:一款灵活的开源依赖修复工具

一、背景 在现代软件开发中&#xff0c;开发者通常依赖大量的开源库来加快开发进程。然而&#xff0c;随着时间的推移&#xff0c;可能会遇到一些问题&#xff1a; 开源包的缺陷&#xff1a;开源库可能存在 Bug 或者与项目不兼容的问题。开发者可以自己修复这些问题&#xff0…

QML控件: 动画输入框 LineEdit PySide6

1. 前言 本代码为扫地僧-smile原创, 废话不多说, 直接看效果图由于录制的这个GIF图掉帧严重, 实际动画效果非常细腻 2.看代码 控件模块代码如下 SmileLineEdit.qml import QtQuick import QtQuick.Controls/* __author__: 扫地僧-smile */Rectangle {// 属性property int …

这些年使用Delphi的成果

成果1&#xff1a; 收到了一件文化衫 成果2&#xff1a;被评为亚洲专家&#xff0c;收到了一套Delphi7 光碟找不到了。

Arista与英伟达IB网络竞争格局分析

悄然崛起的英伟达新对手 英伟达都有哪些对手&#xff1f; 当然首选AMD和英特尔。AMD具备AI加速卡业务&#xff0c;融合CPU和GPU设计能力&#xff1b;英特尔作为x86架构的开创者&#xff0c;如今也涉足AI加速卡领域。它们的产品在参数上与英伟达对标&#xff0c;同时在定位和售…

江西生物科技职业学院春雨宣讲团丨弘扬西柏坡精神,共绘时代新篇章

今年五月&#xff0c;江西生物科技职业学院春雨宣讲团获批共青团中央2024年全国大学生西柏坡精神志愿宣讲团之一。 秉承传承红色文化、弘扬西柏坡精神的崇高使命&#xff0c;该宣讲团成员自7月3日起至8月20日&#xff0c;踏上了深入江西省南昌市、九江市、景德镇市、吉安市等地…

走线特征阻抗

ns/ft中ft代表英尺 :1ft0.3048m30.48cm 对于FR-4板&#xff0c;1.017*根号&#xff08;4.5&#xff09;2.121ns/ft 也即每英寸的传输时间为2.121ns&#xff0c;30.48/2.12114.6cm/ns&#xff1b; 当差分线中以相同的驱动电压驱动时&#xff0c;我们称之为偶模&#xff0c;当以…

Eclipse 自定义字体大小

常用编程软件自定义字体大全首页 文章目录 前言具体操作1. 打开设置对话框2. 打开字体设置页面3. 找到Text Font&#xff0c;点击修改4. 修改字体 前言 Eclipse 自定义字体大小&#xff0c;统一设置为 Courier New &#xff0c;大小为 三号 具体操作 【Windows】>【Perfer…

IROS 2024不容错过的4大理由

01 IROS是国际机器人顶会 关于机器人学术顶会&#xff0c;听IROS 2025大会主席、上海交通大学王贺升教授怎么说。 ICRA 2024专辑&#xff1a;上交王贺升教授聊机器人学术顶会【度量访问】 02 未来一年难得的国际交流机会 ICRA 2025 将在美国亚特兰大举办&#xff1b; RSS 20…

zookeeper命令 及 ACL控制

1命令 登录 zkCli.sh -server 192.168.58.81:2128 登录ip zkCli.sh 登录本机 关闭会话 close 帮助文档 help 让zk数据发生变化都是一次事务 create创建 create /aaa 创建持久节点 create -e /aaa/bbb 创建临时节点 create /aaa/bbb/ccc 不能创建成功 …