首页 > 其他分享 >17_纯前端实现导出功能

17_纯前端实现导出功能

时间:2024-06-11 11:45:56浏览次数:14  
标签:XLSX sheet 17 worksheet 前端 导出 book const utils

js-xlsx

中文文档

  • SheetJS 出品的 js-xlsx 是一款非常方便的只需要纯 JS 即可读取和导出 excel 的工具库,功能强大,支持格式众多,支持 xls、xlsx 等十几种格式

工作类

1. 从数组(数组项为数组)创建工作表

const worksheet = XLSX.utils.aoa_to_sheet(excleData);

  • XLSX.utils.aoa_to_sheet:接收js数组并返回数据对应的工作表
    • 将一个二维数组转成 sheet,会自动处理 number、string、boolean、date 等类型数据
将数组中的数据添加到现有工作表

XLSX.utils.sheet_add_aoa(worksheet, excleData);

  • XLSX.utils.sheet_add_aoa:接收js数组并更新现有工作表

2. 从对象数组创建工作表

const worksheet = XLSX.utils.json_to_sheet(newList);

  • XLSX.utils.json_to_sheet:接收js对象数组并返回数据对应的工作表
将对象数组中的数据添加到现有工作表

XLSX.utils.sheet_add_json(worksheet, excleData);

  • XLSX.utils.sheet_add_json:接收js对象数组并更新现有工作表

3. 创建新工作簿

const workbook = XLSX.utils.book_new();

若不带参数 book_new 函数将创建一个空工作簿

单一工作表

const workbook = XLSX.utils.book_new(worksheet);
const workbook = XLSX.utils.book_new(worksheet, 'Blatte');

  • 参数1:工作表对象,它将被添加到新工作簿中
  • 参数2:工作表的名称,默认 Sheet1

4. 将工作表附加到工作簿

XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');

5. 工作表对象属性

  • worksheet['!cols']:列对象数组

    • 每个列对象对属性进行编码,包括级别、宽度和可见性
  • worksheet['!rows']:行对象数组

    • 每个行对象对属性进行编码,包括级别、高度和可见性
  • worksheets['!merges']:与工作表中合并的单元格相对应的范围对象数组

    • 纯文本格式不支持合并单元格

    • CSV 导出将写入合并范围中的所有单元格(如果存在),因此请确保仅设置范围中的第一个单元格(左上角)

快速上手

1. 操作 dom 导出

domExportExcel(id, fileName) {
  // 1. 获取表格的 dom 对象 'data-table'
  let elt = document.getElementById(id);

  // 2. 创建工作簿
  let wb = XLSX.utils.table_to_book(elt, {
    sheet: 'Sheet1'
  });

  // 3. 导出
  return XLSX.writeFile(wb, fileName)
},

2. 二维数组导出

exportExcel(excleData, excleDataTitle, fileName) {

  excleData.unshift(excleDataTitle);
  // 1. 生成工作表:aoa_to_sheet 把数组转换为工作表
  const worksheet = XLSX.utils.aoa_to_sheet(excleData);

  // 2. book_new 新建一个工作簿
  const workbook = XLSX.utils.book_new();

  // 3. book_append_sheet 将工作表添加到工作簿
  XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');

  // 4. writeFile 输出工作表
  XLSX.writeFile(workbook, fileName);
},
const excleDataTitle = ['周一', '周二', '周三', '周四', '周五'];
const excleDataArr = [
  ['语文', '数学', '历史', '政治', '英语'],
  ['数学', '数学', '政治', '英语', '英语'],
  ['政治', '英语', '历史', '政治', '数学']
];
exportExcel(excleDataArr, excleDataTitle, '课程表.xlsx');

3. 对象数组导出

exportExcel(excleDataObj, excleDataTitle, fileName) {
  // 替换 表头 -> { '周一': '语文', ... }
  const excleData = [];
  excleDataObj.map(item => {
    let o = {};
    Object.entries(item).map(([key, value]) => {
      o[excleDataTitle[key]] = value;
    })
    excleData.push(o)
  })

  // 1. 生成工作表:json_to_sheet 把json转换为工作表
  const worksheet = XLSX.utils.json_to_sheet(excleData);

  // // 设置表格样式,!cols为列宽
  // const options = {
  //   '!cols': [
  //     { wpx: 100 },
  //     { wpx: 100 },
  //     { wpx: 100 },
  //     { wpx: 100 },
  //     { wpx: 100 },
  //   ]
  // };

  // // 设置每列的列宽,10代表10个字符,注意中文占2个字符
  // worksheet['!cols'] = options['!cols'];
  // // 合并单元格
  // worksheet['!merges'] = [{ e: { c: 2, r: 2 }, s: { c: 1, r: 1 } }];

  // 2. book_new 新建一个工作簿
  const workbook = XLSX.utils.book_new();

  // 3. book_append_sheet 将工作表添加到工作簿
  XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');

  // 4. writeFile 输出工作表
  XLSX.writeFile(workbook, fileName);
},
const excleDataTitle = {
  'Monday': '周一',
  'Tuesday': '周二',
  'Wednesday': '周三',
  'Thursday': '周四',
  'Friday': '周五'
};
const excleDataObj = [
  { Monday: '语文', Tuesday: '数学', Wednesday: '历史', Thursday: '政治', Friday: '英语' },
  { Monday: '数学', Tuesday: '数学', Wednesday: '政治', Thursday: '英语', Friday: '英语' },
  { Monday: '政治', Tuesday: '英语', Wednesday: '历史', Thursday: '政治', Friday: '数学' }
];

exportExcel(excleDataObj, excleDataTitle, '课程表.xlsx');

应用

由前端生成并下载表格文件

/**
 * @typedef {object} ExportConfig
 * @prop {array[]|object[]} data 目标数据
 * @prop {'matrix'|'dictArray'} dataType 数据的数据格式
 *  - dictArray:成员是对象的数组
 *  - matrix:二维数组
 * @prop {{[key: string]: string} | string[]} headers 表头
 */

import cloneDeep from "lodash/cloneDeep";
import * as XLSX from "xlsx";

/**
 * 由前端生成并下载表格文件
 * @param {ExportConfig} setting
 */
function exportLocalSheet(setting) {
  const { dataType } = setting;

  switch (dataType) {
    case "matrix":
      exportSheetOfMatrix(setting);
      break;

    default:
      exportSheetOfDictArray(setting);
      break;
  }
}

/**
 * 下载【对象数组】的表格
 * @param {ExportConfig} setting
 */
function exportSheetOfDictArray(setting) {
  const { data, headers, fileName } = setting;
  // 替换 表头
  const tableData = data.map((row) => {
    const newRow = {};

    Object.entries(row).map(([key, value]) => {
      newRow[headers[key]] = value;
    });

    return newRow;
  });

  // 1. 生成工作表:json_to_sheet 把json转换为工作表
  const worksheet = XLSX.utils.json_to_sheet(tableData);

  // 2. book_new 新建一个工作簿
  const workbook = XLSX.utils.book_new();

  // 3. book_append_sheet 将工作表添加到工作簿
  XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");

  // 4. writeFile 输出工作表
  XLSX.writeFile(workbook, fileName);
}

/**
 * 下载【二维数组】的表格
 * @param {ExportConfig} setting
 * @param {string[]} setting.headers
 */
function exportSheetOfMatrix(setting) {
  const { data, headers, fileName } = setting;
  const tableData = cloneDeep(data);

  tableData.unshift(headers);

  // 1. 生成工作表:aoa_to_sheet 把数组转换为工作表
  const worksheet = XLSX.utils.aoa_to_sheet(tableData);

  // 2. book_new 新建一个工作簿
  const workbook = XLSX.utils.book_new();

  // 3. book_append_sheet 将工作表添加到工作簿
  XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");

  // 4. writeFile 输出工作表
  XLSX.writeFile(workbook, fileName);
}

export { exportLocalSheet, exportSheetOfDictArray, exportSheetOfMatrix };

组件实现

<template>
  <div
    v-if="isDownloadOpen"
    class="ow-download"
    :class="[`ow-download-${type}`, { 'ow-old-school': oldSchool }]">
    <!-- 简易模式 -->
    <div
      v-if="type === 'simple'"
      class="icon-btn"
      :title="btnTips"
      @click="onDownloadClick">
      <Icon type="md-download" size="16"></Icon>
    </div>
    <!-- 完整模式 -->
    <div v-else-if="type === 'complete'" class="row align-items-center">
      <Button
        type="success"
        v-bind="btnProps"
        :title="btnTips"
        @click="onDownloadClick">
        <slot>
          <Icon type="md-download" size="14"></Icon>
          下载明细
        </slot>
      </Button>
      <Dropdown
        trigger="click"
        v-if="hasExportTypes"
        @on-click="onExportTypeChange">
        <Button
          class="more-btn"
          title="选择下载格式"
          type="success"
          v-bind="btnProps">
          <Icon type="md-arrow-dropdown"></Icon>
        </Button>
        <DropdownMenu slot="list">
          <DropdownItem
            v-for="item in exportTypeSelection.options"
            :key="item.value"
            :name="item.label"
            :selected="item.label === innerExportType"
            >{{ item.label }}</DropdownItem
          >
        </DropdownMenu>
      </Dropdown>
    </div>
  </div>
</template>
<script>
import { exportLocalSheet } from "./download";

/* 下载文件的格式 */
const EXPORT_FILE_TYPES = {
  xls: 1,
  csv: 2,
  txt: 3,
  1: "xlsx",
  2: "csv",
  3: "txt",
};

export default {
  name: "LocalDownloadBtn",
  props: {
    /** 下载的数据 */
    data: Array,

    /** 下载的表头 */
    headers: Array,

    /** 下载的文件名 */
    fileName: String,

    /** 组件的类型 [simple, complete] */
    type: {
      type: String,
      default: "simple",
    },

    /** 显示下载格式选项 */
    hasExportTypes: {
      type: Boolean,
      default: true,
    },

    /** 传入的下载格式值 */
    exportType: {
      type: String,
      default: "csv",
    },

    /** type=complete 时的按钮属性 */
    btnProps: Object,

    /* 旧的样式 */
    oldSchool: Boolean,
  },
  data() {
    return {
      exportTypeSelection: {
        visible: false,
        options: [
          { label: "xlsx", value: EXPORT_FILE_TYPES.xlsx },
          { label: "csv", value: EXPORT_FILE_TYPES.csv },
          // { label: 'txt', value: EXPORT_FILE_TYPES.txt }
        ],
      },
      innerExportType: this.exportType,
    };
  },
  watch: {
    exportType(val) {
      this.innerExportType = val;
    },
  },
  computed: {
    isDownloadOpen() {
      return this.$store.state.gameConfig.isDownloadOpen;
    },
    btnTips() {
      return `点击下载,当前格式:${this.innerExportType}`;
    },
  },
  methods: {
    // 点击下载
    onDownloadClick() {
      const parmas = {};
      const downloadSetting = {
        IS_STOP_DOWNLOAD: false, // 中止下载,这里之前的组件放置的地方不一样,应该统一
        exportType: this.innerExportType,
      };

      this.$emit("beforeStart", parmas, downloadSetting);
      if (!downloadSetting.IS_STOP_DOWNLOAD) {
        exportLocalSheet({
          headers: this.headers,
          data: this.data,
          fileName: `${this.fileName}.${this.innerExportType}`,
          ...parmas,
        });
      }
    },
    onExportTypeChange(val) {
      this.innerExportType = val;
      // 通知父组件更新 exportType 的值
      this.$emit("update:exportType", val);
      this.$emit("onExportTypeChange", val);
    },
  },
};
</script>

标签:XLSX,sheet,17,worksheet,前端,导出,book,const,utils
From: https://www.cnblogs.com/pleaseAnswer/p/18241780

相关文章

  • WOS中批量导出文献后的文献信息统计查看
    1、WOS读取文献信息WOS要进行全信息的导出,需要先登录,选择WOS核心集,然后再进行检索。2、整理文献信息进Excel整理文献标题、年份、作者、关键词、摘要、期刊和被引用次数进excel表格。使用的数据格式为WOS中导出的全信息的plaintextfile。基于以下,后续可根据需求查找......
  • Java整合FreeMarker导出Pdf文件
    引入依赖<!--Freemarkerwls--> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.30</version> </dependency> <dependency> <groupId>......
  • 如何使用前端表格控件实现数据更新?
    前言小编之前分享过一篇文章叫《如何使用前端表格控件实现多数据源整合?》。今天,继续为大家介绍如何使用前端表格控件来更新已连接的数据源信息。环境准备SpreadJS在线表格编辑器:SpreadJS前端表格控件新版本新增了一款报表插件,该插件基于SpreadJS本身强大的表格能力,在DataM......
  • 【译】Visual Studio 17.10 发布了新版扩展管理器
    我们将更新的扩展管理器带给所有用户!在过去的一年里,我们已经将更新后的扩展管理器作为可选的预览功能提供,并一直期待您的反馈。基于您令人难以置信的反馈,我们现在准备从VisualStudio17.10开始提供新的扩展管理器作为默认预览功能。我们已将基本功能简化为现代风格UI,以......
  • 从零手写实现 nginx-17-nginx.conf 全局的默认配置
    前言大家好,我是老马。很高兴遇到你。我们为java开发者实现了java版本的nginxhttps://github.com/houbb/nginx4j如果你想知道servlet如何处理的,可以参考我的另一个项目:手写从零实现简易版tomcatminicat手写nginx系列如果你对nginx原理感兴趣,可以阅读:从零......
  • 01-前端开发Vscode插件配置
    01自动保存配置02空格渲染方式配置好以后,可以看到代码的空格有几个,以点的方式呈现,1个点表示1个空格03图标插件VSCodeGreatIcons04缩进推荐使用205vscode标记一整块代码文件>>首选项>>设置添加2行代码"editor.bracketPairColorization.enabled":true,"e......
  • ARC179D Portable Gate
    题意简述有一棵树\(n\)个点,你有一个门,你现在从一个你选定的点开始走,目标是所有点都至少访问一次。每次你可以选择:经过一条树边走到相邻点,花费\(1\)。将门放在当前点。将自己传送到门所在的点。求最小花费。\(n\le2\times10^5\)。分析先考虑根(出发点)固定怎么做。由于......
  • 大一新生HTML期末作业 学生个人网页设计作业 HTML5响应式个人简历网站模板 web前端网
    ......
  • 基于微信小程序+Springboot线上租房平台设计和实现【三端实现小程序+WEB响应式用户前
    感兴趣的可以先收藏起来,大家在毕设选题,项目以及论文编写等相关问题都可以给我加好友咨询一、前言介绍:近年来,我国的社会经济迅猛发展,社会对于房屋租赁的需求也在不断增多。在房屋租赁企业中面对繁琐而又庞大的信息量,为了企业和人们可以更好的了解和最快知道最新的房源信息。......
  • web前端期末大作业:旅游网页设计与实现——个人旅游博客(4页)HTML+CSS
    ......