Excel+vue+java实现批量处理功能

news2024/11/24 8:12:45

需求背景:
产品创建流程比较复杂,有时候需要一次性创建多至10+个,所以做了Excel维护产品信息,直接导入创建的功能。能极大提高效率。

简要概括实现:
一、参考单个创建,设计创建模板,表头对应填写字段名,后续每一行为每一个创建对象填写参数值。
二、页面添加批量创建按钮,实现点击时打开批量上传窗口。
三、添加窗口采用el-dialog组件,点击确定调批量处理接口。
四、前端实现批量操作窗口各种操作函数(上传文件、取消、确定)。
五、后端增加批量处理接口。
六、实现处理接口:循环读表数据调单个处理接口,并包装创建结果返回前端。

具体如下。
一、参考单个创建,设计创建模板,表头对应填写字段名,后续每一行为每一个创建对象填写参数值。如图:
在这里插入图片描述

二、页面添加批量创建按钮,实现点击时打开批量上传窗口。
页面对应.vue文件样式增加代码:

<el-button type="primary" size="mini" @click="openUploadFileDialog">批量创建</el-button>
<e-link type="primary'href="/template/批量创建产品模板.xlsx" download="批量创建产品模板.xlsx">下载文件模板</e-ink>

三、添加窗口采用el-dialog组件,点击确定调批量处理接口。
页面对应.vue文件样式增加代码:

<div>
<div>
<el-dialog
title="批量创建"
:visible.sync="dialogVisible"
width="30%">

<span>
<el-upload
class="upload-demo"
ref="createProdlnBulk"
drag
:action="uploadURL" // 批量创建接
accept=".xlsx,.xls" // 限制文件类型
:auto-upload="false
:limit="1"
:file-list="fileList" //定义file-list接收文件,上传成功后清空
:on-success="handleFilUploadSuccess" // 上传成功后调用
:before-upload="beforeUpload" // 选中文件后调用
<i class="el-icon-upload"></i>
<div class="el-upload_text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload_tip"slot="tip">只能上传 excel 文件,且不超过500kb</div>
</el-upload></span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleUpload()">确定</ el-button>
</span></el-dialog></div>

四、前端实现批量操作窗口各种操作函数。
页面对应.vue文件js脚本增加代码:

<script>
import { createProd} from'@/api/prod'
import request from@/utils/request'
import'@/utils/dialog' 
data() {
 return {
response:'',
// 如果是多环境,可以获取基础url地址+接口设置上传地址
uploadURL:request.defaults.baseURL+'/ xxx/createProdlnBulk',
dialogVisible: false, 
fileList:[],
},
methods:{
// 文件上传成功时的函数 
handleFilUploadSuccess(res,file,fileList) {
// console.log(res,file,fileList)
$message.success("创建完成")
console.log("res.data")
// 接收响应数据,可用于展示在页面
this.response = res.data
// 上传成功后跳到responseTab页( <el-container>组件的特性),并展示响应数据
this.activeName ='responseTab'
// 重置文件 this.fileList =[]
},
openUploadFileDialog (){ 
this.dialogVisible=true;
},
beforeUpload(file) {
// 拦截下非Excel文件 
const isExcel =file.type==='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' || file.type==='application/vnd.ms-excel';
if (!isExcel) {
this.$message.error('只能上传Excel文件!');
return isExcel;
},
handleRemove(file,fileList){
console.log(file,fileList);
},
submitUpload(){
this.$refs.createProdInBulk.submit();
},
}}
</script>

五、后端增加批量处理接口。
controller层增加代码:

@RequestMapping(value= {"/{env}/xxx/createProdlnBulk"},method=RequestMethod.POST)
 public ResponseInfo createProdlnBulk(@PathV ariable String env, @Valid FileWorkDTO fileWorkDTO, HttpServletRequest request,@RequestParam("file") MultipartFile file) throws IOException {
return createProdServicelmpl.createProdlnBulk(env, file);
}

六、实现处理接口:循环读表数据调单个处理接口,并包装创建结果返回前端。
createProdServicelmpl类增加代码:

public ResponseInfo createProdlnBulk(String env, MultipartFile file) throws BizException,IOException{
// System.out.println("request=" + httpRequest);
System.out.println("file.toString() ="+ file.toString());
String allRes ="批量创建结果:";  // 响应内容
// 获取文件数据流 
try (
InputStream inputStream =file.getlnputStream()Workbook workbook= WorkbookFactory.create(inputStream);
Sheet sheet =workbook.getSheetAt(0);
Iterator<Row> rowIterator = sheet.iterator();
rowIterator.next(); //跳过表头
Row headerRow = sheet.getRow(0); // 获取表头行
// 遍历文件所有行(表头行除外)
while(rowlterator.hasNext()){
Row row =
rowIterator.next();
if(isRowEmpty(row)) {
continue; // 如果整行数据为空,则跳过
}
//当前行数据检查:空值检查、Date相关字段检查
Iterator<Cell> cellIterator1 = row.cellIterator();
while(cellIterator1.hasNext()){
Cell cell =cellIterator1.next();
if(cell.getStringCellValue().isEmpty()){
return newResponselnfo(RetCode.ERROR_CODE,RetCode.ERROR_MSG,cell.getColumnIndex()+"列数据为空");
String value =cell.getCellTypeEnum().toString().equals("STRING") ? cell.getStringCellValue():String.valueOf(cell.getNumericCellValue());
if(headerRow.getCell(cell.getColumnIndex()).getStringCellValue().contains("Date") && value.length() != 8){
System.out.println("key+value = " + header Row.getCell(cell.getColumn Index()).getStringCellValue()+value);
return newResponselnfo(RetCode.ERROR_CODE,"表格类型或值错误","表格类型或值错误");
}
// 获取当前行全部字段值(如果模板字段跟创建接口字段统一,直接遍历获取就行,比较方便)
Map<String,Object> request = new HashMap<>();
Iterator<Cell> cellIterator =
row.cellIterator();
while(cellIterator.hasNext()){
Cell cell =cellIterator.next();
if(cell.getStringCellValue().isEmpty()){
// return newResponselnfo(RetCode.ERR OR_CODE,RetCode.ERROR_ MSG,cell.getColumnIndex()+"列数据为空");//
}
System.out.println("headerR ow.getCell(cell.getColumnlndex()).getStringCellValue()=" +headerRow.getCell(cell.getColumnIndex()).getStringCellValue());
String value =cell.getCellTypeEnum().tostring().equals("STRING") ? cell.getStringCellValue(): String.valueOf(cell.getNumericCellValue());
request.put(headerRow.getCell(cell.getColumnIndex()).getStringCellValue(),value);
// 调用单个创建接口,创建产品
request.put("createType","1");
request.put("requestld","createProdinBulk-" + DateUtil.getUUID());
insertOprLog(env,request); // 插入操作历史记录
Responselnfo<T>res = createProd("fat",request);// 调用创建产品的逻辑
// 收集单个创建结果
allRes +=res.getData() +"\n";
System.out.println("res.getData()="+ res.getData());
}
// 更新历史记录结果 
updateOprLog(jsonResponse, request.get("reque stld").toString());
} catch (Exception e) {
e.printStackTrace(); 
return new Response Info(RetCode.ERROR_CODE, RetCode.ERROR_MSG, allRes);
}
return new Responselnf o(RetCode.SUCCESS_CODE, RetCode.SUCCESS_MSG, allRes);
}

七、一些坑。
1>、上传后文件未清除,每次要点x再重新上传。
解决:定义 fileList 接收文件,上传成功后把fileList清空。具体:
el-dialog组件加: file-list=“fileList”
return {}中加 fileList 定义
handleFilUploadSuccess()函数里,把fileList清空。

2>、Excel表的单元格数据获取失败,报格式错误。是因为单元格默认格式有可能是number值,统一用 STRING获取就会异常。
解决方案:
//单元格值获取

String value =cell.getCellTypeEnum().toString().equals("STRING") ?cell.getStringCellValue():String.valueOf(cell.getNume ricCellValue());

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

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

相关文章

Go使用Gin框架开发的Web程序部署在Linux时,无法绑定监听Ipv4端口

最近有写一部分go语言开发的程序&#xff0c;在部署程序时发现&#xff0c;程序在启动后并没有绑定ipv4的端口&#xff0c;而是直接监听绑定ipv6的端口。 当我用netstat -antup | grep 3601查找我的gin服务启动的端口占用情况的时候发现&#xff0c;我的服务直接绑定了tcp6 &a…

容易涨粉的视频素材有哪些?容易涨粉的爆款短素材库网站分享

如何挑选社交媒体视频素材&#xff1a;顶级视频库推荐 在社交媒体上脱颖而出&#xff0c;视频素材的选择至关重要。以下是一些顶级的视频素材网站推荐&#xff0c;不仅可以提升视频质量&#xff0c;还能帮助你吸引更多粉丝。 蛙学网&#xff1a;创意的源泉 作为创意和独特性的…

使用 Ubuntu x86_64 平台交叉编译适用于 Linux aarch64(arm64) 平台的 QT5(包含OpenGL/WebEngine支持) 库

使用 Ubuntu AMD64 平台交叉编译适用于 Linux ARM64 平台的 QT5(包含 OpenGL/WebEngine 支持) 库 目录 使用 Ubuntu AMD64 平台交叉编译适用于 Linux ARM64 平台的 QT5(包含 OpenGL/WebEngine 支持) 库写在前面前期准备编译全流程1. 环境搭建2. 复制源码包并解压&#xff0c;创…

信息就像糖,让人上瘾

今天阅读阮一峰的科技爱好者周刊&#xff0c;其中提到一个观点「信息就像糖&#xff0c;让人上瘾」&#xff0c;让人印象深&#xff0c;糖之所以上瘾&#xff0c;是因为会让人增加多巴胺的分泌&#xff0c;让人成瘾。而研究表明&#xff0c;信息上瘾跟糖上瘾一样&#xff0c;信…

Golang | Leetcode Golang题解之第198题打家劫舍

题目&#xff1a; 题解&#xff1a; func rob(nums []int) int {if len(nums) 0 {return 0}if len(nums) 1 {return nums[0]}first : nums[0]second : max(nums[0], nums[1])for i : 2; i < len(nums); i {first, second second, max(first nums[i], second)}return se…

保姆教程教你如何使用数据集运行ORB-SLAM3

链接: 自学SLAM&#xff08;2&#xff09;—保姆教程教你如何使用自己的视频运行ORB-SLAM2 这篇文章是详细教怎么运行ORB-SLAM2的&#xff0c;那么下来我们就看看怎么运行ORB-SLAM3 理论上ORB-SLAM2的环境也是可以跑ORB-SLAM3的&#xff0c;因为我之前试过&#xff0c;编译成功…

力扣300. 最长递增子序列(动态规划)

Problem: 300. 最长递增子序列 文章目录 题目描述思路及解法复杂度Code 题目描述 思路及解法 明确题目涉及到求取最值问题因此我们可以考虑使用动态规划来解决问题 1.定义状态&#xff1a;定义int类型的dp数组表示以nums[i]结尾的序列的最长长度&#xff0c;初始化均为1即表示…

spring mvc实现自定义验证器Validator

使用场景 在接口开发的日常实践中&#xff0c;确保数据准确性是保障业务稳定性的关键一环。面对诸如登录时验证用户名密码非空、创建用户时检查邮箱和手机号格式的正确性等需求&#xff0c;手动编写校验逻辑不仅耗时费力&#xff0c;还会显著降低代码的可读性和维护性。鉴于网…

[OtterCTF 2018]Graphic‘s For The Weak

恶意软件的图形中有些可疑之处。 软件图形 &#xff1f;&#xff1f;&#xff1f;这里的恶意文件都是 vmware-tray.ex使用procdump转存进程的可执行文件 &#xff08;可执行的&#xff09;导出了 &#xff0c;看文件里面是否存在 图片 volatility.exe -f .\OtterCTF.vmem --pro…

springboot+vue+mybatis奶茶管理系统+PPT+论文+讲解+售后

由于科学技术的快速发展&#xff0c;人们的生活也与信息时代的发展相关。同时&#xff0c;随着市场化和经济化的发展&#xff0c;国内很多行业已经意识到了这一点&#xff0c;为了提升行业的竞争力&#xff0c;就应当率先把握机会。于是在互联网的默化潜移影响下&#xff0c;餐…

QT4-QT5(6)-const char* QString 乱码转换

我简单粗暴的给出个结论&#xff1a; QString GBK编码正常&#xff0c;可以转UTF-8编码&#xff0c;但会有少量乱码。 const char* 编码就不要转编码&#xff0c;转哪个都是乱码。 UTF-8.cpp 下 1.QString GBK->UTF-8 2.const char * GBK->UTF-8 const char *…

了解WPF控件:OpenFileDialog常用属性与用法(十六)

掌握WPF控件&#xff1a;熟练OpenFileDialog常用属性&#xff08;十六&#xff09; OpenFileDialog控件在WPF中用于需要用户指定文件路径&#xff0c;为用户提供了一个直观且易用的界面来浏览和选择本地文件系统中的文件。例如&#xff0c;当用户需要打开一个已存在的文本文件…

【python012】Python根据页码处理PDF文件的内容

在日常工作和学习中&#xff0c;需要从PDF文件中提取特定页面的内容&#xff0c;以便进行知识、材料压缩等。 2.欢迎点赞、关注、批评、指正&#xff0c;互三走起来&#xff0c;小手动起来&#xff01; 3.欢迎点赞、关注、批评、指正&#xff0c;互三走起来&#xff0c;小手动起…

phpstorm2024代码总是提示“no usages”或者“无用法”解决办法

问题&#xff1a;phpstorm2024使用时&#xff0c;总是会提示无用法&#xff0c;如果没有安装中文语言包的情况下会提示&#xff1a;no usages&#xff0c;如果想关闭怎么办&#xff1f; 编译器右上角点击齿轮进入设置&#xff0c;按照下图的方法点击即可关闭。或者在编译器的“…

GaussDB关键技术原理:高性能(二)

GaussDB关键技术原理&#xff1a;高性能&#xff08;一&#xff09;从数据库性能优化系统概述对GaussDB的高性能技术进行了解读&#xff0c;本篇将从查询处理综述方面继续分享GaussDB的高性能技术的精彩内容。 2 查询处理综述 内容概要&#xff1a;本章节介绍查询端到端处理的…

24/06/24(12.1117)指针进阶 ,冒泡和快排 习题为依托巩固概念(strlen,sizeof,字符串,数组,指针大小的区别)

回调函数 回过头来调用的函数 #include <stdio.h> #include <stdlib.h> int Find_Max(int arr[], int n){ int max_value arr[0]; for (int i 1; i < n; i){ if (max_value < arr[i]) max_value arr[i]; } return…

工业自动化控制中心

目录 一 设计原型 二 后台源码 一 设计原型 二 后台源码 using System; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms;namespace 工业自动化控制中心 {public partial class Form1 : Form{public Form1(){InitializeComponent();}pri…

2SK241 LTSpice模型及仿真

2SK241是东芝生产的一款NMOS&#xff0c;早已停产&#xff0c;但是在收音机圈子里还是有很多死忠粉&#xff0c;所以在淘宝上也是一堆打磨改标的假货。 言归正传&#xff0c;在矿坛上找到了2SK241的模型&#xff1a; .model M2SK241bottom NMOS(Level1 Rd1 Rs10 Rg50 Kp8mV…

Linux源码-进程描述符

Linux操作系统引入了PCB(Process Control Block,进程控制块)结构。PCB是Linux操作系统识别进程的通道。 创建进程时&#xff0c;首先会创建PCB&#xff0c;根据PCB中的信息对进程实施有效管理。当进程终止后&#xff0c;Linux操作系统会释放对应的PCB资源。 PCB的数据结构是s…

IP定位技术中的网络拓扑分析

IP地址物理位置的高精度定位对于众多应用至关重要&#xff0c;从网络安全监控到个性化内容推荐&#xff0c;从地理定位服务、流量优化策略以及广告分布推广等。IP定位技术作为实现这一目标的关键手段&#xff0c;不断演进和创新&#xff0c;今天就IP定位技术中的网络拓扑分析来…