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

devtools/2024/9/22 15:32:32/

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

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

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

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

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

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

javascript"><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脚本增加代码:

javascript"><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层增加代码:

java">@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类增加代码:

java">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获取就会异常。
解决方案:
//单元格值获取

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

http://www.ppmy.cn/devtools/57185.html

相关文章

详解 HTTP 中间人攻击

什么是中间人攻击&#xff1f; 攻击者将自己插入通信过程中&#xff0c;以窃取&#xff0c;篡改数据。通信的两端不知道中间人的存在&#xff0c;他们以为在与对方直接通信&#xff0c;实际上他们的通信已经被监听或干扰。WIFI 路由器被破解之后就能进行中间人攻击。 中间人攻…

基于Java的微信记账小程序【附源码】

摘 要 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;记账微信小程序被用户普遍使用&#xff0c;为方便用户能够…

介绍几种 MySQL 官方高可用方案

前言&#xff1a; MySQL 官方提供了多种高可用部署方案&#xff0c;从最基础的主从复制到组复制再到 InnoDB Cluster 等等。本篇文章以 MySQL 8.0 版本为准&#xff0c;介绍下不同高可用方案架构原理及使用场景。 1.MySQL Replication MySQL Replication 是官方提供的主从同…

【力扣】有效的字母异位词

&#x1f525;博客主页&#xff1a; 我要成为C领域大神&#x1f3a5;系列专栏&#xff1a;【C核心编程】 【计算机网络】 【Linux编程】 【操作系统】 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 给定两个字符串 s …

高性价比模块:LSYT201B语音模块学习使用

最近打算做个语音的项目&#xff0c;找到了深圳雷龙发展的LSY201B这款语音模块&#xff0c;写出来安利一下 程序源码&#xff1a;SuiXinSc/Speech-Module (github.com) 或者进入Q群找我获取 目录 一&#xff0c;简要介绍&#xff1a; 硬件参数&#xff1a; 1&#xff0c;处理…

【pearcmd】通过pearcmd.php 进行GetShell

https://cloud.tencent.com/developer/article/2204400 关于PHP 配置 register_argc_argv 小结 的一些研究文章。 应用例题 [NewStarCTF 2023 公开赛道]Include &#x1f350; <?phperror_reporting(0);if(isset($_GET[file])) {$file $_GET[file];if(preg_match(/flag|l…

力扣第218题“天际线问题”

在本篇文章中&#xff0c;我们将详细解读力扣第218题“天际线问题”。通过学习本篇文章&#xff0c;读者将掌握如何使用扫描线算法和堆来解决这一问题&#xff0c;并了解相关的复杂度分析和模拟面试问答。每种方法都将配以详细的解释&#xff0c;以便于理解。 问题描述 力扣第…

Android14之RRO资源文件替换策略(二百二十一)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 优质视频课程:AAOS车载系统+AOSP…