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

news2024/11/18 20:18:49

原生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.innerText
      if (cellValue !== "" && cellValue == +cellValue) cellValue = +cellValue

      //Skip ranges
      ranges.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 Span
      if (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 Value
      outRow.push(cellValue !== "" ? cellValue : null)

      //Handle Colspan
      if (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.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) & 0xFF
  return 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] = ws

  var 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] = ws

  var 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)  // 打印看看  XLSX
    console.log(FileSaver)  // 打印看看  FileSaver
    console.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 = arr
      const 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 = arr
      const 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.coloradmin.cn/o/2052278.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

小区社区超市商城停车场管理系统-计算机毕设Java|springboot实战项目

&#x1f34a;作者&#xff1a;计算机毕设匠心工作室 &#x1f34a;简介&#xff1a;毕业后就一直专业从事计算机软件程序开发&#xff0c;至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长&#xff1a;按照需求定制化开发项目…

Ai学术叫叫兽全网最新创新点改进系列:丰富文章的热力图如何制作,论文装逼必用神器!极大丰富文章内容,并提升论文实验效果及其质量!

Ai学术叫叫兽全网最新创新点改进系列&#xff1a;丰富文章的热力图如何制作&#xff0c;论文装逼必用神器&#xff01;极大丰富文章内容&#xff0c;并提升论文实验效果及其质量&#xff01; 所有改进代码均经过实验测试跑通&#xff01;截止发稿时YOLOv8、YOLOv10均已改进40&…

tekton什么情况下在Dockerfile中需要用copy

kaniko配置如下 如果docker中的workDir跟tekton中的workDir不一致需要copy。也可以通过mv&#xff0c;cp达到类似效果

大数据——Flink原理

摘要 Apache Flink是一个框架和分布式处理引擎&#xff0c;用于对无界和有界数据流进行有状态计算。Flink被设计在所有常见的集群环境中运行&#xff0c;以内存执行速度和任意规模来执行计算。 1. FLink特点 1.1. 事件驱动型(Event-driven) 事件驱动型应用是一类具有状态的应…

基于 NXP LPC5516 + MC33665 + MC33774 的菊花链 HVBMS 储能方案

在 ESS 储能系统中&#xff0c;HVBMS 一般会采用两级或三级架构&#xff0c;从而实现从电池模组到电池簇&#xff0c;再到电池堆的分级管理和控制。本方案则给大家讲解基于 LPC5516 MC33665 MC33774 菊花链 HVBMS 方案&#xff0c;涵盖了 BMU、BJB、CMU&#xff0c;构建 HVBM…

简洁清新个人博客网页模板演示学习

30多款个人博客、个人网站、个人主页divcss,html在线预览,个人静态页面模板(wordpress、帝国cms、typecho主题模板).这些简洁和优雅的博客网页模板,为那些想成为创建博客的个人或媒体提供灵感设计。网页模板可以记录旅游、生活方式、食品或摄影博客等网站。部分网页模板来源网友…

MySQL8.0.0.28数据库安装配置

MySQL8.0.0.28数据库安装配置 1. 安装前的准备工作 1.1 确认目前服务器上是否存在MySQL 命令&#xff1a;rpm -qa | grep mysql 说明&#xff1a;若返回空信息&#xff0c;就说明当前环境没有安装MySQL&#xff1b;直接跳到第4步操作后续。 1.2 检查当前环境是否有自带的m…

系统编程-文件属性和目录操作

4 文件属性和目录操作 一、目录操作 -- 目录操作主要的目的&#xff1a;让程序知道路径下有什么文件存在 -- 注&#xff1a;程序在哪里运行他的工作路径就在哪里 &#xff0c;程序中所有的相对路径的文件就是基于工作路径来实现的 1、获取当前程序运行的工作路径 -- 函数头…

爬取豆瓣TOP250电影详解

一.分析网页DOM树结构 1.分析网页结构及简单爬取 豆瓣&#xff08;Douban&#xff09;是一个社区网站&#xff0c;创立于2005年3月6日。该网站以书影音起家&#xff0c;提供关于书籍、电影、音乐等作品的信息&#xff0c;其作品描述和评论都是由用户提供&#xff08;User-Gen…

MATLAB 手动实现一种高度覆盖值提取建筑物点云的方法(74)

专栏往期文章,包含本章 MATLAB 手动实现一种高度覆盖值提取建筑物点云的方法(74) 一、算法介绍二、算法实现1.代码2.效果总结一、算法介绍 手动实现一种基于高度覆盖值的建筑物点云提取方法,适用于高大的城市建筑物,比只利用高度提取建筑物的方法更加稳定和具有价值,主要…

NC 丑数

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 描述 把只包含质因…

Linux_Shell三剑客grep,awk,sed-08

三剑客的概述&#xff1a; awk、grep、sed是linux操作文本的三大利器&#xff0c;合称文本三剑客&#xff0c;也是必须掌握的linux命令之一。三者的功能都是处理文本&#xff0c;但侧重点各不相同&#xff0c;其中属awk功能最强大&#xff0c;但也最复杂。grep更适合单纯的查找…

英伟达开源 Nemotron-4-4B:小型模型,大能量

前沿科技速递&#x1f680; 在人工智能领域&#xff0c;语言模型已经成为推动自然语言处理&#xff08;NLP&#xff09;进步的关键力量。然而&#xff0c;随着模型规模的不断扩大&#xff0c;训练和部署这些大型语言模型&#xff08;LLM&#xff09;的资源成本也在急剧增加。为…

2024年8月 trueNas 容器端口只能设置大于9000问题解决

前言 这两天在搭建个人nas&#xff0c;想顺便在局域网搭建一个dns服务器&#xff0c;我采用的是jpillora/dnsmasq的docker镜像搭建的&#xff0c;但是遇到一个问题始终无法解决容器端口必须大于9000&#xff0c;而dns使用的端口是53是改不了的&#xff0c;找了很多资料发现有老…

地图相册系统的设计与实现

摘 要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时代&a…

Transformer 中自注意力机制的 一些细节理解

摘自知乎博主https://www.zhihu.com/question/362131975/answer/2182682685?utm_oi78365163782144 作者&#xff1a;月来客栈 链接&#xff1a;https://www.zhihu.com/question/362131975/answer/2182682685 1. 多头注意力机制原理 1.1 动机 首先让我们先一起来看看作者当…

IP SSL证书快速申请教程

在互联网安全领域中&#xff0c;SSL证书是比较普遍的传输数据加密方式之一。SSL证书通过建立加密通道&#xff0c;确保客户端与服务器之间传输的数据不被第三方窃取或篡改。而大多数SSL证书&#xff0c;如单域名SSL证书、多域名SSL证书以及通配符SSL证书&#xff0c;在申请时必…

颇为实用的现代化开源数据表格GristCore

GristCore&#xff1a;用Grist&#xff0c;让数据自动化&#xff0c;让工作更智能。 - 精选真开源&#xff0c;释放新价值。 概览 Grist-core项目是Grist的心脏&#xff0c;是一个创新的在线数据协作平台&#xff0c;它突破了传统电子表格的局限&#xff0c;引入了先进的自动化…

宋仕强论道之效率与成本的关系

宋仕强论道之效率与成本的关系中说&#xff0c;效率于企业的意义重大&#xff0c;一是技术发展和应用带来效率提高&#xff0c;农耕文明与工业时代分别以铁制农具应用和电气化为标志。在现阶段&#xff0c;人工智能&#xff08;AI&#xff09;是目前最有效的新技术&#xff0c;…

Linux找回root密码,帮助指令

目录 找回root密码 帮助指令 man获得帮助指令 help指令 应用实例 找回root密码 进入开机界面&#xff0c;输入e进入编辑界面。 在指定位置输入init/bin/sh 再输入ctrlx进入单用户模式。 最后输入passwd修改密码。 帮助指令 man获得帮助指令 man ls后可以看到很多指令以…