vue2动态导出多级表头表格

server/2024/11/20 20:27:23/

需求:导出多级表格,如下,每个人名对应的是不同的城市金钱和年龄,日期占俩行,需要根据数据进行动态展示

1.效果 

 2.关键代码讲解

2.1数据源

2.2所需插件

npm install xlsx

 2.3关键代码

创建name组和date组,金钱、城市、年龄根据name和date进行分组

javascript">  groupDataByDateAndName() {const grouped = {};this.tableData.forEach((item) => {if (!grouped[item.date]) {grouped[item.date] = {};}if (!grouped[item.date][item.name]) {grouped[item.date][item.name] = {city: item.city,money: item.money,age: item.age,};}});console.log(grouped, "分组数据");return grouped;},

 

 分组之后创建表头,注意!如果要修改代码,主要修改createHeaders函数的数据,如果一个人名对应多个属性,那么需要在name之后空出多个列headerRow1.push(name, "", ""); // 姓名列和空列

javascript">    createHeaders() {const names = Array.from(new Set(this.tableData.map((item) => item.name)));const headerRow1 = ["日期"]; // 第一行开始是“日期”const headerRow2 = [""]; // 第二行开始是空列names.forEach((name) => {headerRow1.push(name, "", ""); // 姓名列和空列headerRow2.push("城市", "金钱", "年龄"); // 每个姓名下面是城市和金钱});console.log("创建头部表格", [headerRow1, headerRow2]);return [headerRow1, headerRow2];},

 

 创建每一行的数据,最后再进行配置

javascript">    createRows(groupedData) {const rows = [];const dates = Object.keys(groupedData);const names = Array.from(new Set(this.tableData.map((item) => item.name)));dates.forEach((date) => {const row = [date]; // 每行第一列是日期names.forEach((name) => {const data = groupedData[date][name] || {};// 每个人的城市和金钱row.push(data.city || "", data.money || "", data.age || "");});rows.push(row);});console.log("创建行数据", rows);return rows;},

 

3.完整代码

注意,如果要改成自己的数据源,需要注意更改this.tableData和name,city,money,age改为自己数据源的属性,还有    horizontal: "center", //水平居中没有生效,等有解决方法了再更新

javascript"><template><div><button @click="exportToExcel">导出 Excel</button></div>
</template><script>
import * as XLSX from "xlsx";
// import XLSXStyle from "xlsx-style";
export default {data() {return {tableData: [{date: "2016-05-03",name: "张三",city: "上海",money: 1000,age: "17",},{date: "2016-05-03",name: "王小虎",city: "北京",money: 2000,age: "17",},{date: "2016-05-03",name: "李四",city: "武汉",money: 2000,age: "17",},{date: "2016-05-04",name: "张三",city: "上海",money: 23222,age: "17",},{date: "2016-05-04",name: "王小虎",city: "北京",money: 3000,age: "17",},{date: "2016-05-04",name: "李四",city: "武汉",money: 2000,age: "17",},{date: "2016-05-05",name: "张三",city: "上海",money: 9345,age: "17",},{date: "2016-05-05",name: "王小虎",city: "北京",money: 3100,age: "17",},{date: "2016-05-05",name: "李四",city: "武汉",money: 2000,age: "17",},],};},methods: {exportToExcel() {//步骤1:按日期和名称对数据进行分组const groupedData = this.groupDataByDateAndName();//步骤2:准备Excel的标题和行const headers = this.createHeaders();const rows = this.createRows(groupedData);//步骤3:创建工作表和工作簿const ws = XLSX.utils.aoa_to_sheet([headers[0], headers[1], ...rows]);//合并名称和日期列的标题单元格this.mergeHeaders(ws);// 步骤4:导出到Excel文件const wb = XLSX.utils.book_new();XLSX.utils.book_append_sheet(wb, ws, "数据");XLSX.writeFile(wb, "导出的表格.xlsx");},// 步骤1:按日期和名称对数据进行分组groupDataByDateAndName() {const grouped = {};this.tableData.forEach((item) => {if (!grouped[item.date]) {grouped[item.date] = {};}if (!grouped[item.date][item.name]) {grouped[item.date][item.name] = {city: item.city,money: item.money,age: item.age,};}});console.log(grouped, "分组数据");return grouped;},// 步骤2:为表格创建标题createHeaders() {const names = Array.from(new Set(this.tableData.map((item) => item.name)));const headerRow1 = ["日期"]; // 第一行开始是“日期”const headerRow2 = [""]; // 第二行开始是空列// 为城市和金钱年龄添加名称和列names.forEach((name) => {headerRow1.push(name, "", ""); // 姓名列和空列headerRow2.push("城市", "金钱", "年龄"); // 每个姓名下面是城市和金钱});console.log("创建头部表格", [headerRow1, headerRow2]);return [headerRow1, headerRow2];},//步骤3:基于分组数据创建行createRows(groupedData) {const rows = [];const dates = Object.keys(groupedData);const names = Array.from(new Set(this.tableData.map((item) => item.name)));dates.forEach((date) => {const row = [date]; // 每行第一列是日期names.forEach((name) => {const data = groupedData[date][name] || {};// 每个人的城市和金钱row.push(data.city || "", data.money || "", data.age || "");});rows.push(row);});console.log("创建行数据", rows);return rows;},//步骤4:根据名称列和日期列合并标题mergeHeaders(ws) {const names = Array.from(new Set(this.tableData.map((item) => item.name)));let colIndex = 1; // 从第1列(Excel工作表中的第二列)开始ws["!merges"] = ws["!merges"] || [];ws["!merges"].push({s: { r: 0, c: 0 }, //设置第一行和第二行的第一列都是日期e: { r: 1, c: 0 },});const dateCellRef = XLSX.utils.encode_cell({ r: 0, c: 0 });ws[dateCellRef] = {v: "日期",s: {alignment: {horizontal: "center", //水平居中},},};ws["!cols"] = [{ width: 21 }];// 遍历名称以合并标题单元格names.forEach((name) => {const colSpan = 3; // 每个 name 占多少列// 合并此名称的单元格ws["!merges"].push({s: { r: 0, c: colIndex }, // Start at row 0, column `colIndex`e: { r: 0, c: colIndex + colSpan - 1 }, // End at the next column});// 设置此合并单元格的对齐方式(中心对齐)const cellRef = XLSX.utils.encode_cell({ r: 0, c: colIndex });ws[cellRef] = {v: name,s: {alignment: {horizontal: "center", //水平居中},},};// 移动到下一个名称的下一组列colIndex += colSpan;});},},
};
</script>

文章到此结束,希望对你有所帮助~


http://www.ppmy.cn/server/143533.html

相关文章

2024-11-19 kron积

若A[a11 a12; a21 a22]; B[b11 b12; b21 b22]; 则C[a11*b11 a12*b11 a21*b11 a22*b11; a11*b12 a12*b12 a21*b12 a22*b12; a11*b21 a12*b21 a21*b21 a22*b21; a11*b22 a12*b22 a21*b22 a22*b22] 用MATLAB实现 方法1&#xff1a; A [a11 a12; a21 a22]; B [b11 b12; b21 b22]…

线程(一)——初识线程

概念&#xff1a; 1、线程是什么 线程是一个“执行流”。每个线程之间可以按照自己的顺序执行自己的代码&#xff0c;多个线程之间还可以同时执行多份代码。 用银行来举例子&#xff1a;一个人去银行办理业务&#xff0c;多个业务一个人跑肯定是效率不高&#xff0c;这时候就需…

【1】猫眼娱乐后端开发面试题整理

[1]. 全量索引和增量索引的区别 全量索引&#xff1a;检索系统在启动时一次性读取当前数据库中的所有数据&#xff0c;建立索引。 增量索引&#xff1a;系统运行过程中&#xff0c;监控数据库的变化&#xff0c;即增量&#xff0c;实时加载更新&#xff0c;构建索引。 [2]. …

3D Gaussian Splatting 代码层理解之Part1

2023 年初,来自法国蔚蓝海岸大学和 德国马克斯普朗克学会的作者发表了一篇题为“用于实时现场渲染的 3D 高斯泼溅”的论文3d_gaussian_splatting。该论文提出了实时神经渲染的重大进步,超越了NeRF等以往方法的实用性。高斯泼溅不仅减少了延迟,而且达到或超过了 NeRF 的渲染质…

5个Midjourney技巧,让你的图片更自然真实,没有“AI味”

您是否觉得有些AI生成的图像看起来过于完美&#xff1f;有股AI味&#xff1f;MidJourney 可以创建非常高质量的逼真图像&#xff0c;然而画面完美无瑕、栩栩如生&#xff0c;让人感觉完美得令人不安&#xff0c;几乎不真实。 比如这个&#xff0c;有点夸张&#xff1a; 大多数…

32.3 mmap的在io提速上的应用和prometheus的应用

本节重点总结 : mmap的在io提速上的应用prometheus 中mmap的应用 mmap 减少copy次数 传统IO 在开始谈零拷贝之前&#xff0c;首先要对传统的IO方式有一个概念。基于传统的IO方式&#xff0c;底层实际上通过调用read()和write()来实现。通过read()把数据从硬盘读取到内核缓…

第三十七章 如何清理docker 日志

如何清理docker 日志 目标 掌握docker 日志设置掌握docker日志的清理办法背景 在现代软件开发和部署环境中,Docker 容器技术因其轻量级、可移植性和高效资源利用的特点,已成为许多企业和开发团队的首选。Docker 容器在运行过程中会产生大量的日志信息,这些日志对于监控容器…

电子电气架构 --- 传统刷写流程怎么用在SOC上就不适用呢?

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所有人的看法和评价都是暂时的,只有自己的经历是伴随一生的,几乎所有的担忧和畏惧,都是来源于自己的想象,只有你真的去做了,才会发现有多快乐。…