【vue3+xlxs+xlsx-style-vite】vue3项目中使用xlsx插件实现Excel表格的导出和解析,已实现
在vue3项目中使用xlsx插件实现Excel表格的导出和解析
1、xlsx插件包官方 xlsx插件包官方
2、FileReader官方文档:FileReader官方文档
安装xlsx和xlsx-style-vite、file-saver
npm install xlsx
npm install xlsx-style-vite
npm install file-saver
package.json中查看安装版本
在utils文件夹下新建excel.js
import { saveAs } from "file-saver";export function exportExcel(ids,filename,excelProps,excelList,dictOptions = {}
) {const newExcelProps = JSON.parse(JSON.stringify(excelProps));import("@/utils/export2Excel").then((excel) => {// 顺序表按值删除for (var i = newExcelProps.length - 1; i >= 0; i--) {if (newExcelProps[i].visible === false ||newExcelProps[i].field === "operation") {newExcelProps.splice(i, 1);}}const propLength = newExcelProps.length;const title = [filename];const tHeader = newExcelProps.map((item) => item[name]); // 表头// 需要过滤的导出表头const toRemove = ["操作"];const filterHeader = tHeader.filter((item) => !toRemove.includes(item));tHeader.length = 0;tHeader.push(...filterHeader);// 如果ids为空或者undefined导出默认的数据,否则筛选数据let fileData;if (ids === undefined || ids.length === 0) {fileData = excelList;} else if (ids && ids.length >= 0) {let arr = JSON.parse(JSON.stringify(excelList));let arrMap = new Map(arr.map((obj) => [obj.id, obj]));let resultArr = ids.map((id) => arrMap.get(id));fileData = resultArr;}fileData.forEach((item) => {newExcelProps.forEach((v) => {// 如果props 中type为dict 且 scopedSlots存在content 则会对每行导出数据进行下拉筛选if (v.type === "dict" && v.scopedSlots.content) {let dictField = v.dictField || ["dictValue", "dictLabel"];const filterData = dictOptions[v.field].filter((f) => item[v.field] == f[dictField[0]]);item[v.field] = !filterData.length ? "" : filterData[0][dictField[1]];}});});const data = Array.from(fileData, (v) =>newExcelProps.map(({ field }) => v[field]));//单元格值判空操作for (let i = 0; i < data.length; i++) {const item = data[i];for (let index = 0; index < item.length; index++) {item[index] =item[index] === "" ||item[index] === null ||item[index] === undefined? "": item[index];}}const merges = [`A1:${numToEng(propLength)}1`];excel.export_json_to_excel({title,header: tHeader,data,merges,filename,autoWidth: true,bookType: "xlsx",});});
}
// 转换英文字符
export function numToEng(num) {const A_Z = []for (let i = 65; i < 91; i++) {A_Z.push(String.fromCharCode(i))}return A_Z[num - 1]
}
在utils文件夹下新建export2Excel.js
/* eslint-disable */
// require("script-loader!file-saver");
import * as XLSX from "xlsx";
import * as XLSX_STYLE from "xlsx-style-vite"; // Vue3 + Vitefunction generateArray(table) {var out = [];var rows = table.querySelectorAll("tr");var ranges = [];for (var R = 0; R < rows.length; ++R) {var outRow = [];var row = rows[R];var columns = row.querySelectorAll("td");for (var C = 0; C < columns.length; ++C) {var cell = columns[C];var colspan = cell.getAttribute("colspan");var rowspan = cell.getAttribute("rowspan");var cellValue = cell.innerText;if (cellValue !== "" && cellValue == +cellValue) cellValue = +cellValue;//Skip rangesranges.forEach(function (range) {if (R >= range.s.r &&R <= range.e.r &&outRow.length >= range.s.c &&outRow.length <= range.e.c) {for (var i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null);}});//Handle Row Spanif (rowspan || colspan) {rowspan = rowspan || 1;colspan = colspan || 1;ranges.push({s: {r: R,c: outRow.length,},e: {r: R + rowspan - 1,c: outRow.length + colspan - 1,},});}//Handle ValueoutRow.push(cellValue !== "" ? cellValue : null);//Handle Colspanif (colspan) for (var k = 0; k < colspan - 1; ++k) outRow.push(null);}out.push(outRow);}return [out, ranges];
}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);
}function sheet_from_array_of_arrays(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],};if (cell.v == null) continue;var cell_ref = XLSX_STYLE.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_STYLE.SSF._table[14];cell.v = datenum(cell.v);} else cell.t = "s";ws[cell_ref] = cell;}}if (range.s.c < 10000000) ws["!ref"] = XLSX_STYLE.utils.encode_range(range);return ws;
}function Workbook() {if (!(this instanceof Workbook)) return new Workbook();this.SheetNames = [];this.Sheets = {};
}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;
}export function export_table_to_excel(id) {var theTable = document.getElementById(id);var oo = generateArray(theTable);var ranges = oo[1];/* original data */var data = oo[0];var ws_name = "SheetJS";var wb = new Workbook(),ws = sheet_from_array_of_arrays(data);/* add ranges to worksheet */ws["!merges"] = ranges;/* add worksheet to workbook */wb.SheetNames.push(ws_name);wb.Sheets[ws_name] = ws;var wbout = XLSX_STYLE.write(wb, {bookType: "xlsx",bookSST: false,type: "binary",});saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream",}),"test.xlsx");
}// 生成器
function* generateHeaderString() {let index = 0;const letterString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";while (true) {let str = "";let n = index;while (n >= 0) {str = letterString[n % 26] + str;n = Math.floor(n / 26) - 1;}yield str;index++;}
}// 迭代生成单元格表头数组
function generateHeaderArr(length) {const result = [];const generator = generateHeaderString();for (let i = 0; i < length; i++) {const nextString = generator.next().value;result.push(nextString);}return result;
}export function export_json_to_excel({title,multiHeader = [],header,data,filename,merges = [],autoWidth = true,bookType = "xlsx",
} = {}) {/* original data */filename = filename || "excel-list";data = [...data];// data.unshift(header);data.unshift(title);for (let i = multiHeader.length - 1; i > -1; i--) {data.unshift(multiHeader[i]);}var ws_name = filename || "SheetJS";var wb = new Workbook(),ws = sheet_from_array_of_arrays(data);if (merges.length > 0) {if (!ws["!merges"]) ws["!merges"] = [];merges.forEach((item) => {ws["!merges"].push(XLSX_STYLE.utils.decode_range(item));});}if (autoWidth) {/*设置worksheet每列的最大宽度*/const colWidth = data.map((row) =>row.map((val) => {/*先判断是否为null/undefined*/if (val == null || val == "") {return {wch: 20,};} else if (val.toString().charCodeAt(0) > 255) {/*再判断是否为中文*/return {wch: val.toString().length * 10,};} 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[0]["wch"] < colWidth[i][j]["wch"]) {result[0]["wch"] = colWidth[i][j]["wch"] + 5;} else {}}}result.push({ wch: 55 });ws["!cols"] = result;}/* add worksheet to workbook */wb.SheetNames.push(ws_name);wb.Sheets[ws_name] = ws;var dataInfo = wb.Sheets[wb.SheetNames[0]];//单元格外侧框线const borderAll = {top: {style: "thin",},bottom: {style: "thin",},left: {style: "thin",},right: {style: "thin",},};//给单元格加上边框let row = ["!ref", "!merges", "!cols"];for (var i in dataInfo) {if (row.indexOf(i) === -1) {dataInfo[i + ""].s = {border: borderAll,alignment: {horizontal: "center",vertical: "center",},};}}// 根据表头长度生成单元格列数组const arr = generateHeaderArr(header.length);// 表头加上样式arr.forEach((v) => {let v2 = v + "3";if (dataInfo.hasOwnProperty(v2)) {dataInfo[v2].s = {border: borderAll,font: {color: { rgb: "FFFFFF" },bold: false,italic: false,underline: false,},alignment: {horizontal: "center",vertical: "center",},fill: {fgColor: { rgb: "808080" },},};}});//设置主标题样式dataInfo["A1"].s = {font: {name: "微软雅黑",sz: 16,color: { rgb: "000000" },bold: false,italic: false,underline: false,},alignment: {horizontal: "center",vertical: "center",},};var wbout = XLSX_STYLE.write(wb, {bookType: bookType,bookSST: false,type: "binary",});saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream",}),`${filename}.${bookType}`);
}
在页面上使用
<script setup>
import Edit from "./components/Edit.vue";
import { onMounted, ref } from "vue";
import axios from "axios";
import { exportExcel } from "./utils/excel.js";
// TODO: 列表渲染
const list = ref([]);
const ids = ref([]);
const title = ref("测试导出");
const column = ref([{ field: "name" }, { field: "place" }]);
const getList = async () => {const res = await axios.get("/list");list.value = res.data;
};
const onDelete = async (id) => {await axios.delete("/del/&{id}");getList();
};
onMounted(() => getList());
// TODO: 删除功能const editRef = ref(null);
// TODO: 编辑功能
const onEdit = (row) => {editRef.value.open(row);
};
// 导出
const handleExport = () => {exportExcel(ids.value, title.value, column.value, list.value);
};
</script><template><div class="app"><el-button type="primary" @click="handleExport">导出</el-button><el-table :data="list"><el-table-column label="ID" prop="id"></el-table-column><el-table-column label="姓名" prop="name" width="150"></el-table-column><el-table-column label="籍贯" prop="place"></el-table-column><el-table-column label="操作" width="150"><template #default="{ row }"><el-button type="primary" link @click="onEdit(row)">编辑</el-button><el-button type="danger" link @click="onDelete(row.id)">删除</el-button></template></el-table-column></el-table></div><Edit ref="editRef" @onUpdate="getList" />
</template><style scoped>
.app {width: 980px;margin: 100px auto 0;
}
</style>
实现效果:
相关文章:

【vue3+xlxs+xlsx-style-vite】vue3项目中使用xlsx插件实现Excel表格的导出和解析,已实现
在vue3项目中使用xlsx插件实现Excel表格的导出和解析 1、xlsx插件包官方 xlsx插件包官方 2、FileReader官方文档:FileReader官方文档 安装xlsx和xlsx-style-vite、file-saver npm install xlsx npm install xlsx-style-vite npm install file-saverpackage.json中查…...

Doris2.0时代的一些机遇和挑战!
300万字!全网最全大数据学习面试社区等你来! 上个周五的时候,Doris官宣了2.0版本,除了在性能上的大幅提升,还有一些特性需要大家特别关注。 根据官网的描述,Doris在下面领域都有了长足进步: 日志…...

Leetcode-每日一题【剑指 Offer 32 - I. 从上到下打印二叉树】
题目 从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。 例如: 给定二叉树: [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7 返回: [3,9,20,15,7] 提示: 节点总数 < 1000 解题思路 1.题目要求我们从…...

网神 SecGate 3600 防火墙任意文件上传漏洞复现
0x01 产品简介 网神SecGate3600下一代极速防火墙(NSG系列)是基于完全自主研发、经受市场检验的成熟稳定网神第三代SecOS操作系统 并且在专业防火墙、VPN、IPS的多年产品经验积累基础上精心研发的高性能下一代防火墙 专门为运营商、政府、军队、教育、大型…...

把独显塞回CPU,新核显能够媲美RTX 30、40系显卡了
上个月,AMD 发布了 Zen4 架构 R5 7600X 的无核显版 - 7500F 。 各种数据评测和玩家实际体验大家也已经看过了,说是变相降价一点不错。 原因也很简单,感谢 Intel 。 Jon Peddie Research 刚出炉报告显示,2023 第二季度 AMD 客户端…...

Python爬虫——scrapy_工作原理
引擎向spiders要url引擎把将要爬取的url给调度器调度器会将url生成的请求对象放入到指定的队列中从队列中出队一个请求引擎将请求交给下载器进行处理下载器发送请求获取互联网数据下载器将数据返回给引擎引擎将数据再次给到spidersspiders通过xpath解析该数据,得到数…...

gRPC vs REST:创建API的方法比较
本文对gRPC和REST的特征和区别进行了介绍,这可能是当今创建API最常用的两种方法。 文章目录 一、gRPC的介绍 二、什么是REST? 三、什么是gRPC? 四、gRPC和REST的比较 (1)底层HTTP协议 (2)支持的数据…...

缓存平均的两种算法
引言 线边库存物料的合理性问题是物流仿真中研究的重要问题之一,如果线边库存量过多,则会对生产现场的布局产生负面影响,增加成本,降低效益。 写在前面 仿真分析后对线边Buffer的使用情况进行合理的评估就是一个非常重要的事情。比较关心的参数包括:缓存位最大值…...

SpringBoot的配置文件(properties与yml)
文章目录 1. 配置文件的作用2. 配置文件格式3. 配置文件的使用方法3.1. properties配置文件3.1.1. 基本语法和使用3.1.2. properties优缺点分析 3.2. yml配置文件3.2.1. 基本语法与使用3.2.2. yml中单双引号问题3.2.3. yml配置不同类型的数据类型及null3.2.4. 配置对象3.2.5. 配…...

如何应用项目管理软件进行敏捷开发管理
敏捷开发(Agile Development)是一种软件开发方法论,强调在不断变化的需求和环境下,通过迭代、协作和自适应的方式来开发软件。敏捷方法的目标是提供更快、更灵活、更高质量的软件交付,以满足客户需求并实现项目成功。 …...

ARM DIY 硬件调试
前言 之前打样的几块 ARM 板,一直放着没去焊接。今天再次看到,决定把它焊起来。 加热台焊接 为了提高焊接效率,先使用加热台焊接。不过板子为双面贴片,使用加热台只能焊接一面,那就优先焊主芯片那面,并…...

DataFrame.rename()函数--Pandas
1. 函数作用 修改DataFrame的行名、列名 2. 函数语法 DataFrame.rename(mapperNone, *, indexNone, columnsNone, axisNone, copyNone, inplaceFalse, levelNone, errorsignore)3. 函数参数 参数含义mapper与axis结合使用,表示运用到axis上的值:类字…...

09- DMA(DirectMemoryAccess直接存储器访问)
DMA 09 、DMA(DirectMemoryAccess直接存储器访问)DMA配置流程 09 、DMA(DirectMemoryAccess直接存储器访问) DMA配置流程 dma.c文件 main.c文件 详见《stm32中文参考手册》表57。...

责任链模式
责任链模式 责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它用于将请求的发送者和接收者解耦,使多个对象都有机会处理请求。这种模式建立在一个处理对象的链上,每个处理对象都可以选择处理请求或…...

【BI看板】Docker-compose安装Superset,安装最新版本2.1.0
软件及环境准备 docker, docker-compose docker-compose安装 字节码安装 #wget https://github.com/docker/compose/releases/download/v2.5.0/docker-compose-linux-x86_64 #mv docker-compose-linux-x86_64 docker-compose #chmod x /usr/local/bin/docker-com…...

VS2019生成的DLL,给QT(MinGW版本)使用的小结
VS2019端: a 基于生成一个DLL的工程(要注意生成是x86,还是x64的,需要和后面的QT的App工程对应),这里不多解释了,网上多的是; b 在cpp实现文件里,假如要导出一个这样的…...

c++--SLT六大组件之间的关系
1.SLT六大组件: 容器,迭代器,算法,仿函数,适配器,空间配置器 2.六大组件之间的关系 容器:容器是STL最基础的组件,没有容器,就没有数据,容器的作用就是用来存…...

解析个人信息保护影响评估
一、个人信息保护影响评估的概念及范围(What) 什么是“个人信息保护影响评估”?如何理解?“个人信息保护影响评估”的概念未在我国高位阶的法律规定中明确,其历经从观念到实践的演变,逐渐形成业界普遍认可…...
2.阿里云对象存储OSS
1.对象存储概述 文件上传,是指将本地图片、视频、音频等文件上传到服务器上,可以供其他用户浏览或下载的过程。文件上传在项目中应用非常广泛,我们经常发抖音、发朋友圈都用到了文件上传功能。 实现文件上传服务,需要有存储的支持…...

(三)Unity开发Vision Pro——入门
3.入门 1.入门 本节涵盖了几个重要主题,可帮助您加快visionOS 平台开发速度。在这里,您将找到构建第一个 Unity PolySpatial XR 应用程序的分步指南的链接,以及 PolySpatial XR 开发时的一些开发最佳实践。 2.开发与迭代 有关先决条件、开…...

铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...

CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解
进来是需要留言的,先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码,输入的<>当成字符串处理回显到页面中,看来只是把用户输…...
【实施指南】Android客户端HTTPS双向认证实施指南
🔐 一、所需准备材料 证书文件(6类核心文件) 类型 格式 作用 Android端要求 CA根证书 .crt/.pem 验证服务器/客户端证书合法性 需预置到Android信任库 服务器证书 .crt 服务器身份证明 客户端需持有以验证服务器 客户端证书 .crt 客户端身份…...