EasyPoi实现简单的Excel导出、导入

EasyPoi实现Excel导出、导入
下面这种方式不需要模板,更加方便但是不能进行复杂的导出

一、引入依赖

<dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-base</artifactId>
            <version>4.4.0</version>
        </dependency>
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-web</artifactId>
            <version>4.4.0</version>
        </dependency>
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-annotation</artifactId>
            <version>4.4.0</version>
        </dependency>
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-spring-boot-starter</artifactId>
            <version>4.4.0</version>
        </dependency>

二、数据准备

在这里插入图片描述

三、数据库数据导出到Excel

3.1 创建数据表对应的BO类

/**
 菜品
 */
@Data
public class Dish implements Serializable {

    private static final long serialVersionUID = 1L;

    @Excel(name = "菜品ID", width = 20)   // 此注解标识的属性将被导出(该注解的各属性将在最后说明)
    @ExcelIgnore    //  此注解标识的属性将被忽略导出
    private Long id;


    //菜品名称
    @Excel(name = "菜品名称", width = 20)
    private String name;


    //菜品分类id
    @Excel(name = "菜品分类ID", width = 20)
    private Long categoryId;


    //菜品价格
    @Excel(name = "菜品价格", width = 20)
    private BigDecimal price;


    //商品码
    @Excel(name = "商品码", width = 20)
    private String code;


    //图片
    @Excel(name = "菜品图片", width = 20)
    private String image;


    //描述信息
    @Excel(name = "描述信息", width = 20)
    private String description;


    //0 停售 1 起售
    private Integer status;


    //顺序
    private Integer sort;


    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;


    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;


    @TableField(fill = FieldFill.INSERT)
    private Long createUser;


    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateUser;


    //是否删除
    private Integer isDeleted;

}

3.2 数据访问层实现

@Mapper
public interface DishDAO {

    List<Dish> selectAllDish();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wyw.learn.excel.DishDAO">

    <select id="selectAllDish" resultType="com.wyw.learn.excel.Dish">
        select id,
               name,
               category_id as categoryId,
               price,
               code,
               image,
               description,
               status,
               sort,
               create_time as createTime,
               update_time as updateTime,
               create_user as createUser,
               update_user as updateUser,
               is_deleted as isDeleted
        from dish;
    </select>
</mapper>

3.3 业务逻辑层实现(关键导出逻辑)

/**
 * @author name:    silk
 * @version 1.0
 * @description: TODO
 * @date 2024/4/16 15:16
 */
@Service
public class DishService {

    @Autowired
    private DishDAO dishDAO;

    /***
     * @description: 测试导出数据至Excel
     * @param:
     * @return:
     * @author name silk
     * @date: 2024/4/16 15:01
     */
    public void testDishExportExcel() throws Exception {
        // 1. 查询数据库所有的菜品信息
        List<Dish> dishList = dishDAO.selectAllDish();
        // 2. 构造工作簿
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        // ExportParams有多个构造器,根据需要选择用哪个
        // "菜品信息表"是第1个表头名称,df.format(new Date())是第2个表头名称,"sheet1"是当前sheet名称
        ExportParams exportParams = new ExportParams("菜品信息表", df.format(new Date()), "sheet1");
        // 注意ExcelExportUtil工具类并不完美,可能还需要针对具体需求进一步完善
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, Dish.class, dishList);
        // 3. 构造文件输出流,输出excel
        FileOutputStream os = new FileOutputStream("E:/" + "testExportExcel-" + df.format(new Date()) + ".xlsx");
        workbook.write(os); // 将工作簿写出
        os.flush(); // 强制把缓冲区中的数据发送到目的地,确保数据的及时性
        os.close(); // 关闭流
    }
}

3.4 导出结果

查看Excel可知,仅导出了被@Excel标识的属性,对应的列名称就是配置的name值;
关于@Excel其他属性,在下面第五节中说明;
在这里插入图片描述
在这里插入图片描述

四、读取Excel数据至数据库表

4.1 BO类复用上述Dish类

4.2 数据访问层省略

因为我们的Excel是从该数据库表中导出的,为了避免再次插入相同的数据,导致数据库报错,在此仅将Excel读取到List中,接口返回该List即可,不再写表;

4.3 业务逻辑层(关键读取逻辑)

/**
 * @author name:    silk
 * @version 1.0
 * @description: TODO
 * @date 2024/4/16 15:16
 */
@Service
public class DishService {

    @Autowired
    private DishDAO dishDAO;

    /***
     * @description: 测试读取Excel数据
     * @param:
     * @return:
     * @author name silk
     * @date: 2024/4/17 10:05
     */
    public List<Dish> testDishImportExcel() throws Exception {
        List<Dish> res = new ArrayList<>();
        // 1. 构建文件输入流
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        FileInputStream fileInputStream = new FileInputStream("E:/" + "testExportExcel-" + df.format(new Date()) + ".xlsx");
        // 2. 构造工作簿,逐行逐列读取数据
        XSSFWorkbook workbook = new XSSFWorkbook(fileInputStream);
        // 获取工作簿sheet1中的所有数据
        XSSFSheet sheet1 = workbook.getSheet("sheet1");
        // 排除表头信息,逐行读取
        int lastRowNum = sheet1.getLastRowNum();
        if (lastRowNum <= 2) {
            System.out.println("Excel表有效数据为空,请重新导入!");
            throw new Exception("Excel表有效数据为空,请重新导入!");
        }
        for (int i = 3; i < lastRowNum; i++) {
            //行数据
            XSSFRow row = sheet1.getRow(i);
            if (ObjectUtil.isEmpty(row)) {
                continue;
            }
            Dish dish = new Dish();
            // 6列数据类型,(菜品名称 菜品分类ID 菜品价格 商品码 菜品图片 描述信息)
            // 该行的第1个元素 菜品名称
            XSSFCell name = row.getCell(0);	
            if (ObjectUtil.isEmpty(name) || StrUtil.isEmpty(name.toString())) {
                continue;
            }
            dish.setName(name.toString());
            // 该行的第2个元素 菜品分类ID
            XSSFCell categoryId = row.getCell(1);
            if (ObjectUtil.isEmpty(categoryId) || StrUtil.isEmpty(categoryId.toString())) {
                continue;
            }
            dish.setCategoryId(Long.parseLong(categoryId.toString()));
            XSSFCell price = row.getCell(2);
            if (ObjectUtil.isEmpty(price) || StrUtil.isEmpty(price.toString())) {
                continue;
            }
            // 需要注意数据类型转换,转换成适配的数据类型
            dish.setPrice(BigDecimal.valueOf(Double.parseDouble(price.toString())));
            XSSFCell code = row.getCell(3);
            if (ObjectUtil.isEmpty(code) || StrUtil.isEmpty(code.toString())) {
                continue;
            }
            dish.setCode(code.toString());
            XSSFCell image = row.getCell(4);
            if (ObjectUtil.isEmpty(image) || StrUtil.isEmpty(image.toString())) {
                continue;
            }
            dish.setImage(categoryId.toString());
            XSSFCell description = row.getCell(5);
            if (ObjectUtil.isEmpty(description) || StrUtil.isEmpty(description.toString())) {
                continue;
            }
            dish.setDescription(description.toString());
            // 3. 数据添加至返回结果List,接口将该List返回做展示
            res.add(dish);
        }
        return res;
    }
}

4.4 读取结果

在这里插入图片描述

五、@Excel注解属性【参考博客】

EasyPoi的@Excel注解具有多个属性,下表总结了这些属性及其作用。
请注意,随着EasyPoi版本的更新,可能会有新的属性加入或旧的属性被修改,以下信息基于EasyPoi的一个特定版本,可能不涵盖所有的属性和最新的变动。
在这里插入图片描述

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

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

相关文章

MyBatis操作数据库(4)

动态sql 动态sql是MyBatis的强大特性之一, 能够完成不同条件下的sql拼接. <if>标签 在注册用户的问题时, 可能会有这样的一个问题:就是说注册时有一些信息是必填的, 而有一些信息是选填的. 那么如果在添加用户的时候有不确定字段的传入, 程序应该如何实现呢? 这时就…

单调队列(C/C++)

引言&#xff1a; 单调队列和单调栈都是一种数据结构&#xff0c;应用十分广泛&#xff0c;在蓝桥杯、ICPC、CCPC等著名编程赛事都是重点的算法&#xff0c;今天博主将自己对单调栈与单调队列的理解以及刷题的经验&#xff0c;用一篇博客分享给大家&#xff0c;希望对大家有所…

第七、八章 函数 + 文件

第七章 函数 多个返回值 def test_return():return 1, "hello", Truex,y,z test_return() print(x) print(y) print(z) 1 hello True 传入的参数 位置参数 定义&#xff1a;调用函数时根据函数定义的参数位置来传递参数要求&#xff1a;传递的参数和定义的参数的顺…

1.C++入门

1.关键字&#xff08;C98&#xff09; 2.命名空间 在 C/C 中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变量、函数和类的名称将都存 在于全局作用域中&#xff0c;可能会导致很多冲突。使用命名空间的目的是 对标识符的名称进行本地化 &#xff…

利用 Amazon ECS 进行分布式机器学习

本文作者 Santiago Flores Kanter 亚马逊云科技高级解决方案架构师 Ravi Yadav 亚马逊云科技首席容器专家 校译作者 梁宇 亚马逊云科技专业服务团队 DevOps 顾问 在 Amazon ECS 服务上运行分布式机器学习工作负载可让 ML 团队更加专注于创建、训练和部署模型&#xff0c;而不是…

搭建PyTorch神经网络进行气温预测(手写+调包两种方法)(保证学会!)+找到神经网络的最优情况

代码上有注释&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 本篇主要包括三大部分&#xff1a; 第一部分&#xff1a;导入数据集导入第三方库数据集简单介绍与可视化数据集简单预处理 第二部分&#xff1a;手写神经网络代码实现气温预测&#…

链表传一级指针以及leetcode做题有感

上个文章说要传二级指针&#xff0c;经过一段时间的学习之后才知道可以传一级指针&#xff1a; 之所以要传二级指针&#xff0c;是要改变一级指针的值&#xff0c;也就是把头节点的指针改变&#xff0c;如图&#xff1a; 从左边到右边&#xff0c;头指针 一级指针plist 的值发…

C++算法题 - 哈希表

目录 383. 赎金信205. 同构字符串290. 单词规律242. 有效的字母异位词49. 字母异位词分组1. 两数之和202. 快乐数219. 存在重复元素Ⅱ128. 最长连续序列 383. 赎金信 LeetCode_link 给你两个字符串&#xff1a;ransomNote 和 magazine &#xff0c;判断 ransomNote 能不能由 m…

道合顺传感新品上市!高性能氢气传感器DSB14-G3K-J详解

道合顺传感高性能氢气传感器DSB14-G3K-J正式发布&#xff01;超强抗干扰能力优势明显。应对氢气安全挑战、高性能氢气传感器国产化、为储能保驾护航。 氢气&#xff0c;作为现今能源领域中的新贵&#xff0c;在储能行业中应用广泛且备受瞩目。但氢气易燃、易爆特性使其在生产、…

gradle.properties 中文字符乱码问题

我用AS开发Android应用。在gradle.properties中输入中文&#xff0c;再次打开时&#xff0c;发现中文变成了&#xff1f;&#xff1f;&#xff1f;。上网查询&#xff0c;发现了一个解决办法&#xff1a; 在菜单File-Settings-Editor-File Encodings中&#xff0c;将“Default…

【复习笔记】FreeRTOS(五)时间片调度

本文是FreeRTOS复习笔记的第五节&#xff0c;时间片调度。 上一篇文章&#xff1a; 【复习笔记】reeRTOS(四) 列表项的插入和删除 文章目录 1.时间片调度简介1.1. 运行过程 二、实验设计三、测试例程四、实验效果 1.时间片调度简介 FreeRTOS支持多个任务同时拥有一个优先级&am…

春藤实业启动SAP S/4HANA Cloud Public Edition项目,与工博科技携手数字化转型之路

3月11日&#xff0c;广东省春藤实业有限公司&#xff08;以下简称“春藤实业”&#xff09;SAP S/4HANA Cloud Public Edition&#xff08;以下简称“SAP ERP公有云”&#xff09;项目正式启动。春藤实业董事长陈董、联络协调项目经理慕总、内部推行项目经理陈总以及工博董事长…

数仓建模—数据架构

数仓—数据架构 为了在企业决策中使用数据,数据必须经过整个数据平台的各个阶段。整个过程是什么样子的,从开始到结束?原始形式的数据是如何转化为可导致商业决策的见解的?这些问题可以通过数据架构来回答。 数据架构是指记录组织所有数据资产的模型、规则和标准。它映射…

Web前端-JavaScript

黑马程序员JavaWeb开发教程 文章目录 一、js引入方式1、内部脚本2、外部脚本 二、js基础语法1、书写语法&#xff08;1&#xff09;基本语法&#xff08;2&#xff09;输出语句 2、变量&#xff08;1&#xff09;变量&#xff08;2&#xff09;注意事项 3、数据类型、运算符、流…

spring-数据处理及跳转

结果跳转方式 ModelAndView 设置ModelAndView对象 , 根据view的名称 , 和视图解析器跳到指定的页面 . 页面 : {视图解析器前缀} viewName {视图解析器后缀} <!-- 视图解析器 --> <bean class"org.springframework.web.servlet.view.InternalResourceViewRes…

Java定时任务

一、java.util.Timer java.util.Timer 类允许您在未来的某个时间执行一个任务&#xff0c;或者在一定的时间间隔执行任务。您可以创建一个 Timer 实例&#xff0c;并调用其 schedule() 方法来安排任务的执行。这种方式比较简单&#xff0c;但在高并发环境下可能不够灵活。 1.…

Git学习与码云实战

Git学习与码云实战 Git安装 概述&#xff1a; Git 是一个开源的分布式版本控制系统&#xff0c;可以有效、高速的处理从很小到非常大的项目版本管理&#xff0c;是目前使用范围最广的版本管理工具。 下载安装&#xff1a; 下载地址&#xff1a;https://git-scm.com/ 下载后傻瓜…

李彦宏:开源模型会越来越落后

李彦宏&#xff1a;开源模型会越来越落后 昨天听完的李总讲座 大家以前用开源觉得开源便宜&#xff0c;其实在大模型场景下&#xff0c;开源是最贵的。所以&#xff0c;开源模型会越来越落后。 ——李彦宏 至于开源还是闭源&#xff0c;这和企业的利益息息相关。 随着科技的迅猛…

双向链表详解

一.双向链表结构 我们一般所说的双向链表是带头循环双向链表&#xff0c;这里的带头更我们之前的头节点不是一回事。带头链表里的头节点&#xff0c;实际上为哨兵位&#xff0c;哨兵位的头节点种是不存放任何有效数据的&#xff0c;只是站在这里起到放哨的作用。 哨兵位的意义…

【C++从练气到飞升】08---模板

&#x1f388;个人主页&#xff1a;库库的里昂 ✨收录专栏&#xff1a;C从练气到飞升 &#x1f389;鸟欲高飞先振翅&#xff0c;人求上进先读书。 目录 一、泛型编程 什么是泛型编程: 二、函数模板 1. 函数模板概念 2. 函数模板格式 3. 函数模板的原理 4. 函数模板的实例…
最新文章