原生js用Export2Excel导出excel单级表头和多级表头数据方式实现

原生js用Export2Excel导出excel单级表头和多级表头数据方式实现

  • 原生js用Export2Excel导出excel单级表头和多级表头数据方式实现
    • HTML文件导入需要的文件
    • HTML文件中实现导出函数
    • HTML总代码实现汇总(直接复制代码,注意js引入路径)

原生js用Export2Excel导出excel单级表头和多级表头数据方式实现

因为项目框架的原因,不是使用纯vue开发的,所以用不了import的方式导入 file-saver 和 xlsx 的三方插件包去实现,索性我就把这两个文件下载本地,然后在HTML使用 script 标签的方式来实现。下面是具体实现方式:

HTML文件导入需要的文件

1、新建文件夹 命名为js,把对应的js文件放到里面,在js文件同级新建个表格导出.html 文件;
2、这里我用到了三个文件:FileSaver.min.js、xlsx.full.min.js、Export2Excel.js
3、注意其中的Export2Excel.js 是需要自己写的,其他两个文件去对应的GitHub地址下载即可,如果找不到可以评论区聊我,我看到可以私发你,这个Export2Excel.js 文件代码我粘贴在文章里面,直接复制使用,如下:
在这里插入图片描述

在这里插入图片描述

/* eslint-disable */
// 注意html中script js不能直接使用import方式导入文件, 需要把这两个js文件下载后,通过script方式加载进去
// import { saveAs } from 'file-saver'
// import XLSX from 'xlsx'function 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.innerTextif (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 || 1colspan = colspan || 1ranges.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 += 1462var 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 = 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]}if (cell.v == null) continuevar cell_ref = 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[cell_ref] = cell}}if (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 = {}
}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
}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['!cols'] = ['apple', 'banan'];ws['!merges'] = ranges/* add worksheet to workbook */wb.SheetNames.push(ws_name)wb.Sheets[ws_name] = wsvar wbout = XLSX.write(wb, {bookType: 'xlsx',bookSST: false,type: 'binary'})saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), "test.xlsx")
}function export_json_to_excel({multiHeader = [],header,data,filename,merges = [],autoWidth = true,bookType = 'xlsx'
} = {}) {/* original data */filename = filename || 'excel-list'data = [...data]data.unshift(header)for (let i = multiHeader.length - 1; i > -1; i--) {data.unshift(multiHeader[i])}var ws_name = "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.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]['wch'] < colWidth[i][j]['wch']) {result[j]['wch'] = colWidth[i][j]['wch']}}}ws['!cols'] = result}/* add worksheet to workbook */wb.SheetNames.push(ws_name)wb.Sheets[ws_name] = wsvar wbout = XLSX.write(wb, {bookType: bookType,bookSST: false,type: 'binary'})saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), `${filename}.${bookType}`)
}

HTML文件中实现导出函数

  <script>console.log(XLSX)  // 打印看看  XLSXconsole.log(FileSaver)  // 打印看看  FileSaverconsole.log(export_json_to_excel)  // 打印看看export_json_to_excel 方法function downLoad() {let arr = [{sno: 1000,username: "fqniu",gender: "男",age: 27,card: "4****************7"}, {sno: 1001,username: "fqniu1",gender: "男",age: 27,card: "4****************8"},{sno: 1002,username: "fqniu2",gender: "男",age: 27,card: "4****************9"}]// 单级表格const tHeader = ["编号", "姓名", "性别", "年龄", "身份证号"]const filterVal = ["sno", "username", "gender", "age", "card"]const list = arrconst data = formatJson(filterVal, list)export_json_to_excel({header: tHeader,data,filename: "单级表格",autoWidth: true,bookType: "xlsx",})}// 多级表头function downLoad1() {let arr1 = [{date: '2024-08-17',num1: '1',count1: '10',num2: '11',count2: '100',num3: '111',count3: '1000',total: '1110',},{date: '2024-08-18',num1: '2',count1: '20',num2: '22',count2: '200',num3: '222',count3: '2000',total: '2220',},{date: '2024-08-19',num1: '3',count1: '30',num2: '33',count2: '300',num3: '333',count3: '3000',total: '3330',}]let filterVal1 = ['date', 'num1', 'count1', 'num2', 'count2', 'num3', 'count3', 'total']const data1 = formatJson(filterVal1, arr1)export_json_to_excel({multiHeader: [['日期', '上期结存', '', '本期结存', '', '下期结存', '', '总数']],header: ['', '数量', '金额', '数量', '金额', '数量', '金额', ''], //表头 必填data: data1, //具体数据 必填filename: '多级表头的表格',// 要合并的单元格merges: ['A1:A2', 'B1:C1', 'D1:E1', 'F1:G1', 'H1:H2'],autoWidth: true,bookType: 'xlsx',})}function formatJson(filterVal, jsonData) {return jsonData.map((v) =>filterVal.map((j) => {if (j === "timestamp") {return parseTime(v[j])} else {return v[j]}}))}</script>

导出的Excel文件内容截图如下:

单级表头效果

在这里插入图片描述

多级级表头效果

在这里插入图片描述

注意点:

导出多级表头首先要理解,单元格合并规则:

日期 所占单元格为 A1:A3
配送信息 所占单元格为 B1:F1
姓名 所占单元格为 B2:B3

然后依次类推即可

在这里插入图片描述
注:图片引用网络,仅用于学习分享

HTML总代码实现汇总(直接复制代码,注意js引入路径)

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script src="./js/FileSaver.min.js"></script><script src="./js/xlsx.full.min.js"></script><script src="./js/Export2Excel.js"></script><script>console.log(XLSX)console.log(FileSaver)console.log(export_json_to_excel)function downLoad() {let arr = [{sno: 1000,username: "fqniu",gender: "男",age: 27,card: "4****************7"}, {sno: 1001,username: "fqniu1",gender: "男",age: 27,card: "4****************8"},{sno: 1002,username: "fqniu2",gender: "男",age: 27,card: "4****************9"}]// 单级表格const tHeader = ["编号", "姓名", "性别", "年龄", "身份证号"]const filterVal = ["sno", "username", "gender", "age", "card"]const list = arrconst data = formatJson(filterVal, list)export_json_to_excel({header: tHeader,data,filename: "单级表格",autoWidth: true,bookType: "xlsx",})}// 多级表头function downLoad1() {let arr1 = [{date: '2024-08-17',num1: '1',count1: '10',num2: '11',count2: '100',num3: '111',count3: '1000',total: '1110',},{date: '2024-08-18',num1: '2',count1: '20',num2: '22',count2: '200',num3: '222',count3: '2000',total: '2220',},{date: '2024-08-19',num1: '3',count1: '30',num2: '33',count2: '300',num3: '333',count3: '3000',total: '3330',}]let filterVal1 = ['date', 'num1', 'count1', 'num2', 'count2', 'num3', 'count3', 'total']const data1 = formatJson(filterVal1, arr1)export_json_to_excel({multiHeader: [['日期', '上期结存', '', '本期结存', '', '下期结存', '', '总数']],header: ['', '数量', '金额', '数量', '金额', '数量', '金额', ''], //表头 必填data: data1, //具体数据 必填filename: '多级表头的表格',// 要合并的单元格merges: ['A1:A2', 'B1:C1', 'D1:E1', 'F1:G1', 'H1:H2'],autoWidth: true,bookType: 'xlsx',})}function formatJson(filterVal, jsonData) {return jsonData.map((v) =>filterVal.map((j) => {if (j === "timestamp") {return parseTime(v[j])} else {return v[j]}}))}</script><div id="box">点击下载单级表格</div><div id="box1">点击下载多级表格</div><script>let box = document.getElementById('box')box.onclick = () => {downLoad()}let box1 = document.getElementById('box1')box1.onclick = () => {downLoad1()}</script></body>
</html>

以上就是我使用原生js用Export2Excel导出excel单级表头和多级表头数据方式实现的方式,内容比较简单,代码功能单一,仅限于导出个Excel内容文件,如果复杂功能,可能需要进一步研究,谢谢!

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

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

相关文章

Linux驱动入门实验班——DHT11、DS18B20模块驱动(附百问网视频链接)

目录 前言 一、DHT11模块 1.通信协议 2.数据格式 3.编程思路 ①入口函数 ②实现read函数 ③编写中断处理函数 ④***编写数据解析函数 ⑤应用程序 二、DS18B20模块 1. 通信时序 ① 初始化时序 ② 写时序 ③ 读时序 2. 常用命令 3. 编程思路 1.启动温度转换 2…

PPT分享:埃森哲-流程制造的智能工厂规划设计

在分享PPT之前&#xff0c;笔者与大家一起熟悉下&#xff0c;流程制造是什么&#xff0c;与离散制造有哪些区别。 往期回顾>> 125页PPT&#xff1a;某行业数据架构蓝图规划方案 170页PPT&#xff1a;制造业采购供应链及财务管控业务流程蓝图规划 60页PPT:集团SRM项目业…

xxl_job任务调度简单使用

一、概念 任务调度是为了自动完成特定任务&#xff0c;在约定的特定时刻去执行任务的过程 如以下应用场景&#xff1a; 某电商平台需要每天上午10点&#xff0c;下午3点&#xff0c;晚上8点发放一批优惠券 某银行系统需要在信用卡到期还款日的前三天进行短信提醒 某财务系统…

【图文并茂】ant design pro 如何对接后端个人信息接口

上一节我们有讲到如何对接登录接口的 【图文并茂】ant design pro 如何对接登录接口 仅仅能登录是最基本的&#xff0c;但是我们要进入后台还是需要另一个接口。 这个接口有两个作用&#xff1a; 来获取当前登录账号的信息&#xff0c;比如头像&#xff0c;用户名&#xff0…

大脑可视化:多种方式实现fMRI的ROI的绘图

前言 在探索神经科学的深邃领域中&#xff0c;我们常常面临着如何将复杂的脑区数据以一种清晰、直观的方式呈现给同行和公众的挑战。随着功能性磁共振成像&#xff08;fMRI&#xff09;技术的发展&#xff0c;我们拥有了更多工具来揭示大脑的奥秘。本文旨在介绍一系列笔者学习的…

深度学习从入门到精通——大模型认知理解

大模型认知 1. 传统区别与实际运用 1.1 小模型时代工作方式 小模型&#xff08;如视觉模型、语义模型、语音模型、决策/规划模型&#xff09;和大模型&#xff08;如GPT、BERT等大型预训练模型&#xff09;的工作方式和特点存在一些关键区别。 视觉模型 工作方式: 视觉模型…

鸿蒙崛起,前端/Java人才如何搭上这趟技术快车?

在科技飞速发展的今天&#xff0c;鸿蒙系统的崛起犹如一颗璀璨的新星&#xff0c;照亮了技术领域的新航道。对于前端和 Java 人才来说&#xff0c;这不仅仅是一个新的挑战&#xff0c;更是一次搭乘技术快车、实现职业飞跃的绝佳机遇。 一、鸿蒙崛起之势 鸿蒙系统自诞生以来&…

C++相关概念和易错语法(28)(可变模板参数、编译时和运行时逻辑、emplace_back)

1.可变模板参数 在C语言中我们学习的第一个函数就是printf&#xff0c;这个函数有一个特点&#xff0c;即支持任意个参数&#xff0c;即可变参数。C中引入了可变模板参数&#xff0c;我们可以在C中利用模板函数实现像printf那样的功能。但众所周知C语言是没有模板函数的&#…

三种方法加密图纸!2024如何对CAD图纸进行加密?分享给你

“机事不密则害成&#xff0c;是以君子慎密而不出也。” 此言道出了保密的重要性&#xff0c;尤其是在今日数字化时代&#xff0c;图纸作为设计领域的核心资料&#xff0c;其安全性更是至关重要。 CAD图纸作为设计行业的基石&#xff0c;不仅承载着设计师的心血与智慧&#x…

docker配置国内镜像加速

docker配置国内镜像加速 由于国内使用docker拉取镜像时&#xff0c;会经常出现连接超时的网络问题&#xff0c;所以配置Docker 加速来使用国内 的镜像加速服务&#xff0c;以提高拉取 Docker 镜像的速度。 1、备份docker配置文件 cp /etc/docker/daemon.json /etc/docker/da…

IT圈前端已死,后端快亡?这个职业却越来越缺人

前言 不知道何时&#xff0c;“前端已死&#xff0c;后端快完”的论调便充斥着整个互联网圈子&#xff0c;掘金&#xff0c;知乎&#xff0c;B站&#xff0c;牛客&#xff0c;脉脉…… 前端是什么&#xff1f; 前端通常指的是Web开发中与用户交互的部分&#xff0c;也称为客…

MyBatis核心机制

实现MyBatis核心机制环境搭建 1.核心框架示意图 2.模块搭建 1.创建maven项目 2.引入依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSc…

CoppeliaSim(V-Rep)与ROS1、ROS2接口变迁-2024-

Webots&#xff1a;Webots与ROS1、ROS2接口变迁 Gazebo&#xff1a;Gazebo与ROS1、ROS2接口变迁 ROS1 2016&#xff1a;ROS_Kinetic_18 使用V-Rep3.3.1和Matlab2015b&#xff08;vrep_ros_bridge&#xff09;续 vrep_ros_bridge 插件 一、项目背景与目标 vrep_ros_bridge 是…

Linux系统之jobs命令的基本使用

Linux系统之jobs命令的基本使用 一、jobs命令介绍二、jobs命令的使用帮助2.1 jobs命令的help帮助信息2.2 jobs命令的语法解释 三、jobs命令的基本使用3.1 运行一个后台任务3.2 列出后台所有的作业3.3 列出进程ID3.4 只列出进程ID3.5 终止后台任务3.6 只显示运行任务3.7 只显示停…

设备状态图表-甘特图

1.背景&#xff1a;设备状态监控图表&#xff0c;监控不同状态的时间段&#xff0c;可以使用甘特图来展示效果 鼠标经过时的数据提示框 2、代码实现 <template><divref"ganttChartRefs":style"{ height: 6.2rem, width: 100% }"class"bg…

视频项目开发,EasyCVR视频融合平台为何成为关键驱动力

智慧类视频项目是基于多个系统融合&#xff0c;旨在实现更广泛联动功能&#xff0c;以满足智能化应用需求为基石的信息化项目。当前&#xff0c;智慧社区、智慧园区、智慧工厂乃至智慧城市等应用场景的需求日益增长。这些智慧项目的整合进程中&#xff0c;视频融合能力扮演着不…

burpsuite xssValidator插件(xss插件)

安装 1. 商城安装插件 2. 安装环境 Download PhantomJShttps://phantomjs.org/download.htmlGitHub - NetSPI/xssValidator: This is a burp intruder extender that is designed for automation and validation of XSS

房价下跌的大环境下,我的佣金为何能逆市增长?

声明&#xff1a;此篇为 ai123.cn 原创文章&#xff0c;转载请标明出处链接&#xff1a;https://ai123.cn/2199.html &#x1f3e0;&#x1f4b0;最近房地产市场可不太景气&#xff0c;房价跌跌不休&#xff0c;咱们中介们的佣金收入也受到了影响。你知道那种心情吗&#xff1f…

【IoTDB 线上小课 06】列式写入=时序数据写入性能“利器”?

【IoTDB 视频小课】更新来啦&#xff01;今天已经是第六期了~ 关于 IoTDB&#xff0c;关于物联网&#xff0c;关于时序数据库&#xff0c;关于开源... 一个问题重点&#xff0c;3-5 分钟&#xff0c;我们讲给你听&#xff1a; 列式写入到底是&#xff1f; 上一期我们详细了解了…

汽车冷却液温度传感器的作用与检测方法

汽车冷却系统中的关键部件之一是冷却液温度传感器&#xff0c;它的位置通常在发动机的缸体或水泵附近&#xff0c;与冷却液直接接触。该传感器的作用是监测发动机冷却液的温度&#xff0c;它采用负温度系数热敏电阻&#xff0c;这种电阻随温度升高而降低。当冷却液温度达到预定…