前端实现导出excel表格(单行表头)

news2024/11/25 13:43:33
需求:实现勾选行导出为表格

在这里插入图片描述

一、安装插件
npm install --save file-saver xlsx

运行项目报如下警告的话 运行npm install xlsx@0.16.0 --save 来降低版本号(最初我安装的版本号是0.18.16的版本)再次运行项目就不会报如下警告了

在这里插入图片描述

二、新建一个excel.js文件

我存放的路径如下图(下面代码会引入此路径):

在这里插入图片描述

import { saveAs } from 'file-saver'
import XLSX from 'xlsx'

function generateArray(table) {
  const out = []
  const rows = table.querySelectorAll('tr')
  const ranges = []
  for (let R = 0; R < rows.length; ++R) {
    const outRow = []
    const row = rows[R]
    const columns = row.querySelectorAll('td')
    for (let C = 0; C < columns.length; ++C) {
      const cell = columns[C]
      let colspan = cell.getAttribute('colspan')
      let rowspan = cell.getAttribute('rowspan')
      let cellValue = cell.innerText
      if (cellValue !== '' && cellValue === +cellValue) cellValue = +cellValue

      ranges.forEach(function (range) {
        if (
          R >= range.s.r &&
          R <= range.e.r &&
          outRow.length >= range.s.c &&
          outRow.length <= range.e.c
        ) {
          for (let i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null)
        }
      })

      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,
          },
        })
      }

      outRow.push(cellValue !== '' ? cellValue : null)

      if (colspan) for (let k = 0; k < colspan - 1; ++k) outRow.push(null)
    }
    out.push(outRow)
  }
  return [out, ranges]
}

function datenum(v, date1904) {
  if (date1904) v += 1462
  const epoch = Date.parse(v)
  return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000)
}

function sheet_from_array_of_arrays(data) {
  const ws = {}
  const range = {
    s: {
      c: 10000000,
      r: 10000000,
    },
    e: {
      c: 0,
      r: 0,
    },
  }
  for (let R = 0; R !== data.length; ++R) {
    for (let 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
      const cell = {
        v: data[R][C],
      }
      if (cell.v === null) continue
      const 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) {
  const buf = new ArrayBuffer(s.length)
  const view = new Uint8Array(buf)
  for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xff
  return buf
}

export function export_table_to_excel(id) {
  const theTable = document.getElementById(id)
  const oo = generateArray(theTable)
  const ranges = oo[1]

  const data = oo[0]
  const ws_name = 'SheetJS'

  const wb = new Workbook(),
    ws = sheet_from_array_of_arrays(data)

  ws['!merges'] = ranges

  wb.SheetNames.push(ws_name)
  wb.Sheets[ws_name] = ws

  const wbout = XLSX.write(wb, {
    bookType: 'xlsx',
    bookSST: false,
    type: 'binary',
  })

  saveAs(
    new Blob([s2ab(wbout)], {
      type: 'application/octet-stream',
    }),
    'test.xlsx'
  )
}

export function export_json_to_excel({
  multiHeader = [],
  header,
  data,
  filename,
  merges = [],
  autoWidth = true,
  bookType = 'xlsx',
} = {}) {
  filename = filename || 'excel-list'
  data = [...data]
  data.unshift(header)

  for (let i = multiHeader.length - 1; i > -1; i--) {
    data.unshift(multiHeader[i])
  }

  const ws_name = 'SheetJS'
  const 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) {
    const colWidth = data.map((row) =>
      row.map((val) => {
        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,
          }
        }
      })
    )
    const 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
  }

  wb.SheetNames.push(ws_name)
  wb.Sheets[ws_name] = ws

  const wbout = XLSX.write(wb, {
    bookType: bookType,
    bookSST: false,
    type: 'binary',
  })
  saveAs(
    new Blob([s2ab(wbout)], {
      type: 'application/octet-stream',
    }),
    `${filename}.${bookType}`
  )
}

上面代码中修改默认导出表格的名称

在这里插入图片描述

三、组件中引入使用

<template>
  <div class="select-excel-container">
    <el-form :inline="true">
      <el-form-item>
        <el-input v-model="filename"  placeholder="请输出导出文件名称" />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="handleDownload">
          导出选中行
        </el-button>
      </el-form-item>
    </el-form>

    <el-table
      ref="multipleTable"
      border
      :data="list"
      @selection-change="handleSelectionChange"
    >
      <el-table-column align="center" type="selection" />
      <el-table-column align="center" label="序号" width="55">
        <template #default="{ $index }">
          {{ $index + 1 }}
        </template>
      </el-table-column>
      <el-table-column align="center" label="标题">
        <template #default="{ row }">
          {{ row.title }}
        </template>
      </el-table-column>
      <el-table-column align="center" label="作者">
        <template #default="{ row }">
          <el-tag>{{ row.author }}</el-tag>
        </template>
      </el-table-column>
      <el-table-column align="center" label="访问量" width="115">
        <template #default="{ row }">
          {{ row.pageViews }}
        </template>
      </el-table-column>
      <el-table-column align="center" label="时间">
        <template #default="{ row }">
          <span>{{ row.datetime }}</span>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  name: "ExportSelectExcel",
  data() {
    return {
      list: [
        {
          uuid: "3AAD8907-5Efb-9D3F-0219-8f80e67a5634",
          id: "230000198507241209",
          title: "Htqr",
          description: "较无己文日需说事酸热由写来将两市细队。",
          status: "published",
          author: "贺娟",
          datetime: "2010-09-29 07:43:20",
          pageViews: 4179,
          img:
            "https://cdn.jsdelivr.net/gh/chuzhixin/image/table/vab-image-10.jpg",
          switch: true,
          percent: 90,
          rate: 2,
          percentage: 3,
        },
        {
          uuid: "75E17e52-f7f5-CbB0-8DD5-Ef988cbe244D",
          id: "820000202202052027",
          title: "Nfxemhvce",
          description: "集最度达边光设儿就管具七土维对多身。",
          status: "draft",
          author: "郝敏",
          datetime: "1975-03-22 03:21:01",
          pageViews: 3648,
          img:
            "https://cdn.jsdelivr.net/gh/chuzhixin/image/table/vab-image-25.jpg",
          switch: true,
          percent: 85,
          rate: 3,
          percentage: 36,
        },
        {
          uuid: "d2f5cAE8-E1df-9997-918B-4C24cbCDbe82",
          id: "460000199510077216",
          title: "Dcpdyqjxpo",
          description: "都际一这他派效政认治计百这。",
          status: "published",
          author: "乔超",
          datetime: "2011-01-07 17:03:16",
          pageViews: 3799,
          img:
            "https://cdn.jsdelivr.net/gh/chuzhixin/image/table/vab-image-3.jpg",
          switch: true,
          percent: 90,
          rate: 2,
          percentage: 87,
        },
        {
          uuid: "daA2f356-1CAA-9FEA-DaE3-5ED6eFBd794C",
          id: "630000200001199589",
          title: "Hrhhzwj Drtf",
          description: "第使道具所活交克小术表商认么。",
          status: "draft",
          author: "方磊",
          datetime: "1990-03-07 20:29:11",
          pageViews: 3816,
          img:
            "https://cdn.jsdelivr.net/gh/chuzhixin/image/table/vab-image-22.jpg",
          switch: true,
          percent: 90,
          rate: 4,
          percentage: 65,
        },
        {
          uuid: "e989d59B-b2CE-33E9-2dFd-0B6e93EbadEB",
          id: "520000201106102834",
          title: "Kinltlj",
          description: "方西严办政受定每组龙适老看同将。",
          status: "draft",
          author: "罗勇",
          datetime: "1998-06-03 06:10:48",
          pageViews: 322,
          img:
            "https://cdn.jsdelivr.net/gh/chuzhixin/image/table/vab-image-9.jpg",
          switch: false,
          percent: 82,
          rate: 3,
          percentage: 70,
        },
        {
          uuid: "1DE3AEED-AFCC-bbf9-b5E8-C99e303Decdf",
          id: "340000199509093035",
          title: "Nhsfyt Ivuof",
          description: "干导划此世由空单接马发型府头。",
          status: "deleted",
          author: "熊芳",
          datetime: "1997-02-20 01:07:34",
          pageViews: 1068,
          img:
            "https://cdn.jsdelivr.net/gh/chuzhixin/image/table/vab-image-28.jpg",
          switch: false,
          percent: 80,
          rate: 3,
          percentage: 35,
        },
        {
          uuid: "fcE302cF-D71b-dAB6-c2D5-565efE1E8335",
          id: "54000020161030747X",
          title: "Wjomrsvy Gltuchp",
          description: "外改也色入王表件回里把为且得。",
          status: "published",
          author: "卢秀英",
          datetime: "2018-12-16 05:19:06",
          pageViews: 2580,
          img:
            "https://cdn.jsdelivr.net/gh/chuzhixin/image/table/vab-image-10.jpg",
          switch: true,
          percent: 90,
          rate: 3,
          percentage: 90,
        },
        {
          uuid: "8A868c6f-bAf6-A935-FbFC-DEAF2ad3EC3a",
          id: "310000201202123580",
          title: "Frmdpvb",
          description: "般时将写中千该式备重见叫技。",
          status: "deleted",
          author: "孔涛",
          datetime: "2012-10-10 04:59:24",
          pageViews: 1969,
          img:
            "https://cdn.jsdelivr.net/gh/chuzhixin/image/table/vab-image-1.jpg",
          switch: true,
          percent: 87,
          rate: 4,
          percentage: 61,
        },

      ],
      multipleSelection: [],
      downloadLoading: false,
      filename: "",
    };
  },
  created() {
  },
  methods: {
    handleSelectionChange(val) {
      this.multipleSelection = val;
    },
    handleDownload() {
      if (this.multipleSelection.length) {
        this.downloadLoading = true;
        import("@/utils/excel").then((excel) => {
          const tHeader = ["Id", "Title", "Author", "Readings", "Date","Description"];
          const filterVal = ["id", "title", "author", "pageViews", "datetime","description"];
          const list = this.multipleSelection;
          const data = this.formatJson(filterVal, list);
          console.log(data);
          console.log(list)
          excel.export_json_to_excel({
            header: tHeader,
            data,
            filename: this.filename,
          });
          this.$refs.multipleTable.clearSelection();
          this.downloadLoading = false;
        });
      } else {
        this.$message("请至少选择一行");
      }
    },
    formatJson(filterVal, jsonData) {
      return jsonData.map((v) => filterVal.map((j) => v[j]));
    },
  },
};
</script>

<style lang="less">
.select-excel-container {
  margin-top: 50px;
}
</style>

导出表格结果如下:

在这里插入图片描述

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

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

相关文章

语音分帧简述

目录 1. 分帧 1.1 非整齐分帧 1.2 整齐分帧 2. 示例代码 1. 分帧 问题1&#xff1a;总帧数如何计算&#xff1f; 记符号N为语音总长度&#xff0c;FRAME_LEN为帧长&#xff0c;OVERLAP_LEN为帧与帧之间的重叠部分&#xff0c;STEP_LEN为帧移(步长)。则总帧数N_Frames计算…

kotlin 编写一个简单的天气预报app(二)

增加界面显示openweathermap返回的信息。 在activity_main.xml里增加输入框来输入城市&#xff0c;在输入款旁边增加搜索按钮来进行查询。 然后原来显示helloworld的TextView用来显示结果。 1. 增加输入城市名字的EditText <EditTextandroid:id"id/editTextCity"…

AcrelEMS企业微电网能效管理平台实现用户侧智能配电和智能用电管理-安科瑞黄安南

摘要&#xff1a;随着科技的发展&#xff0c;电力系统正逐步向智能化、数字化、互联网化迈进。智能配电与智能用电是电力产业发展的重要方向&#xff0c;将为传统电力系统带来革命性的变革。本文将对智能配电和智能用电的概念、特点、关键技术及应用进行详细介绍。 1、智能配电…

Rust vs Go:常用语法对比(八)

题目来自 Golang vs. Rust: Which Programming Language To Choose in 2023?[1] 141. Iterate in sequence over two lists Iterate in sequence over the elements of the list items1 then items2. For each iteration print the element. 依次迭代两个列表 依次迭代列表项1…

【linux基础(一)】Linux基本指令(上)

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:Linux从入门到开通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学更多操作系统知识   &#x1f51d;&#x1f51d; 这里写目录标题 1. 前言1. 创…

[vulnhub]DC2

文章目录 [vulnhub]DC2信息收集flag1flag2cewlwpscan flag3什么是rbash&#xff1f; flag4flag5git提权 总结 [vulnhub]DC2 信息收集 扫ip&#xff0c;有两种方式&#xff1a;arp、nmap nmap -sP 192.168.56.0/24 -T4arp-scan -l192.168.56.137 扫端口&#xff1a; nmap -…

1312. 让字符串成为回文串的最少插入次数;971. 翻转二叉树以匹配先序遍历

1312. 让字符串成为回文串的最少插入次数 核心思想&#xff1a;最后的回文串有两种情况&#xff0c;一种是奇数回文串&#xff0c;一种是偶数回文串&#xff0c;奇数回文串的中心一定是原来就有的&#xff0c;偶数回文串的中心也是原来就有的。假设除去中心的部分为q,p,最后要…

Debian12中为python3配置虚拟环境及在Pycharm中使用虚拟环境

在Debian 12中&#xff0c;python默认为python 3.11。 基于应用&#xff0c;现需设置虚拟环境。 1.安装venv模块 从python3.3开始&#xff0c;配置python虚拟环境&#xff0c;可用venv模块&#xff0c;更加方便了。 执行命令&#xff1a; #apt install python3.11-venv 2.…

原型模式——对象的克隆

1、简介 1.1、概述 可以通过一个原型对象克隆出多个一模一样的对象&#xff0c;该模式被称为原型模式。 在使用原型模式时&#xff0c;需要首先创建一个原型对象&#xff0c;再通过复制这个原型对象来创建更多同类型的对象。 1.2、定义 原型模式&#xff08;Prototype Patt…

ICASSP 2023说话人识别方向论文合集(一)

ICASSP (International Conference on Acoustics, Speech and Signal Processing) 即国际声学、语音与信号处理会议&#xff0c;是IEEE主办的全世界最大、最全面的信号处理及其应用方面的顶级会议&#xff0c;在国际上享有盛誉并具有广泛的学术影响力。 今年入选 ICASSP 2023 …

【LeetCode每日一题】——946.验证栈序列

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时间频度】九【代码实现】十【提交结果】 一【题目类别】 栈 二【题目难度】 中等 三【题目编号】 946.验证栈序列 四【题目描述】 给定 pushed 和 p…

【*1900 图论】CF1328 E

Problem - E - Codeforces 题意&#xff1a; 思路&#xff1a; 注意到题目的性质&#xff1a;满足条件的路径个数是极少的&#xff0c;因为每个点离路径的距离<1 先考虑一条链&#xff0c;那么直接就选最深那个点作为端点即可 为什么&#xff0c;因为我们需要遍历所有点…

ChatGPT伦理挑战:人工智能的权利与责任

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

选读SQL经典实例笔记13_case与聚合

1. 识别非小计行 1.1. 结果集 1.2. DB2 1.3. Oracle 1.4. 超级聚合&#xff08;supera ggregate&#xff09;值 1.4.1. sql select deptno, job, sum(sal) sal,grouping(deptno) deptno_subtotals,grouping(job) job_subtotalsfrom empgroup by cube(deptno,job) 1.5. SQ…

十三、数据结构——二叉树的遍历(先序、中序和后序)详细思路和代码

二叉树遍历 在数据结构中&#xff0c;二叉树是一种常用且重要的数据结构。二叉树的遍历是指按照一定顺序访问二叉树的所有节点&#xff0c;常见的遍历方式有前序遍历、中序遍历和后序遍历。本文将详细介绍这三种遍历算法&#xff0c;并介绍最优二叉树。 二叉树的基本定义 首…

网络摄像机·监控摄像机用镜头驱动芯片(内置光圈控制)MS41908M

产品简述 MS41908M 是一款用于网络摄像机和监控摄像机的镜头 驱动芯片。 芯片内置光圈控制功能&#xff1b;通过电压驱动方式以及扭矩纹 波修正技术&#xff0c;实现了超低噪声微步驱动。 主要特点  电压驱动方式&#xff0c;256 微步驱动电路&#xff08;两通道&…

同一份数据,Redis为什么要存两次

Redis作为目前最主流的高性能缓存&#xff0c;里面有很多精妙的设计&#xff0c;其中有一种数据类型&#xff0c;当在存储的时候会同时采用两种数据结构来进行分别存储&#xff0c;那么 Redis 为什么要这么做呢&#xff1f;这么做会造成同一份数据占用两倍空间吗&#xff1f; …

Python中的元类MetaClass

引言 python中的元类MetaClass&#xff1a;本质也是一个类&#xff0c;但和普通类的用法不同&#xff0c;它可以对类内部的定义&#xff08;包括类属性和类方法&#xff09;进行动态的修改。 换句话说&#xff0c;使用元类的主要目的是为了实现在创建类时&#xff0c;能够动态…

数据库架构设计

数据库架构设计 数据库架构分类 介绍 介绍常见的 四种 数据库架构设计模型&#xff1a; 单库架构、分组架构、分片架构和分组分片架构 &#xff0c;以及每种架构的 使用场景、存在的问题和对应的解决方案 。 一、数据模型 我们以 “ 用户中心 ” 数据库作为 数据模型 &…

python核心-面向对象-方法相关-补充

class Person:__age 18def __run(self):print("pao")def _Person__run(self):print("xxx")p Person # p._Person__run()print(Person.__dict__) 内置特殊方法 信息格式化操作 # class Person: # def __init__(self, n, a): # self.name n …