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

需求背景:
产品创建流程比较复杂,有时候需要一次性创建多至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.mzph.cn/news/863249.shtml

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

相关文章

【华为OD机试】天然蓄水库(C++/Java/Python)

题目 题目描述 公元2919年,人类终于发现了一颗宜居星球——X星。 现想在X星一片连绵起伏的山脉间建一个天热蓄水库,如何选取水库边界,使蓄水量最大? 要求: 山脉用正整数数组s表示,每个元素代表山脉的高度。选取山脉上两个点作为蓄水库的边界,则边界内的区域可以蓄水,蓄…

ComfyUI汉化插件安装

步骤一&#xff1a;点击Manager 步骤二&#xff1a;选择安装插件 步骤三&#xff1a;搜索Translation&#xff0c;选择第一个点击右边得安装 步骤四&#xff1a;点击下放得RESTART进行重启 步骤五&#xff1a;等待重启完成后&#xff0c;点击设置 步骤六&#xff1a;选择中文语…

【Nginx】源码安装

1.安装地址 Nginx官网&#xff1a;nginx: download 2.下载依赖 //一键安装上面四个依赖 yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel 3.上传解压编译安装 //解压压缩包tar -xvf nginx-1.26.1.tar.gz //进入nginx cd nginx-1.26.1/ //安装到指定位…

llm学习-1(包含如何使用github的codespace):

本文学习参考&#xff1a;datawhalechina/llm-universe: 本项目是一个面向小白开发者的大模型应用开发教程&#xff0c;在线阅读地址&#xff1a;https://datawhalechina.github.io/llm-universe/ 一些可使用的大模型地址&#xff1a; Claude 使用地址 PaLM 官方地址 Gemini…

力扣第一道困难题《3. 无重复字符的最长子串》,c++

目录 方法一&#xff1a; 方法二&#xff1a; 方法三&#xff1a; 方法四&#xff1a; 没有讲解&#xff0c;但给出了优秀题解 本题链接&#xff1a;4. 寻找两个正序数组的中位数 - 力扣&#xff08;LeetCode&#xff09; 话不多说&#xff0c;我们直接开始进行本题的思路解…

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…

金榜题名升学宴,怀庄之醉鸿运添彩

十年寒窗苦读&#xff0c;终于迎来金榜题名的辉煌时刻。这是对知识的向往与追求&#xff0c;也是对未来的期许与梦想。在这样一个值得纪念的时刻&#xff0c;举办一场升学宴&#xff0c;无疑是对过去努力的最好告别&#xff0c;也是对未来人生新旅程的美好祝愿。在选择升学宴用…

大数据面试题之HBase(3)

HBase的预分区 HBase的热点问题 HBase的memstore冲刷条件 HBase的MVCC HBase的大合并与小合并&#xff0c;大合并是如何做的?为什么要大合并 既然HBase底层数据是存储在HDFS上&#xff0c;为什么不直接使用HDFS&#xff0c;而还要用HBase HBase和Phoenix的区别 HBase支…

Java怎么对线程池做监控

对Java线程池进行监控是确保系统性能和稳定性的重要部分。监控线程池可以帮助我们了解线程池的状态&#xff0c;如当前活跃线程数、任务队列长度、已完成任务数等。以下是一个详细的介绍和代码示例&#xff0c;说明如何对Java线程池进行监控。 1. 监控内容 &#xff08;1&…

Spring MVC数据绑定和响应——页面跳转(一)返回值为void类型的页面跳转

一、返回值为void类型的页面跳转到默认页面 当Spring MVC方法的返回值为void类型&#xff0c;方法执行后会跳转到默认的页面。默认页面的路径由方法映射路径和视图解析器中的前缀、后缀拼接成&#xff0c;拼接格式为“前缀方法映射路径后缀”。如果Spring MVC的配置文件中没有配…

1,Windows-本地Linux 系统(WSL)

目录 第一步电脑设置 第二步安装Ubuntu 第三文件传递 开发人员可以在 Windows 计算机上同时访问 Windows 和 Linux 的强大功能。 通过适用于 Linux 的 Windows 子系统 (WSL)&#xff0c;开发人员可以安装 Linux 发行版&#xff08;例如 Ubuntu、OpenSUSE、Kali、Debian、Arc…

【子串】3. 无重复的最长子串

3. 无重复的最长子串 难度&#xff1a;中等难度 力扣地址&#xff1a;https://leetcode.cn/problems/longest-substring-without-repeating-characters/description/ 题目看起来简单&#xff0c;刷起来有好几个坑&#xff0c;特此记录一下&#xff0c;解法比官网的更加简单&…

51单片机第10步_数组

本章重点介绍如何访问数组。 #include <REG51.h> //包含头文件REG51.h,使能51内部寄存器; #include <string.h> //使能strcpy(); #include <stdio.h> //包含头文件stdio.h //_getkey();从串口读入一个字符; //putchar();向串口发送一个字节; //printf()…

[OtterCTF 2018]Play Time

还是这个程序 。。要找到游戏名字查看 进程 psscan pstree pslist 0x000000007d686b30 Rick And Morty 3820 2728 0x000000000b59a000 2018-08-04 19:32:55 UTC0000 0x000000007d7cb740 LunarMS.exe 708 2728 0x00000000731cb000 2018-08-04 19:27:39 UTC0000…

《昇思25天学习打卡营第12天 | 昇思MindSpore基于MindSpore的GPT2文本摘要》

12天 本节学习了基于MindSpore的GPT2文本摘要。 1.数据集加载与处理 1.1.数据集加载 1.2.数据预处理 2.模型构建 2.1构建GPT2ForSummarization模型 2.2动态学习率 3.模型训练 4.模型推理

支持纳管达梦数据库,命令存储支持对接Elasticsearch 8,JumpServer堡垒机v3.10.11 LTS版本发布

2024年6月24日&#xff0c;JumpServer开源堡垒机正式发布v3.10.11 LTS版本。JumpServer开源项目组将对v3.10 LTS版本提供长期的支持和优化&#xff0c;并定期迭代发布小版本。欢迎广大社区用户升级至v3.10 LTS最新版本&#xff0c;以获得更佳的使用体验。 在JumpServer v3.10.…

Redis主从复制、哨兵模式以及Cluster集群

一.主从复制 1.主从复制的概念 主从复制&#xff0c;是指将一台Redis服务器的数据&#xff0c;复制到其他的Redis服务器。前者称为主节点(Master)&#xff0c;后者称为从节点(Slave)&#xff1b;数据的复制是单向的&#xff0c;只能由主节点到从节点。默认情况下&#xff0c;…

More Effective C++ 35个改善编程与设计的有效方法笔记与心得 1

一. 基础议题 条款1&#xff1a;仔细区别 pointers 和 references ‌‌‌‌  这是一个常见的问题。指针&#xff08;pointers&#xff09;和引用&#xff08;references&#xff09;都是C面向对象编程中常用的概念&#xff0c;虽然他们在某些方面表现得很相似&#xff0c;但…

深入Symfony事件调度器:掌控应用程序的核心动力

&#x1f39a;️ 深入Symfony事件调度器&#xff1a;掌控应用程序的核心动力 &#x1f680; Symfony是一个高度灵活的PHP框架&#xff0c;以其组件化和可扩展性而闻名。在Symfony中&#xff0c;事件调度器&#xff08;Event Dispatcher&#xff09;是一个强大的工具&#xff0…

Github Page 使用手册(保姆级教程!)

搭建个人网站&#xff1f;没有服务器&#xff1f;那不如尝试一下 Github Page &#xff01; 最近我正好在搭建个人网站&#xff0c;于是就写一篇博客来详细介绍 Github Page 的使用、部署方式吧&#xff01; 一、进入 Github 访问&#xff1a;github.com 如果你没有 github…