vue3 导出数据为 excel 文件
文章目录
- 安装插件
- 封装组件 -- Export2Excel.js
- 多表封装
- 界面使用 -- 数据处理成二维数组
- 更多
菜鸟最近做了一个需求,就是需要上传表单并识别,然后识别出来的内容要可以修改,然后想的就是识别内容变成 form 表单,所以并没有使用 SpreadJS ,这个 SpreadJS 有很多 excel 的功能,强大是强大,就是我这个需求没有那么复杂!
然后上传识别交给后端处理了,菜鸟做的就是查看详情的是时候可把表单展示的数据导出成 excel 文件就行!
安装插件
npm i xlsx
npm install -S file-saver
封装组件 – Export2Excel.js
import { saveAs } from 'file-saver'
import * as XLSX from 'xlsx'/**** @param {Object} workbook 工作薄* @param {Object} worksheet 工作表* @param {Object} cell 单元格* 标记,引用单元格时所使用的地址格式(如:A1、C7)*/
function datenum (v, date1904) {if (date1904) v += 1462var epoch = Date.parse(v)return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000)
}function sheetFromArrayOfArrays (data, opts) {var ws = {}var range = {s: {c: 10000000,r: 10000000},e: {c: 0,r: 0}}for (var R = 0; R !== data.length; ++R) {for (var C = 0; C !== data[R].length; ++C) {if (range.s.r > R) range.s.r = Rif (range.s.c > C) range.s.c = Cif (range.e.r < R) range.e.r = Rif (range.e.c < C) range.e.c = Cvar cell = {v: data[R][C] // v表示单元格原始值, t表示内容类型,s-string类型,n-number类型,b-boolean类型,d-date类型,等等}if (cell.v == null) continue/*** 通过地址对象 { r: R, c: C } 来获取单元格,R 和 C 分别代表从 0 开始的行和列的索引。* XLSX.utils 中的 encode_cell/decode_cell 方法可以转换单元格地址* XLSX.utils.encode_cell({ r: 7, c: 2 }) ===》 C7*/var cellRef = XLSX.utils.encode_cell({ c: C, r: R })if (typeof cell.v === 'number') cell.t = 'n'else if (typeof cell.v === 'boolean') cell.t = 'b'else if (cell.v instanceof Date) {cell.t = 'n'cell.z = XLSX.SSF._table[14]cell.v = datenum(cell.v)} else cell.t = 's'ws[cellRef] = cell}}// ws['!ref']:表示所有单元格的范围,例如从A1到F8则记录为A1:F8if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range)return ws
}function Workbook () {if (!(this instanceof Workbook)) return new Workbook()this.SheetNames = []this.Sheets = {}
}// 字符串转为ArrayBuffer
function s2ab (s) {var buf = new ArrayBuffer(s.length)var view = new Uint8Array(buf)for (var i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFFreturn buf
}/**** @param {Array} multiHeader 多行表头* @param {Array} header 表头* @param {Array} data 数据* @param {String} filename 文件名* @param {Array} merges 合并单元格* @param {Boolean} autoWidth 是否设置单元格宽度* @param {String} bookType 要生成的文件类型*/
export function exportJsonToExcel ({multiHeader = [],header,data,filename,merges = [],autoWidth = true,bookType = 'xlsx'
} = {}) {filename = filename || 'excel-list'data = [...data]data.unshift(header)for (let i = multiHeader.length - 1; i > -1; i--) {data.unshift(multiHeader[i])}var wsName = 'SheetJS'var wb = new Workbook()var ws = sheetFromArrayOfArrays(data)if (merges.length > 0) {// ws[!merges]:存放一些单元格合并信息,是一个数组,每个数组由包含s和e构成的对象组成,s表示开始,e表示结束,r表示行,c表示列if (!ws['!merges']) ws['!merges'] = []merges.forEach(item => {ws['!merges'].push(XLSX.utils.decode_range(item))})}if (autoWidth) {/* 设置worksheet每列的最大宽度 */const colWidth = data.map(row => row.map(val => {/* 先判断是否为null/undefined */if (val == null) {return { 'wch': 10 }} else if (val.toString().charCodeAt(0) > 255) { /* 再判断是否为中文 */return {'wch': val.toString().length * 2}} else {return {'wch': val.toString().length}}}))/* 以第一行为初始值 */let result = colWidth[0]for (let i = 1; i < colWidth.length; i++) {for (let j = 0; j < colWidth[i].length; j++) {if (result[j] && result[j]['wch'] < colWidth[i][j]['wch']) {result[j]['wch'] = colWidth[i][j]['wch']}}}// ws['!cols']设置单元格宽度, [{'wch': 10},{'wch': 10}] ===> 第一列和第二列设置了宽度ws['!cols'] = result}/* add worksheet to workbook */wb.SheetNames.push(wsName)wb.Sheets[wsName] = wsvar wbout = XLSX.write(wb, {bookType: bookType,bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性type: 'binary'})saveAs(new Blob([s2ab(wbout)], { type: 'application/octet-stream' }),`${filename}.${bookType}`)
}
此处参考:vue3中将数据导出为excel表格
多表封装
但是菜鸟的需求是要一个 excel 包含两个表,所以菜鸟对其进行了优化:
import { saveAs } from "file-saver";
import * as XLSX from "xlsx";/**** @param {Object} workbook 工作薄* @param {Object} worksheet 工作表* @param {Object} cell 单元格* 标记,引用单元格时所使用的地址格式(如:A1、C7)*/
function datenum(v, date1904) {if (date1904) v += 1462;var epoch = Date.parse(v);return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
}// eslint-disable-next-line
function sheetFromArrayOfArrays(data, opts) {var ws = {};var range = {s: {c: 10000000,r: 10000000,},e: {c: 0,r: 0,},};for (var R = 0; R !== data.length; ++R) {for (var C = 0; C !== data[R].length; ++C) {if (range.s.r > R) range.s.r = R;if (range.s.c > C) range.s.c = C;if (range.e.r < R) range.e.r = R;if (range.e.c < C) range.e.c = C;var cell = {v: data[R][C], // v表示单元格原始值, t表示内容类型,s-string类型,n-number类型,b-boolean类型,d-date类型,等等};if (cell.v == null) continue;/*** 通过地址对象 { r: R, c: C } 来获取单元格,R 和 C 分别代表从 0 开始的行和列的索引。* XLSX.utils 中的 encode_cell/decode_cell 方法可以转换单元格地址* XLSX.utils.encode_cell({ r: 7, c: 2 }) ===》 C7*/var cellRef = XLSX.utils.encode_cell({ c: C, r: R });if (typeof cell.v === "number") cell.t = "n";else if (typeof cell.v === "boolean") cell.t = "b";else if (cell.v instanceof Date) {cell.t = "n";cell.z = XLSX.SSF._table[14];cell.v = datenum(cell.v);} else cell.t = "s";ws[cellRef] = cell;}}// ws['!ref']:表示所有单元格的范围,例如从A1到F8则记录为A1:F8if (range.s.c < 10000000) ws["!ref"] = XLSX.utils.encode_range(range);return ws;
}function Workbook() {if (!(this instanceof Workbook)) return new Workbook();this.SheetNames = [];this.Sheets = {};
}// 字符串转为ArrayBuffer
function s2ab(s) {var buf = new ArrayBuffer(s.length);var view = new Uint8Array(buf);for (var i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xff;return buf;
}/**** @param {Array} multiHeader 多行表头* @param {Array} header 表头* @param {Array} data 数据* @param {String} filename 文件名* @param {Array} merges 合并单元格* @param {Boolean} autoWidth 是否设置单元格宽度* @param {String} bookType 要生成的文件类型*/
export function exportJsonToExcel({multiHeader = [],header,data,filename,sheetname,merges = [],autoWidth = true,bookType = "xlsx",
} = {}) {filename = filename || "excel-list";for (let i in header) {data[i] = [...data[i]];data[i].unshift(header[i]);}for (let j in data) {for (let i = multiHeader.length - 1; i > -1; i--) {data[j].unshift(multiHeader[i]);}}let wsName = [];for (let i in sheetname) {wsName.push(sheetname[i]);}var wb = new Workbook();let ws = [];for (let i in data) {ws.push(sheetFromArrayOfArrays(data[i]));}if (merges.length > 0) {// ws[!merges]:存放一些单元格合并信息,是一个数组,每个数组由包含s和e构成的对象组成,s表示开始,e表示结束,r表示行,c表示列for (let i in ws) {if (!ws[i]["!merges"]) ws["!merges"] = [];merges.forEach((item) => {ws[i]["!merges"].push(XLSX.utils.decode_range(item));});}}if (autoWidth) {/* 设置worksheet每列的最大宽度 */const colWidth = data.map((row) =>row.map((val) => {/* 先判断是否为null/undefined */if (val == null) {return { wch: 10 };} else if (val.toString().charCodeAt(0) > 255) {/* 再判断是否为中文 */return {wch: val.toString().length * 2,};} else {return {wch: val.toString().length,};}}));/* 以第一行为初始值 */let result = colWidth[0];for (let i = 1; i < colWidth.length; i++) {for (let j = 0; j < colWidth[i].length; j++) {if (result[j] && result[j]["wch"] < colWidth[i][j]["wch"]) {result[j]["wch"] = colWidth[i][j]["wch"];}}}// ws['!cols']设置单元格宽度, [{'wch': 10},{'wch': 10}] ===> 第一列和第二列设置了宽度for (let i in ws) {ws[i]["!cols"] = result;}}/* add worksheet to workbook */for (let i in wsName) {wb.SheetNames.push(wsName[i]);wb.Sheets[wsName[i]] = ws[i];}var wbout = XLSX.write(wb, {bookType: bookType,bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性type: "binary",});saveAs(new Blob([s2ab(wbout)], { type: "application/octet-stream" }), `${filename}.${bookType}`);
}
界面使用 – 数据处理成二维数组
第一个的使用直接参考别人的,我这里使用的是菜鸟封装的,如果有误,可以留言,菜鸟进行更改,因为菜鸟这里只测试了一个和两个表格的情况
// 数据处理 --》 读者按照自己的逻辑来
for (const key in envFactors.value) {let data1 = []; //设置一个二级列表,导出的表格每一行为一个二级列表for (let i in objkeyArr.value) {let keyname = objkeyArr.value[i];data1.push(envFactors.value[key][keyname]);}data2.value.push(data1); //把二级列表塞入一级列表
}
console.log(data2); // data2 必须是二维数组for (const key in sampleGroups.value) {let data1 = [];data1.push(sampleGroups.value[key].sampleTestName,sampleGroups.value[key].sampleAnalysisName,sampleGroups.value[key].groupFirstWay,sampleGroups.value[key].groupSecWay,sampleGroups.value[key].groupThirdWay,sampleGroups.value[key].groupFourthWay,sampleGroups.value[key].groupFifthWay);data3.value.push(data1);
}
console.log(data3);
// 数据处理结束// 导出成表格
function exportExcel() {exportJsonToExcel({header: [["检测报告样品名称","分析样品名称","分组名称","分组名称","分组名称","分组名称","分组名称",],objkeyArr.value,], // 表名个数可以不等于数据每一行的列数filename: "详请表",data: [data3.value, data2.value],sheetname: ["样品分组表", "环境因子表"],});
}
更多
菜鸟这里只使用了header、data、filename、sheetname 等属性,其他属性可以看该篇文章,挺详细的:纯前端js(或者vue)导出excel实现:合并单元格、设置单元格样式、单元格内换行
相关文章:
vue3 导出数据为 excel 文件
文章目录 安装插件封装组件 -- Export2Excel.js多表封装界面使用 -- 数据处理成二维数组更多 菜鸟最近做了一个需求,就是需要上传表单并识别,然后识别出来的内容要可以修改,然后想的就是识别内容变成 form 表单,所以并没有使用 Sp…...
PyQt6简介
锋哥原创的PyQt6视频教程: 2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~共计12条视频,包括:2024版 PyQt6 Python桌面开发 视频教程(无废话版…...
某60区块链安全之未初始化的存储指针实战二学习记录
系列文章目录 文章目录 系列文章目录未初始化的存储指针实战二实验目的实验环境实验工具实验原理实验内容实验过程EXP利用 未初始化的存储指针实战二 实验目的 学会使用python3的web3模块 学会分析以太坊智能合约未初始化的存储指针漏洞 找到合约漏洞进行分析并形成利用 实验…...
软件工程第十二周
软件作坊、软件危机、软件过程控制、重型控制、敏捷、DevOps 这些术语概括了软件开发历史和实践中的几个重要概念和阶段。让我们逐一解析它们: 软件作坊(Software Craftsmanship):这是软件开发的早期模式,强调个人技能…...
electron 问题记录
23年11月24 electron项目npm install 卡在一个地方不动 原因:主要是 install electron 会卡住 解决方法: # 先解决install electron卡死 npm install -g cnpm --registryhttps://registry.npmmirror.com cnpm install electron# 然后下载其他依赖 np…...
nodejs+vue+python+PHP+微信小程序-留学信息查询系统的设计与实现-安卓-计算机毕业设计
1、用户模块: 1)登录:用户注册登录账号。 2)留学查询模块:查询学校的入学申请条件、申请日期、政策变动等。 3)院校排名:查询国外各院校的实力排名。 4)测试功能:通过入学…...
JWT和Token之间的区别
✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏:每天一个知识点 ✨特色专栏:…...
UserRole
Qt::UserRole 是 Qt::ItemDataRole 枚举中的一个成员,用于表示自定义数据角色(Data Role)的起始值。 在 Qt 中,Qt::ItemDataRole 枚举用于标识项(Item)中不同类型的数据。这些数据角色包括 Qt::DisplayRol…...
java学习part10 this
90-面向对象(进阶)-关键字this调用属性、方法、构造器_哔哩哔哩_bilibili 1.java的this java的this性质类似cpp的this, 但它是一种引用,所以用 this. xxx来调用。 this代表当前的类的实例,所以必须和某个对象结合起来使用,不能…...
Spring Cloud + Nacos 项目启动失败【No spring.config.import property has been defined】
在 Spring Cloud 项目使用 bootstrap.yaml 配置文件,添加 nacos 等相关参数配置,启动服务抛入如下异常: org.springframework.cloud.commons.ConfigDataMissingEnvironmentPostProcessor$ImportException: No spring.config.import set ... …...
CANopen协议【SDO】
SDO: SDO是读写单个寄存器。主要用于配置伺服驱动器参数。 1 收发功能: //public unsafe struct VCI_CAN_OBJ //CAN数据帧 【单帧对象】//{// public uint ID;// 帧ID。 【11bit】数据右对齐。 详情请参照: 《8.附件1࿱…...
9-什么是迭代器,生成器,装饰器、django的信号用过吗?如何用,干过什么、什么是深拷贝,什么是浅拷贝,如何使用、slice操作符和list构造函数
1 什么是迭代器,生成器,装饰器 2 django的信号用过吗?如何用,干过什么 3 什么是深拷贝,什么是浅拷贝,如何使用 3.1 浅拷贝 3.2 深拷贝 3.3 扩展(slice操作符和list构造函数) 1 什么是迭代器,生成…...
RabbitMQ之发送者(生产者)可靠性
文章目录 前言一、生产者重试机制二、生产者确认机制实现生产者确认(1)定义ReturnCallback(2)定义ConfirmCallback 总结 前言 生产者重试机制、生产者确认机制。 一、生产者重试机制 问题:生产者发送消息时࿰…...
乐得瑞LDR6020 VR串流线方案:实现同时充电传输视频信号
VR(Virtual Reality),俗称虚拟现实技术,是一项具有巨大潜力的技术创新,正在以惊人的速度改变我们的生活方式和体验,利用专门设计的设备,如头戴式显示器(VR头盔)、手柄、定…...
【libGDX】Mesh纹理贴图
1 前言 纹理贴图的本质是将图片的纹理坐标与模型的顶点坐标建立一一映射关系。纹理坐标的 x、y 轴正方向分别朝右和朝下,如下。 2 纹理贴图 本节将使用 Mesh、ShaderProgram、Shader 实现纹理贴图,OpenGL ES 的实现见博客 → 纹理贴图。 DesktopLauncher…...
基线扫描tomcat安全加固-检查是否支持HTTPS等加密协议
背景:基线扫描时,docker镜像中的tomcat在检查是否支持HTTPS等加密协议这一项上未通过。 思路:先通过JDK自带的keytool工具生成证书,再从tomcat的server.xml配置文件中增加配置。 我不确定不同版本的JDK生成的证书是否可以通用&a…...
基于 STM32F7 和神经网络的实时人脸特征提取与匹配算法实现
本文讨论了如何使用 STM32F7 和神经网络模型来实现实时人脸特征提取与匹配算法。首先介绍了 STM32F7 的硬件和软件特点,然后讨论了人脸特征提取和匹配算法的基本原理。接下来,我们将重点讨论如何在 STM32F7 上实现基于神经网络的人脸特征提取与匹配算法&…...
Android笔记(十四):JetPack Compose中附带效应(一)
在Android应用中可以通过定义可组合函数来搭建应用界面。应用界面的更新往往是与可组合函数内部定义的状态值相关联的。当界面的状态值发生变更,会导致应用界面进行更新。在Android笔记(九):Compose组件的状态,对Compo…...
【web】Fastapi自动生成接口文档(Swagger、ReDoc )
简介 FastAPI是流行的Python web框架,适用于开发高吞吐量API和微服务(直接支持异步编程) FastAPI的优势之一:通过提供高级抽象和自动数据模型转换,简化请求数据的处理(用户不需要手动处理原始请求数据&am…...
竞赛选题 题目:基于FP-Growth的新闻挖掘算法系统的设计与实现
文章目录 0 前言1 项目背景2 算法架构3 FP-Growth算法原理3.1 FP树3.2 算法过程3.3 算法实现3.3.1 构建FP树 3.4 从FP树中挖掘频繁项集 4 系统设计展示5 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 基于FP-Growth的新闻挖掘算法系统的设计与实现…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...
排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...
多模态图像修复系统:基于深度学习的图片修复实现
多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
