EasyExcel实现excel导入(模版上传)

目录

  • 效果
  • pom.xml
  • application.yml
  • controller
  • service
  • 依赖类
  • 前台
    • vue代码

某个功能如果需要添加大量的数据,通过一条条的方式添加的方式,肯定不合理,本文通过excel导入的方式来实现该功能,100条数据导入成功85条,失败15条,肯定需要返回一个表格给前台或者返回1个错误excel给前台,本文就实现这两个功能

效果

在这里插入图片描述

  • 模版 storeTemplate.xlsx
    在这里插入图片描述

在这里插入图片描述

  • 点击确定,会直接下载excel错误文件,打开如下图
    在这里插入图片描述
  • 删除第一行 第一列后,修正后,可再次导入,方便调整错误数据

pom.xml

<!-- easypoi-spring-boot-starter -->
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-spring-boot-starter</artifactId>
            <version>4.1.3</version>
        </dependency>

application.yml

#####模板下载位置
downloadTemplate:
  storePath: storeTemplate.xlsx
  • 提供部分代码,主要是了解思路,可参考实现

controller

package com.zyee.iopace.web.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageInfo;
import com.zyee.iopace.web.config.annotation.Log;
import com.zyee.iopace.web.config.exception.BusinessException;
import com.zyee.iopace.web.dto.station.DeleteBatchPhotoDto;
import com.zyee.iopace.web.dto.station.StationStoreAddDto;
import com.zyee.iopace.web.dto.station.StationStoreDto;
import com.zyee.iopace.web.dto.store.DeleteStoreBatchPhotoDto;
import com.zyee.iopace.web.dto.store.StationStoreUpdateDto;
import com.zyee.iopace.web.dto.store.StoreBindStationDto;
import com.zyee.iopace.web.dto.store.StoreChangeTrackDto;
import com.zyee.iopace.web.entity.*;
import com.zyee.iopace.web.enums.BusinessType;
import com.zyee.iopace.web.enums.EcologyType;
import com.zyee.iopace.web.enums.StationStateEnum;
import com.zyee.iopace.web.enums.StoreStatusType;
import com.zyee.iopace.web.response.ResponseResult;
import com.zyee.iopace.web.service.*;
import com.zyee.iopace.web.utils.BeanCopyUtils;
import com.zyee.iopace.web.utils.PageUtils;
import com.zyee.iopace.web.vo.station.StationStoreDetailVo;
import com.zyee.iopace.web.vo.station.StationStoreVo;
import com.zyee.iopace.web.vo.store.StoreChangeTrackListVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Api(tags = "库存管理")
@RestController
@RequestMapping("/stationStore")
public class StationStoreController {
   
    @Autowired
    private StoreReviseRecordService storeReviseRecordService;

    @ApiOperation(value = "导入库存信息")
    @Log(title = "导入库存信息", businessType = BusinessType.IMPORT)
    @PostMapping("/importStore")
    public ResponseResult importStore(@RequestParam MultipartFile file, HttpServletResponse response) throws Exception {
   
        return ResponseResult.SUCCESS(stationStoreService.importStore(file,response));
    }
}

service

package com.zyee.iopace.web.service;

import com.zyee.iopace.web.dto.dept.DeptSearchDto;
import com.zyee.iopace.web.dto.station.StationStoreAddDto;
import com.zyee.iopace.web.dto.station.StationStoreDto;
import com.zyee.iopace.web.dto.store.StationStoreUpdateDto;
import com.zyee.iopace.web.dto.store.StoreBindStationDto;
import com.zyee.iopace.web.dto.store.StoreChangeTrackDto;
import com.zyee.iopace.web.entity.StationStore;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zyee.iopace.web.entity.StoreChangeTrack;
import com.zyee.iopace.web.vo.element.ElementImportResponseVo;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.List;

public interface StationStoreService extends IService<StationStore> {
   
    /**
     *  导入库存信息
     * @param file
     * @param response
     * @return  失败返回错误地址
     */
    ElementImportResponseVo importStore(MultipartFile file, HttpServletResponse response) throws Exception;
}




@Service
public class StationStoreServiceImpl extends ServiceImpl<StationStoreMapper, StationStore> implements StationStoreService {
   
	   @Override
    public ElementImportResponseVo importStore(MultipartFile file, HttpServletResponse response) throws Exception {
   
        List<StoreImportVo> stationImportVos = PoiUtils.importExcel(file, StoreImportVo.class, null);
        //成功
        List<StationStore> stationStoreList = new ArrayList<>();
        //失败信息的集合
        List<StoreImportVo> errorList = new ArrayList<>();

        //导入成功的数量
        int success = 0;
        //失败条数
        int failure = 0;

        //当前登录用户id
        String userId = userUtils.getUserId();

        //型号
        List<StoreCompanyModel> companyModelList = storeCompanyModelService.list();

        //序列号集合
        List<StationStore> stationStores = list(new LambdaQueryWrapper<StationStore>().select(StationStore::getSerialNumber));
        List<String> serialNumberList = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(stationStores)){
   
            serialNumberList = stationStores.stream().map(StationStore::getSerialNumber).distinct().collect(Collectors.toList());
        }

        //站点集合
        List<Station> stationList = stationService.list(new LambdaQueryWrapper<Station>().orderByAsc(Station::getStationCode));
        if(CollectionUtil.isEmpty(stationList)){
   
            stationList = new ArrayList<>();
        }

        for (StoreImportVo storeImport : stationImportVos) {
   
            StringBuilder errMsg = new StringBuilder();

            StationStore stationStore = checkStore(storeImport, errMsg, userId, companyModelList, serialNumberList, stationList);
            if (errMsg.toString().length() > 0) {
   
                failure++;
                storeImport.setErrorCause(errMsg.toString());
                errorList.add(storeImport);
            }else{
   
                success++;
                stationStoreList.add(stationStore);
            }
        }

        if(CollectionUtil.isNotEmpty(stationStoreList)){
   
            //批量新增
            saveBatch(stationStoreList);

            //增加送检判断
            stationStoreList.stream().forEach(store->{
   
                if(Objects.nonNull(store.getRectifyTime())){
   
                    //库存送检记录
                    StationStoreAddDto dto = new StationStoreAddDto();
                    dto.setRectifyTime(store.getRectifyTime());
                    saveRevise(dto, store);
                }

                if(Objects.nonNull(store.getStationId())){
   
                    //绑定站点
                    stationChangeTrack(null, store);
                }
            });
        }

        //将错误数据上传
        String visitUrl = "";
        String msg = "批量站点信息完成,成功导入" + success + "条数据,失败" + failure  + "条";
        if (failure > 0) {
   
            try {
   
                String name = UUID.randomUUID()+".xlsx";
                Workbook workbook = null;

                StoreExcelStyler.setProperties(stationService,storeCompanyService,storeCompanyModelService);
                workbook = PoiUtils.exportErrorExcel(errorList, name, name,
                        StoreImportVo.class, name, StoreExcelStyler.class, response);
                StoreExcelStyler.setData(workbook);
                FileOutputStream outputStream = new FileOutputStream(pathService.getAbsoTemplateExcelPath(name));
                //写入
                workbook.write(outputStream);

                visitUrl = pathService.getTemplateExcelPath(name);
            } catch (Exception e) {
   
                e.printStackTrace();
            }
        }

        ElementImportResponseVo vo = new ElementImportResponseVo();
        vo.setMsg(msg);
        vo.setVisitUrl(visitUrl);
        return vo;
    }


      /**
     * 验证格式有问题
     * @param storeImport
     * @param errMsg
     * @param userId
     * @return
     */
    private StationStore checkStore(StoreImportVo storeImport, StringBuilder errMsg, String userId,
                                    List<StoreCompanyModel> companyModelList,
                                    List<String> serialNumberList,
                                    List<Station> stationList) {
   
        StationStore store = new StationStore();

        if(StringUtils.isBlank(storeImport.getCompanyName(

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

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

相关文章

BFS算法——层层推进,最短之路,广度优先搜索算法的诗意旅程(下)

文章目录 引言一. 迷宫中离入口最近的出口1.1 题目链接&#xff1a;https://leetcode.cn/problems/nearest-exit-from-entrance-in-maze/1.2 题目分析&#xff1a;1.3 思路讲解&#xff1a;1.4 代码实现: 二. 最小基因变化2.1 题目链接&#xff1a;https://leetcode.cn/problem…

Linux----Makefile基础

Makefile 是自动化构建工具 make 的配置文件&#xff0c;用于定义编译规则和依赖关系&#xff0c;实现高效增量编译。 初识makefile 1. 什么是 make&#xff1f; 定义&#xff1a; make 是一个命令行工具&#xff08;可执行程序&#xff09;&#xff0c;用于解析并执行 Makef…

leetcode876.链表的中间结点

目录 问题描述示例提示 具体思路思路一 代码实现 问题描述 给你单链表的头结点 head &#xff0c;请你找出并返回链表的中间结点。 如果有两个中间结点&#xff0c;则返回第二个中间结点。 题目链接&#xff1a;链表的中间结点 示例 提示 链表的结点数范围是 [1, 100]   1 &…

设计变更滞后导致生产计划混乱?PLM与MES集成实时同步

当产品设计在PLM系统中发生变更时&#xff0c;这些变更信息却无法及时、准确地传递到MES系统中。结果是&#xff0c;车间生产现场仍然按照旧的设计指令执行&#xff0c;导致生产出的产品与设计要求不符&#xff0c;不仅引发质量问题&#xff0c;还可能造成停工、物料浪费甚至客…

20250220解决使用top指令查看荣品PRO-RK3566开发板的CPU占用率为400%的问题

20250220解决使用top指令查看荣品PRO-RK3566开发板的CPU占用率为400%的问题 2025/2/20 19:14 缘起&#xff0c;使用荣品PRO-RK3566开发板配套的百度网盘中的SDK&#xff1a;Android13编译之后&#xff0c;查看RK3566的CPU占用率为400%。 开机就是400%&#xff0c;什么时候都是4…

巧用GitHub的CICD功能免费打包部署前端Node项目

近年来&#xff0c;随着前端技术的发展&#xff0c;前端项目的构建和打包过程变得越来越复杂&#xff0c;占用的资源也越来越多。我有一台云服务器&#xff0c;原本打算使用Docker进行部署&#xff0c;以简化操作流程。然而&#xff0c;只要执行sudo docker-compose -f deploy/…

web 通识3

目录 6 通向3.0区块链技术前沿发展 7.主流区块链项目介绍 9.区块链行业应用总览 6 通向3.0区块链技术前沿发展 隔离见证&#xff1a;将一部分信息放在别的地方&#xff0c;这样原本的地方就可以容纳更多的东西 隔离见证和树图都是通过扩大容量来提高性能 闪电网络&#xf…

Hadoop一 HDFS分布式文件系统

一 分布式文件存储 了解为什么海量数据需要使用分布式存储技术 100T数据太大&#xff0c;单台服务器无法承担。于是&#xff1a; 分布式服务器集群 靠数量取胜&#xff0c;多台服务器组合&#xff0c;才能Hold住&#xff0c;如下 分布式不仅仅是解决了能存的问题&#xff…

java练习(33)

ps:题目来自力扣 最强回文子串 给你一个字符串 s&#xff0c;找到 s 中最长的 回文 子串。 class Solution {public String longestPalindrome(String s) {if (s null || s.length() < 1) {return "";}int start 0, end 0;for (int i 0; i < s.length();…

分布式大语言模型服务引擎vLLM论文解读

论文地址&#xff1a;Efficient Memory Management for Large Language Model Serving with PagedAttention 摘要 大语言模型&#xff08;LLMs&#xff09;的高吞吐量服务需要一次对足够多的请求进行批处理。然而&#xff0c;现有系统面临困境&#xff0c;因为每个请求的键值…

日期类(完全讲解版)

1. 类的设计思想 Date 类的设计目的是为了封装和处理日期信息&#xff0c;它提供了对日期的基本操作&#xff0c;如日期加减、日期比较、日期合法性检查等。类中的私有成员 int _year, int _month, int _day 存储了日期的年、月、日。 类的声明和构造 Date 类的声明&#xff1…

微信小程序(uni)+蓝牙连接+Xprint打印机实现打印功能

1.蓝牙列表实现&#xff0c;蓝牙设备展示&#xff0c;蓝牙连接 <template><view class"container"><view class"container_top"><view class"l">设备名称</view><view class"r">{{state.phoneNam…

zookeeper集群配置

配置 一、配置myid文件 # 进入解压好的文件夹下面 touch myid vim myid # master节点写0&#xff0c;slave1节点写1&#xff0c;slave2节点写2二、配置zoo.cfg文件 1.在master节点编辑zookeeper配置文件 # 进入解压好的文件夹下面 cd conf/ cp zoo_sample.cfg zoo.cfg vim …

C++ Primer 类的静态成员

欢迎阅读我的 【CPrimer】专栏 专栏简介&#xff1a;本专栏主要面向C初学者&#xff0c;解释C的一些基本概念和基础语言特性&#xff0c;涉及C标准库的用法&#xff0c;面向对象特性&#xff0c;泛型特性高级用法。通过使用标准库中定义的抽象设施&#xff0c;使你更加适应高级…

Ubuntu 服务器Llama Factory 搭建DeepSeek-R1微调训练环境

1.首先了解一下什么是LLM微调 LLM 微调指的是在已经预训练好的大型语言模型基础上&#xff0c;使用特定的任务数据或领域数据&#xff0c;通过进一步的训练来调整模型的参数&#xff0c;使其在特定任务或领域上能够表现得更好。简单来说&#xff0c;就是对一个已经具备了丰富语…

C++17 中的 std::to_chars 和 std::from_chars:高效且安全的字符串转换工具

文章目录 1. 传统转换方法的局限性2. std::to_chars&#xff1a;数值到字符串的高效转换函数原型&#xff1a;返回值&#xff1a;示例代码&#xff1a;输出&#xff1a; 3. std::from_chars&#xff1a;字符串到数值的高效解析函数原型&#xff1a;返回值&#xff1a;示例代码&…

【Alertmanager】alertmanager告警系统原理剖析与应用实战,应有尽有非常全面

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…

VScode 使用Deepseek又方便又好用的另一款插件

一、Continue continue类似于copilot&#xff0c;包含5大核心功能&#xff1a;AI对话编程、代码自动补全、代码智能编辑、上下文提供器、快捷键操作&#xff0c;能满足编程的大部分需求。 在AI大模型的支持上&#xff0c;continue能连接包括DeepSeek、OpenAI、Claude在内的十…

互联网 Java 工程师面试题(Java 面试题五)

JVM 底层 与 GC&#xff08;Garbage Collection&#xff09; 的面试问题 31、64 位 JVM 中&#xff0c;int 的长度是多数&#xff1f; Java 中&#xff0c;int 类型变量的长度是一个固定值&#xff0c;与平台无关&#xff0c;都是 32 位。意思就 是说&#xff0c;在 32 位 和 6…

【设计模式精讲】创建型模式之工厂方法模式(简单工厂、工厂方法)

文章目录 第四章 创建型模式4.2 工厂方法模式4.2.1 需求: 模拟发放奖品业务4.2.2 原始开发方式4.2.3 简单工厂模式4.2.3.1 简单工厂模式介绍4.2.3.2 简单工厂原理4.2.3.3 简单工厂模式重构代码4.2.3.4 简单工厂模式总结 4.2.4 工厂方法模式4.2.4.1 工厂方法模式介绍4.2.4.2 工厂…