vue3 + antd vue 纯前端 基于xlsx 实现导入excel 转 json,将json数据转换XLSX并下载(下载模版)

一、导入

0、关键代码

// 安装插件
npm i xlsx/yarn add xlsx
// 导入xlsx
import * as XLSX from 'xlsx';

点击提交的时候才整理数据。上传的时候文件保存在  state.form.file[0] 中的

// 定义字段映射关系
const fieldMap = {sheet2json: {技能名称: 'skill_name',技能等级: 'skill_level',技能描述: 'skill_desc',技能类型: 'skill_type',技能效果: 'skill_effect',技能消耗: 'skill_cost',技能持续时间: 'skill_duration',技能范围: 'skill_range',技能范围: 'skill_range',技能目标: 'skill_target'}
};// 提交 --- 点击提交的时候才整理数据。上传的时候文件保存的  state.form.file[0] 中的
const handleSummit = () => {formRef.value.validate().then(async () => {try {const data = await state.form.file[0].arrayBuffer(); // 使用 arrayBuffer 避免中文乱码const workbook = XLSX.read(data, { type: 'buffer' });const outdata = XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]]);// 映射字段名并过滤掉不符合预期的数据const mappedData = outdata.map(row => {return Object.keys(row).reduce((targetMap, key) => {const mappedKey = fieldMap.sheet2json[key];if (mappedKey) {targetMap[mappedKey] = row[key];}return targetMap;}, {});}).filter(item => Object.keys(item).length > 0); // 过滤空对象console.log('------- 导入的数据 -------', mappedData);emits('submit', mappedData);handleClose();} catch (error) {}});
};

1、template

<a-form :model="state.form" name="form" ref="formRef" :label-col="{ style: { width: '120px' } }" autocomplete="off" :rules="rules"><a-form-item label="导入文件上传" name="file" :rules="rules.file"><div class="file-warp" style="position: relative"><a-uploadstyle="margin-left: 20px":file-list="state.form.file"name="file":customRequest="upload":beforeUpload="beforeUpload"@remove="handleRemove"accept=".xlsx, .xls"><a-button type="primary"><upload-outlined></upload-outlined>上传文件</a-button></a-upload><a-button type="primary" ghost style="position: absolute; top: 0; left: 150px" @click="handleDownload"><VerticalAlignBottomOutlined></VerticalAlignBottomOutlined>模版下载</a-button></div></a-form-item>
</a-form>

2、script

import * as XLSX from 'xlsx';
import { reactive, ref } from 'vue';const state = reactive({form: {file: []}
});
const formRef = ref(null);
const open = ref(true);const rules = {file: [{ required: true, message: '请选择文件', trigger: ['blur', 'change'] }]
};// 定义字段映射关系
const fieldMap = {sheet2json: {技能名称: 'skill_name',技能等级: 'skill_level',技能描述: 'skill_desc',技能类型: 'skill_type',技能效果: 'skill_effect',技能消耗: 'skill_cost',技能持续时间: 'skill_duration',技能范围: 'skill_range',技能范围: 'skill_range',技能目标: 'skill_target'},json2sheet: {skill_name: '技能名称',skill_level: '技能等级',skill_desc: '技能描述',skill_type: '技能类型',skill_effect: '技能效果',skill_cost: '技能消耗',skill_duration: '技能持续时间',skill_range: '技能范围',skill_target: '技能目标'}
};// 上传文件之前检测
const beforeUpload = file => {const isXlsxOrXls = file.name.split('.')[1] == 'xlsx' || file.name.split('.')[1] == 'xls';if (!isXlsxOrXls) {message.error('只允许上传xlsx, xls格式的文件!');return false;}const isLt10M = file.size / 1024 / 1024 < 10;if (!isLt10M) {message.error('文件不得大于10MB!');return false;}return isXlsxOrXls && isLt10M;
};// 选择文件
const upload = file => {// 原本调用接口上传的// uplaodFile(file.file).then(res => {//   fileList.value.push({ name: res.data.originalFilename, url: viteConfig.baseUrl + res.data.fileName, fileUrl: res.data.fileName });//   formRef.value.clearValidate();// });state.form.file = [file.file];formRef.value.clearValidate();
};// 移除文件
const handleRemove = file => {state.form.file = [];
};// 提交 转换数据
const handleSummit = () => {formRef.value.validate().then(async () => {try {const data = await state.form.file[0].arrayBuffer(); // 使用 arrayBuffer 避免中文乱码const workbook = XLSX.read(data, { type: 'buffer' });const outdata = XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]]);// 映射字段名并过滤掉不符合预期的数据const mappedData = outdata.map(row => {return Object.keys(row).reduce((targetMap, key) => {const mappedKey = fieldMap.sheet2json[key];if (mappedKey) {targetMap[mappedKey] = row[key];}return targetMap;}, {});}).filter(item => Object.keys(item).length > 0); // 过滤空对象console.log('------- 导入的数据 -------', mappedData);emits('submit', mappedData);handleClose();} catch (error) {}});
};

二、模板下载

1、script

// 定义字段映射关系
const fieldMap = {json2sheet: {skill_name: '技能名称',skill_level: '技能等级',skill_desc: '技能描述',skill_type: '技能类型',skill_effect: '技能效果',skill_cost: '技能消耗',skill_duration: '技能持续时间',skill_range: '技能范围',skill_target: '技能目标'}
};// 模板数据
let templateData = [{skill_name: '大刀斩',skill_level: '5',skill_desc: '技能描述',skill_type: '大招',skill_effect: '亚瑟王那样的大招',skill_cost: '10000',skill_duration: '10',skill_range: '500',skill_target: '目标:亚瑟王'}
];// 模版下载
const handleDownload = () => {// 映射字段名并过滤掉不符合预期的数据const list = templateData.map(row => {return Object.keys(row).reduce((targetMap, key) => {const mappedKey = fieldMap.json2sheet[key];if (mappedKey) {targetMap[mappedKey] = row[key];}return targetMap;}, {});}).filter(item => Object.keys(item).length > 0); // 过滤空对象;const workSheet = XLSX.utils.json_to_sheet(list);const workBook = XLSX.utils.book_new();XLSX.utils.book_append_sheet(workBook, workSheet, '技能表');// 生成Excel文件并下载XLSX.writeFile(workBook, '技能表模板.xlsx');
};

三、完整的文件

<!--* @Description: ------------ fileDescription -----------* @Author: snows_l snows_l@163.com* @Date: 2024-07-18 14:46:47* @LastEditors: snows_l snows_l@163.com* @LastEditTime: 2024-07-19 15:51:19* @FilePath: /digital-qiankun-you/cmdb/src/pages/ipSource/components/uploadFile.vue
-->
<template><div class="upeate-field-warp"><a-modal width="800px" v-model:open="open" :z-index="10004" centered :title="'规划导入'"><template #footer><a-button type="primary" @click="handleSummit">确认</a-button></template><div class="update-field-content-warp"><a-form :model="state.form" name="form" ref="formRef" :label-col="{ style: { width: '120px' } }" autocomplete="off" :rules="rules"><a-form-item label="导入文件上传" name="file" :rules="rules.file"><div class="file-warp" style="position: relative"><a-uploadstyle="margin-left: 20px":file-list="state.form.file"name="file":customRequest="upload":beforeUpload="beforeUpload"@remove="handleRemove"accept=".xlsx, .xls"><a-button type="primary"><upload-outlined></upload-outlined>上传文件</a-button></a-upload><a-button type="primary" ghost style="position: absolute; top: 0; left: 150px" @click="handleDownload"><VerticalAlignBottomOutlined></VerticalAlignBottomOutlined>模版下载</a-button></div></a-form-item></a-form></div></a-modal></div>
</template><script setup>
import { UploadOutlined, VerticalAlignBottomOutlined } from '@ant-design/icons-vue';
import { reactive, ref } from 'vue';
import * as XLSX from 'xlsx';const emits = defineEmits(['submit']);const state = reactive({form: {file: []}
});
const formRef = ref(null);
const open = ref(true);const rules = {file: [{ required: true, message: '请选择文件', trigger: ['blur', 'change'] }]
};// 上传文件之前检测
const beforeUpload = file => {const isXlsxOrXls = file.name.split('.')[1] == 'xlsx' || file.name.split('.')[1] == 'xls';if (!isXlsxOrXls) {message.error('只允许上传xlsx, xls格式的文件!');return false;}const isLt10M = file.size / 1024 / 1024 < 10;if (!isLt10M) {message.error('文件不得大于10MB!');return false;}return isXlsxOrXls && isLt10M;
};// 选择文件
const upload = file => {// 原本调用接口上传的// uplaodFile(file.file).then(res => {//   fileList.value.push({ name: res.data.originalFilename, url: viteConfig.baseUrl + res.data.fileName, fileUrl: res.data.fileName });//   formRef.value.clearValidate();// });state.form.file = [file.file];formRef.value.clearValidate();
};// 移除文件
const handleRemove = file => {state.form.file = [];
};// 初始化
const init = () => {open.value = true;
};// 关闭
const handleClose = () => {open.value = false;
};// 定义字段映射关系
const fieldMap = {sheet2json: {技能名称: 'skill_name',技能等级: 'skill_level',技能描述: 'skill_desc',技能类型: 'skill_type',技能效果: 'skill_effect',技能消耗: 'skill_cost',技能持续时间: 'skill_duration',技能范围: 'skill_range',技能范围: 'skill_range',技能目标: 'skill_target'},json2sheet: {skill_name: '技能名称',skill_level: '技能等级',skill_desc: '技能描述',skill_type: '技能类型',skill_effect: '技能效果',skill_cost: '技能消耗',skill_duration: '技能持续时间',skill_range: '技能范围',skill_target: '技能目标'}
};// 模板数据
let templateData = [{skill_name: '大刀斩',skill_level: '5',skill_desc: '技能描述',skill_type: '大招',skill_effect: '亚瑟王那样的大招',skill_cost: '10000',skill_duration: '10',skill_range: '500',skill_target: '目标:亚瑟王'}
];// 提交
const handleSummit = () => {formRef.value.validate().then(async () => {try {const data = await state.form.file[0].arrayBuffer(); // 使用 arrayBuffer 避免中文乱码const workbook = XLSX.read(data, { type: 'buffer' });const outdata = XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]]);// 映射字段名并过滤掉不符合预期的数据const mappedData = outdata.map(row => {return Object.keys(row).reduce((targetMap, key) => {const mappedKey = fieldMap.sheet2json[key];if (mappedKey) {targetMap[mappedKey] = row[key];}return targetMap;}, {});}).filter(item => Object.keys(item).length > 0); // 过滤空对象console.log('------- 导入的数据 -------', mappedData);emits('submit', mappedData);handleClose();} catch (error) {}});
};// 模版下载
const handleDownload = () => {// 映射字段名并过滤掉不符合预期的数据const list = templateData.map(row => {return Object.keys(row).reduce((targetMap, key) => {const mappedKey = fieldMap.json2sheet[key];if (mappedKey) {targetMap[mappedKey] = row[key];}return targetMap;}, {});}).filter(item => Object.keys(item).length > 0); // 过滤空对象;const workSheet = XLSX.utils.json_to_sheet(list);const workBook = XLSX.utils.book_new();XLSX.utils.book_append_sheet(workBook, workSheet, '技能表');// 生成Excel文件并下载XLSX.writeFile(workBook, '技能表模板.xlsx');
};defineExpose({init
});
</script><style lang="less" scoped>
.upeate-field-warp {width: 100%;
}
</style><style lang="less">
.update-field-content-warp {padding: 40px 20px;.field-item {display: flex;align-items: center;label {min-width: 80px;}}
}
</style>

四、效果图:

原数据(图1)

导入组件(图2)

导出整理后的数据(图3)

模板下载(图4)

模板下载之后的文件(图5)

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

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

相关文章

AI 绘画|Midjourney设计Logo提示词

你是否已经看过许多别人分享的 MJ 咒语&#xff0c;却仍无法按照自己的想法画图&#xff1f;通过学习 MJ 的提示词逻辑后&#xff0c;你将能够更好地理解并创作自己的“咒语”。本文将详细拆解使用 MJ 设计 Logo 的逻辑&#xff0c;让你在阅读后即可轻松上手&#xff0c;制作出…

机器学习-18-统计学与机器学习中回归的区别以及统计学基础知识

参考通透!一万字的统计学知识大梳理 参考3万字长文!手把手教你学会用Python实现统计学 参考统计学的回归和机器学习中的回归有什么差别? 1 研究对象 一维:就是当前摆在我们面前的“一组”,“一批数据。这里我们会用到统计学的知识去研究这类对象。 二维:就是研究某个“事…

【性能优化】在大批量数据下使用 HTML+CSS实现走马灯,防止页面卡顿

切换效果 页面结构变化 1.需求背景 项目首页存有一个小的轮播模块,保密原因大概只能这么展示,左侧图片右侧文字,后端一次性返回几百条数据(开发环境下,生产环境只会更多).无法使用分页解决,前端需要懒加载防止页面卡顿 写个小demo演示,如下 2.解决思路 获取到数据后,取第一…

【electron6】浏览器实时播放PCM数据

pcm介绍&#xff1a;PCM&#xff08;Puls Code Modulation&#xff09;全称脉码调制录音&#xff0c;PCM录音就是将声音的模拟信号表示成0,1标识的数字信号&#xff0c;未经任何编码和压缩处理&#xff0c;所以可以认为PCM是未经压缩的音频原始格式。PCM格式文件中不包含头部信…

【Langchain大语言模型开发教程】模型、提示和解析

&#x1f517; LangChain for LLM Application Development - DeepLearning.AI 学习目标 1、使用Langchain实例化一个LLM的接口 2、 使用Langchain的模板功能&#xff0c;将需要改动的部分抽象成变量&#xff0c;在具体的情况下替换成需要的内容&#xff0c;来达到模板复用效…

AIoTedge 智能边缘物联网平台

AIoTedge智能边缘物联网平台是一个创新的边云协同架构&#xff0c;它为智能设备和系统提供了强大的数据处理和智能决策能力。这个平台的核心优势在于其边云协同架构设计&#xff0c;它优化了数据处理速度&#xff0c;提高了系统的可靠性和灵活性&#xff0c;适用于多种场景&…

NVIDIA 完全过渡到开源 GPU 内核模块

目录 支持的 GPU安装程序更改将包管理器与 CUDA 元包配合使用使用 runfile使用安装帮助程序脚本包管理器详细信息apt&#xff1a;基于 Ubuntu 和 Debian 的发行版dnf&#xff1a;Red Hat Enterprise Linux、Fedora、Kylin、Amazon Linux 或 Rocky Linuxzypper&#xff1a;SUSE …

项目实战--C#实现图书馆信息管理系统

本项目是要开发一个图书馆管理系统&#xff0c;通过这个系统处理常见的图书馆业务。这个系统主要功能是&#xff1a;&#xff08;1&#xff09;有客户端&#xff08;借阅者使用&#xff09;和管理端&#xff08;图书馆管理员和系统管理员使用&#xff09;。&#xff08;2&#…

pdf太大了怎么变小 pdf太大了如何变小一点

在数字化时代&#xff0c;pdf文件已成为工作与学习的重要工具。然而&#xff0c;有时我们可能会遇到pdf文件过大的问题&#xff0c;这会导致传输困难或者存储不便。别担心&#xff0c;下面我将为你介绍一些实用的技巧和工具&#xff0c;帮助你轻松减小pdf文件的大小。 方法一、…

通过libx246 libfaac转换推送RTMP音视频直播流

一、RTMP简介及rtmplib库&#xff1a; RTMP协议是Real Time Message Protocol(实时信息传输协议)的缩写&#xff0c;它是由Adobe公司提出的一种应用层的协议&#xff0c;用来解决多媒体数据传输流的多路复用&#xff08;Multiplexing&#xff09;和分包&#xff08;packetizing…

Mysql----内置函数

前言 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、日期函数 日期&#xff1a;年月日 时间&#xff1a;时分秒 查询&#xff1a;当前时间&#xff0c;只显示当前日期 注意&#xff1a;如果类型为date或者datetime。表中数据类型为date,你插入时…

昇思MindSpore 应用学习-FCN图像语义分割-CSDN

日期 心得 昇思MindSpore 应用学习-FCN图像语义分割 (AI 代码解析) 全卷积网络&#xff08;Fully Convolutional Networks&#xff0c;FCN&#xff09;是UC Berkeley的Jonathan Long等人于2015年在Fully Convolutional Networks for Semantic Segmentation[1]一文中提出的用…

MATLAB R2023b下载安装教程汉化中文版设置

MATLAB R2023b下载安装教程汉化中文版设置 Matlab 是一款功能强大的商业数学软件 Matlab&#xff08;Matrix Labortory&#xff09;即矩阵实验室&#xff0c;它在数值计算、数据分析、算法开发、建模与仿真等众多领域都发挥着重要作用。 Matlab 具有以下显著特点和优势&…

移动端如何离线使用GPT

在移动端离线使用GPT&#xff0c;只需要一个app&#xff1a;H2O AI Personal GPT 是H2OAI上架的一款app&#xff0c;可离线使用&#xff0c;注重数据隐私&#xff0c;所有数据都只存储在本地。对H2OAI感兴趣的伙伴&#xff0c;可移步&#xff1a;https://h2o.ai 该app支持的模…

大语言模型-文本向量模型评估基准 MTEB

MTEB&#xff08;Massive Text Embedding Benchmark&#xff09; 涵盖112种语言的58个数据集&#xff0c;包含如下8种任务。 1、双语文本挖掘&#xff08;Bitext Mining&#xff09; 任务目标&#xff1a; 在双语语料库中识别语义等价的句子对。 任务描述&#xff1a; 输入…

服务器借助笔记本热点WIFI上网

一、同一局域网环境 1、当前环境&#xff0c;已有交换机组网环境&#xff0c;服务器已配置IP信息。 设备ip服务器125.10.100.12交换机125.10.100.0/24笔记本125.10.100.39 2、拓扑图 #mermaid-svg-D4moqMym9i0eeRBm {font-family:"trebuchet ms",verdana,arial,sa…

价格战再起:OpenAI 发布更便宜、更智能的 GPT-4o Mini 模型|TodayAI

OpenAI 今日推出了一款名为 GPT-4o Mini 的新模型&#xff0c;这款模型较轻便且成本更低&#xff0c;旨在为开发者提供一个经济实惠的选择。与完整版模型相比&#xff0c;GPT-4o mini 在成本效益方面表现卓越&#xff0c;价格仅为每百万输入 tokens 15 美分和每百万输出 tokens…

【接口自动化_12课_基于Flask搭建MockServer】

DAY12_基于Flask搭建MockServer 目标&#xff1a;通过本节课主要核心内容要理解什么是MockServer&#xff0c;并且结合Flask进行实战。 章节大纲 1. 什么是Mock及应用场景理解 2. 框架对比及Flask基本应用理解 3. Mock Server接口设计实战重要 4. Mock Server如何运行理解…

守护动物乐园:视频AI智能监管方案助力动物园安全与秩序管理

一、背景分析 近日&#xff0c;某大熊猫参观基地通报了4位游客在参观时&#xff0c;向大熊猫室外活动场内吐口水的不文明行为。这几位游客的行为违反了入园参观规定并可能对大熊猫造成严重危害&#xff0c;已经被该熊猫基地终身禁止再次进入参观。而在此前&#xff0c;另一熊猫…

IMU提升相机清晰度

近期&#xff0c;一项来自北京理工大学和北京师范大学的团队公布了一项创新性的研究成果&#xff0c;他们将惯性测量单元&#xff08;IMU&#xff09;和图像处理算法相结合&#xff0c;显著提升了非均匀相机抖动下图像去模糊的准确性。 研究团队利用IMU捕捉相机的运动数据&…