vue2动态导出多级表头表格

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

1.效果 

 2.关键代码讲解

2.1数据源

2.2所需插件

npm install xlsx

 2.3关键代码

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

  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, "", ""); // 姓名列和空列

    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];},

 

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

    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", //水平居中没有生效,等有解决方法了再更新

<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.rhkb.cn/news/474486.html

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

相关文章

散户持股增厚工具:智能T0算法交易

最近市场很多都说牛市&#xff0c;但是大多数朋友怎么来的又怎么吐出去了。这会儿我们用T0的智能算法交易又可以增厚我们的持仓收益。简单来说&#xff0c;就是基于用户原有的股票持仓&#xff0c;针对同一标的&#xff0c;配合智能T0算法&#xff0c;每天全自动操作&#xff0…

独立开发:一人公司模式下副业产品的全流程

在数字经济的浪潮下&#xff0c;越来越多的开发者选择成为自由职业者或创立一人公司&#xff0c;通过副业产品开发实现个人价值与经济收益的双重提升。本文将围绕一人公司模式下副业产品的设计、开发、运营及变现落地全流程&#xff0c;提供一套实战指南&#xff0c;帮助有志于…

SD模型微调之Textual Inversion和Embedding fine-tuning

​ &#x1f33a;系列文章推荐&#x1f33a; 扩散模型系列文章正在持续的更新&#xff0c;更新节奏如下&#xff0c;先更新SD模型讲解&#xff0c;再更新相关的微调方法文章&#xff0c;敬请期待&#xff01;&#xff01;&#xff01;&#xff08;本文及其之前的文章均已更新&a…

【Vue笔记】基于vue3 + element-plus + el-dialog封装一个自定义的dialog弹出窗口组件

这篇文章,介绍一下如何使用vue3+element-plus中的el-dialog组件,自己封装一个通用的弹出窗口组件。运行效果如下所示: 目录 1.1、父子组件通信 1.2、自定义VDialog组件(【v-model】模式) 1.2.1、编写VDialog组件代码 1.2.2、使用VDialog组件 1.2.3、运行效果 1.3、自…

Spring Cloud Alibaba [Gateway]网关。

1 简介 网关作为流量的入口&#xff0c;常用功能包括路由转发、权限校验、限流控制等。而springcloudgateway 作为SpringCloud 官方推出的第二代网关框架&#xff0c;取代了Zuul网关。 1.1 SpringCloudGateway特点: &#xff08;1&#xff09;基于Spring5&#xff0c;支持响应…

不完全微分PID控制算法

不完全微分PID控制算法是一种改进的PID控制方法&#xff0c;主要针对PID控制中的微分环节对高频噪声敏感的问题。通过对微分项进行优化和改造&#xff0c;减少其对噪声的放大作用&#xff0c;同时保留对系统动态变化的响应能力。 不完全微分PID控制原理 不完全微分的核心思想是…

DataOps for LLM 的数据工程技术架构实践

导读 在 LLM 蓬勃发展的今天&#xff0c;数据工程已成为支持大规模 AI 模型训练的基石。DataOps 作为数据工程的重要方法论&#xff0c;通过优化数据集成、转换和自动化运维&#xff0c;加速数据到模型的闭环流程。本文聚焦新一代数据 & AI 集成工具- Apache SeaTunnel 在…

go-zero(七) RPC服务和ETCD

go-zero 实现 RPC 服务 在实际的开发中&#xff0c;我们是通过RPC来传递数据的&#xff0c;下面我将通过一个简单的示例&#xff0c;说明如何使用go-zero框架和 Protocol Buffers 定义 RPC 服务。 一、生成 RPC项目 在这个教程中&#xff0c;我们根据user.api文件&#xff0…

【c++丨STL】list模拟实现(附源码)

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;C、STL 目录 前言 一、节点、迭代器以及函数声明 二、list功能实现 1. 节点 2. 迭代器 迭代器的默认构造 operator* operator-> 前置和-- 后置和--…

SpringBoot:不支持发行版本17超详细解决办法

一开始linux中就已经下好了JDK21&#xff0c;但是后来创建项目的时候选用了JDK23&#xff0c;导致环境错乱&#xff0c;估计大部分都是因为这个原因&#xff0c;接下来我会一步步带大家解决。 检查系统环境&#xff08;以Ubuntu为例&#xff09; 没有下载JDK的可以在官网下载…

计算机网络中的数据包传输机制详解

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 计算机网络中的数据包传输机制详解 计算机网络中的数据包传输机制详解 计算机网络中的数据包传输机制详解 引言 数据包的基本概念…

Springboot3.3.5 启动流程之 tomcat启动流程介绍

在文章 Springboot3.3.5 启动流程&#xff08;源码分析&#xff09; 中讲到 应用上下文&#xff08;applicationContext&#xff09;刷新(refresh)时使用模板方法 onRefresh 创建了 Web Server. 本文将详细介绍 ServletWebServer — Embedded tomcat 的启动流程。 首先&…

HarmonyOs鸿蒙开发实战(9)=>解析json数据,自动生成实体Bean插件-jsonFormat使用教程(铁粉福利)

1.条件:基于HarmonyOs5.0.0版本. 2.老规矩先看效果> 3.第一步 >下载jsonFormat.jar文件,使用版本1.0.5-deveco https://plugins.jetbrains.com/plugin/24930-jsonformat/versions/stable 4.第二步 > 在DevEco Stuio中安装插件 5.第三步 > 新建bean文件&#xff…

VSCode+ESP-IDF开发ESP32-S3-DevKitC-1(2)第一个工程 LED心跳灯

VSCodeESP-IDF开发ESP32-S3-DevKitC-1&#xff08;2&#xff09;第一个工程 LED心跳灯 前言1.新建工程2.编写控制LED代码3.LED控制独立成.c和.h文件 前言 实际开发中很多时候我们需要有一个类似心跳灯或运行指示灯的灯以不同的状态闪烁以表示程序的运行状态&#xff0c;所以第…

系统掌握大语言模型提示词 - 从理论到实践

以下是我目前的一些主要个人标签&#xff1a; 6 年多头部大厂软件开发经验&#xff1b;1 年多 AI 业务应用经验&#xff0c;拥有丰富的业务提示词调优经验和模型微调经验。信仰 AGI&#xff0c;已经将 AI 通过自定义 Chatbot /搭建 Agent 融合到我的工作流中。头部大厂技术大学…

FromData格式提交接口时入参被转成JSON格式问题

本地上传文件后通过事件提交文件&#xff0c;一般先通过前端组件生成文本流&#xff0c;在通过接口提交文本流&#xff0c;提交文本流一般使用FormData的入参形式传入&#xff0c;接口请求头也默认"Content-Type": “multipart/form-data”&#xff0c;但是某些场景统…

【插件】重复执行 pytest-repeat

安装 pip3 install pytest-repeat 用法 1.命令行 pytest --count num pytest --count 32.装饰器 pytest.mark.repeat(num) #num运行次数 pytest.mark.repeat(5)#执行结果如下&#xff1a;

【Spring】循环引用 解决流程,只用一二级缓存?

文章目录 循环引用循环引用循环引用解决流程为什么不只用一二级缓存&#xff1f;:red_circle: 循环引用 循环引用 循环依赖&#xff1a;循环依赖其实就是循环引用&#xff0c;也就是bean互相持有对方&#xff0c;最终形成闭环。比如A依赖于B&#xff0c;B依赖于A 循环依赖在…

【青牛科技】视频监控器应用

1、简介&#xff1a; 我司安防产品广泛应用在视频监控器上&#xff0c;产品具有性能优良&#xff0c;可 靠性高等特点。 2、图示&#xff1a; 实物图如下&#xff1a; 3、具体应用&#xff1a; 标题&#xff1a;视频监控器应用 简介&#xff1a;视频监控器工作原理是光&#x…

机器学习day5-随机森林和线性代数1最小二乘法

十 集成学习方法之随机森林 集成学习的基本思想就是将多个分类器组合&#xff0c;从而实现一个预测效果更好的集成分类器。大致可以分为&#xff1a;Bagging&#xff0c;Boosting 和 Stacking 三大类型。 &#xff08;1&#xff09;每次有放回地从训练集中取出 n 个训练样本&…