通过Easy Excel导入数据

news/2024/7/21 7:03:36 标签: excel, easyexcel, poi

目录

  • 🍑一、背景
  • 🍑二、开发验证
    • 🍊2.1、引入easyexcel依赖
    • 🍊2.2、创建表及基础代码
    • 🍊2.3、处理类及接口
      • 🍓2.3.1、EasyExcel监听处理器
      • 🍓2.3.2、Controller接口
      • 🍓2.3.3、service调用监听器
    • 🍊2.4、启动项目,通过swagger接口测试
      • 🍓2.4.1、上传excel
      • 🍓2.4.2、excel详情
      • 🍓2.4.3、查看数据库验证
  • 🍑三、其它

🔼上一集:小钊记

🍑一、背景


大概2023年7月6号,整了一个180天倒计时(距离2024元旦),设定了一些计划,通过腾讯在线文档记录每天完成情况。突然想起来,今年五一的时候,搭建了一个系统,就是上面的小钊记,想着要不把180天倒计时计划表导入数据库,之前也做过解析excel,是通过poi,springboot 解析Excel(栏位与实体类一一对应),这次改用Easy Excel试一下,听名字就感觉比较简单。
在这里插入图片描述

🍑二、开发验证


excel_11">🍊2.1、引入easyexcel依赖


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

🍊2.2、创建表及基础代码


  • 日常记录表
    DROP TABLE IF EXISTS `t_rxz_daily_record`;
    create table t_rxz_daily_record
    (
        id                     int not null auto_increment comment '主键',
        record_date            Date not null comment '记录日期',
        wake_up_time           time not null comment '起床时间',
        lunch_break_duration   varchar(50) not null comment '午休时长',
        hunger_before_bedtime  varchar(50) not null comment '睡前饿意',
        motion                 varchar(50) not null comment '运动',
        learning               varchar(50) not null comment '学习',
        sleep_time             varchar(50) not null comment '睡觉时间',
        explosive_red_rate     varchar(50) not null comment '爆红率',
        net_weight             FLOAT not null comment '净重',
        update_time            datetime default CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP comment '更新时间',
        primary key (id)
    );
    
  • 基础代码
    • entity

      package com.renxiaozhao.bean.entity;
      
      import java.io.Serializable;
      import java.sql.Time;
      import java.util.Date;
      
      import com.baomidou.mybatisplus.annotation.TableName;
      
      import io.swagger.annotations.ApiModelProperty;
      import lombok.Data;
      
       /**
       * 日常记录表实体.
       * @author : 韧小钊
       * @date : 2023-8-10
       */
      @Data
      @TableName("t_rxz_daily_record")
      public class DailyRecordEntity implements Serializable {
          private static final long serialVersionUID = 5252694875850308782L;
          
          /** 主键 */
          @ApiModelProperty(name = "主键",notes = "")
          private Integer id ;
          /** 记录日期 */
          @ApiModelProperty(name = "记录日期",notes = "")
          private Date recordDate ;
          /** 起床时间 */
          @ApiModelProperty(name = "起床时间",notes = "")
          private Time wakeUpTime ;
          /** 午休时长 */
          @ApiModelProperty(name = "午休时长",notes = "")
          private String lunchBreakDuration ;
          /** 睡前饿意 */
          @ApiModelProperty(name = "睡前饿意",notes = "")
          private String hungerBeforeBedtime ;
          /** 运动 */
          @ApiModelProperty(name = "运动",notes = "")
          private String motion ;
          /** 学习 */
          @ApiModelProperty(name = "学习",notes = "")
          private String learning ;
          /** 睡觉时间 */
          @ApiModelProperty(name = "睡觉时间",notes = "")
          private String sleepTime ;
          /** 爆红率 */
          @ApiModelProperty(name = "爆红率",notes = "")
          private String explosiveRedRate ;
          /** 净重 */
          @ApiModelProperty(name = "净重",notes = "")
          private Float netWeight ;
          /** 更新时间 */
          @ApiModelProperty(name = "更新时间",notes = "")
          private Date updateTime ;
          
      }
      
    • mapper

      package com.renxiaozhao.dao.mapper;
      
      import com.baomidou.mybatisplus.core.mapper.BaseMapper;
      import com.renxiaozhao.bean.entity.DailyRecordEntity;
      
      
      public interface DailyRecordMapper extends BaseMapper<DailyRecordEntity>{}
      
      
      
    • service接口及实现类

      package com.renxiaozhao.service.impl;
      
      import org.springframework.stereotype.Service;
      
      import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
      import com.renxiaozhao.bean.entity.DailyRecordEntity;
      import com.renxiaozhao.dao.mapper.DailyRecordMapper;
      import com.renxiaozhao.service.inf.DailyRecordService;
      
      @Service
      public class DailyRecordServiceImpl extends ServiceImpl<DailyRecordMapper, DailyRecordEntity>  implements DailyRecordService {}
      
      
      
      package com.renxiaozhao.service.inf;
      
      import com.baomidou.mybatisplus.extension.service.IService;
      import com.renxiaozhao.bean.entity.DailyRecordEntity;
      
      public interface DailyRecordService  extends IService<DailyRecordEntity>   {
          
      }
      
      
      

🍊2.3、处理类及接口


🍓2.3.1、EasyExcel监听处理器


  • 读取监听器(ReadListener): 在读取 Excel 文件之前,可以使用 BeforeReadListener 接口来处理读取开始前的事件。在每次读取一行数据时,可以使用 ReadListener 接口的 onRead 方法来处理读取到的数据。在读取完成后,可以使用 AfterReadListener 接口来处理读取结束后的事件。
  • 写入监听器(WriteListener): 在写入 Excel 文件之前,可以使用 BeforeWriteListener 接口来处理写入开始前的事件。在每次写入一行数据时,可以使用 WriteListener 接口的 onWrite 方法来处理要写入的数据。在写入完成后,可以使用 AfterWriteListener 接口来处理写入结束后的事件。
    分析监听器(AnalysisEventListener):
  • AnalysisEventListener: 是一种用于读取大量数据时的监听器接口。您可以实现 AnalysisEventListener 接口,并在 onRead 方法中处理读取到的每一行数据。EasyExcel 会将读取的数据分批处理,以减少内存消耗。

目前只用到了读取监听器,代码如下:

package com.renxiaozhao.service.impl;

import java.sql.Time;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.renxiaozhao.bean.entity.DailyRecordEntity;
import com.renxiaozhao.service.util.DateUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * 初始化表格数据.
 */
@Slf4j
public class ExcelListener implements ReadListener<LinkedHashMap<Integer, String>> {

    List<DailyRecordEntity> dailyRecords = new ArrayList<>();

    @Override
    public void invoke(LinkedHashMap<Integer, String> rowData, AnalysisContext context) {
        DailyRecordEntity record = new DailyRecordEntity();
        try {
            // 记录日期
            record.setRecordDate(DateUtils.parseDate(rowData.get(0)));
            // 起床时间
            record.setWakeUpTime(Time.valueOf(rowData.get(1) + ":00"));
            // 午休时长
            record.setLunchBreakDuration(rowData.get(2));
            // 睡前饿意
            record.setHungerBeforeBedtime(rowData.get(3));
            // 运动
            record.setMotion(rowData.get(4));
            // 学习
            record.setLearning(rowData.get(5));
            // 睡觉时间
            record.setSleepTime(rowData.get(6));
            // 爆红率
            record.setExplosiveRedRate(rowData.get(7));
            // 净重
            record.setNetWeight(Float.parseFloat(rowData.get(8)));
        } catch (ParseException e) {
            log.error(rowData + "参数转化格式失败:",e);
        }
        dailyRecords.add(record);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {

    }

    public List<DailyRecordEntity> getDailyRecords() {
        return dailyRecords;
    }
    
}

🍓2.3.2、Controller接口


@PostMapping("/exportRecord")
    @ApiOperation(value = "导入每日记录信息", notes = "导入每日记录信息")
    public Result<String> exportRecord(@RequestParam("file") MultipartFile file) {
        try {
            sportRecordService.exportRecord(file);
            return Result.success();
        } catch (Exception e) {
            log.error("导入记录数据异常", e);
            return Result.error("导入记录数据异常" + e.getMessage());
        }
    }

在这里插入图片描述

🍓2.3.3、service调用监听器


支持多个sheet,每遍历完一个记得清空数据,图中listener.getDailyRecords().clear() 是在清空 listener 对象中的 dailyRecords 数据,以便在处理下一个 sheet 时,相关数据不会重叠或占用过多的内存。
在这里插入图片描述

@Override
    public void exportRecord(MultipartFile file) {
        String message = "共导入%s个月记录,成功%s,失败%s";
        StringBuilder failMessages = new StringBuilder();
        InputStream inputStream = null;
        ExcelReader excelReader = null;
        try {
            inputStream = file.getInputStream();
            ExcelListener listener = new ExcelListener();
            excelReader = EasyExcel.read(inputStream).registerReadListener(listener).build();
            //获取sheet页
            List<ReadSheet> readSheets = excelReader.excelExecutor().sheetList();
            int success = 0;
            int fail = 0;
            for (ReadSheet readSheet : readSheets) {
                String sheetName = readSheet.getSheetName();
                //读取excel数据
                excelReader.read(readSheet);
                List<DailyRecordEntity> records = listener.getDailyRecords();
                try {
                    if (records != null && records.size() > 0) {
                        //保存表信息
                        boolean flag = dailyRecordService.saveBatch(records);
                        if (flag) {
                            success++;
                        }
                    }
                } catch (Exception e) {
                    log.error("插入数据错误", e);
                    failMessages.append("sheet ").append(sheetName).append(":").append(e.getMessage()).append(";");
                    fail++;
                } finally {
                    listener.getDailyRecords().clear();
                }
            }
            message = String.format(message, success + fail, success, fail);
            if (!StringUtils.isEmpty(failMessages.toString())) {
                log.error(failMessages.toString());
            }
        } catch (Exception e) {
            log.error("读取文件失败", e);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.error("读取文件失败", e);
                }
            }
            if (excelReader != null) {
                excelReader.finish();
            }
        }
    }

🍊2.4、启动项目,通过swagger接口测试


excel_297">🍓2.4.1、上传excel


在这里插入图片描述

excel_300">🍓2.4.2、excel详情


导出腾讯在线文档,按照月份划分sheet,详情如下:

  • 7月
    在这里插入图片描述- 8月
    在这里插入图片描述

🍓2.4.3、查看数据库验证


成功登记了7、8月份的数据
在这里插入图片描述

🍑三、其它


确实简单好用!!!


http://www.niftyadmin.cn/n/4930700.html

相关文章

机器学习笔记值优化算法(十四)梯度下降法在凸函数上的收敛性

机器学习笔记之优化算法——梯度下降法在凸函数上的收敛性 引言回顾&#xff1a;收敛速度&#xff1a;次线性收敛二次上界引理 梯度下降法在凸函数上的收敛性收敛性定理介绍证明过程 引言 本节将介绍梯度下降法在凸函数上的收敛性。 回顾&#xff1a; 收敛速度&#xff1a;次…

Netty学习一

一、什么是Netty Netty是一个基于Java的异步事件驱动的网络应用程序框架&#xff0c;它用于快速开发高性能、可扩展的网络服务器和客户端应用程序。 Netty的设计目标是提供简单、高效的API&#xff0c;并且具备良好的性能、可靠性和可扩展性。 Netty的主要特点包括&#xff1…

实践指南-前端性能提升 270% | 京东云技术团队

一、背景 当我们疲于开发一个接一个的需求时&#xff0c;很容易忘记去关注网站的性能&#xff0c;到了某一个节点&#xff0c;猛地发现&#xff0c;随着越来越多代码的堆积&#xff0c;网站变得越来越慢。 本文就是从这样的一个背景出发&#xff0c;着手优化网站的前端性能&a…

P5735 【深基7.例1】距离函数

题目描述 给出平面坐标上不在一条直线上三个点坐标 ( x 1 , y 1 ) , ( x 2 , y 2 ) , ( x 3 , y 3 ) (x_1,y_1),(x_2,y_2),(x_3,y_3) (x1​,y1​),(x2​,y2​),(x3​,y3​)&#xff0c;坐标值是实数&#xff0c;且绝对值不超过 100.00&#xff0c;求围成的三角形周长。保留两…

tornado如何在网页模板中显示字典

要在 Tornado 的网页模板中显示字典的键和值&#xff0c;你可以使用 Tornado 内置的模板引擎 tornado.template 来处理。下面是一个简单的示例&#xff1a; 首先&#xff0c;确保你已经安装了 Tornado 模块。你可以使用以下命令进行安装&#xff1a; pip install tornado创建…

昂贵的聘礼

题目链接 思路&#xff1a;每个替代物品就可以降低成本&#xff0c;可以在代替物品和被代替物品之间连一条边&#xff0c;边权为折后价&#xff0c;然后判断从每个物品出发到达物品1的最小总成本是多少&#xff0c;所以可以创建一个超级源点&#xff0c;然后在超级源点与每个物…

【LeetCode】买卖股票的最佳时机含冷冻期

买卖股票的最佳时机含冷冻期 题目描述算法分析程序设计 链接: 买卖股票的最佳时机含冷冻期 题目描述 算法分析 程序设计 class Solution { public:int maxProfit(vector<int>& prices) {int n prices.size();//天数vector<vector<int>> dp(n,vector&l…

Vue + MapBox快速搭建

一、说明&#xff1a; 1.mapbox-gl自2.0版本开始不再开源&#xff0c;需要用户在官网申请key使用。 2.maplibre GL JS是一个开源库&#xff0c;它起源于 mapbox-gl-js 的开源分支。该库的初始版本&#xff08;1.x&#xff09;旨在替代Mapbox的OSS版本。简单来说maplibre是mapb…