纯前端实现 导入 与 导出 Excel

news/2024/7/21 6:55:03 标签: 前端, excel, vue

最近经常在做 不规则Excel的导入,或者一些普通Excel的导出,当前以上说的都是纯前端来实现;下面我们来聊聊经常用到的Excel导出与导入的实现方案,本文实现技术栈以 Vue2 + JS 为例

导入分类:

  1. 调用 API 完全由后端来解析数据,清洗数据,前端只负责调用 API
  2. 前端解析 Excel ,清洗数据,把对应的数据处理成 API需要的 JSON;(本文主要介绍这个)

导出分类:

  1. 调用API 完全由后端来生成Excel前端获得 API 返回的文件名,下载即可;
  2. 前端根据 JSON 数据来生成 Excel, 然后利用第三方库 file-saver 进行下载;(本文主要介绍这个)

导入 Excel 需要用到 xlsx 这个 npm 库

导出 Excel 需要用到 exceljs , file-saver 这两个

直接 npm install 对应库即可;

1. 导入Excel,处理数据

1.1 需求示例

在这里插入图片描述

假如我现在有一个这种 Excel 需要导入,前端负责解析 Excel,清洗数据,API 只需要 4-5 个有用的字段

1.2 具体实现 – html 部分

<section>
    <el-button @click="handleUpload" size="mini" type="primary">{{l("ChooseFile")}}</el-button>
    <input v-show="false" @change="handleFileChange" ref="inputFile" type="file" />
    <el-alert type="warning" :closable="false" style="margin-top:6px;">
      {{'Please Upload (xls | xlsx) Type File'}}
    </el-alert>
</section>
import XLSX from "xlsx";

handleUpload() {
  if (!this.importResult) {
    this.$refs["inputFile"].click();
  }
},
handleFileChange(e) {
      const file = e.target.files[0];
      const fileName = file.name.substring(file.name.lastIndexOf(".") + 1);
      if (fileName !== "xlsx" && fileName !== "xls") {
        this.$message.error(this.l("FileTypeError,PleaseTryAgain"));
        return;
      }
      const reader = new FileReader();
      reader.readAsBinaryString(file);
      reader.onload = (e) => {
        const result = e.target.result;
        if (!result) {
          this.errorMsg = this.l("NoData");
          this.step = 1;
          return;
        }
        if (this.importType === 1) {
          this.handleSinglePageExcel(result);
        } else {
          this.handleMultiplePageExcel(result);
        }
      };
      reader.onerror = (err) => {
        throw new Error("UpLoadError: " + err.stack);
      };
    },

1.3 具体实现 – 单个 sheet

handleSinglePageExcel(data) {
  const wb = XLSX.read(data, {
    type: "binary",
    cellDates: true,
  });
  const sheet = wb.SheetNames[0];
  const importData = XLSX.utils.sheet_to_json(wb.Sheets[sheet], {
    range: -1,
  });
  const arr = [];
  for (let i = 3; i < importData.length; i++) {
    // 处理业务逻辑
  }
  this.importResult = arr;
},

1.4 具体实现 – 多个 sheet

handleMultiplePageExcel(data) {
  const wb = XLSX.read(data, {
    type: "binary",
    cellDates: true,
  });
  const sheetList = wb.SheetNames;
  const arrMap = {}; // 多 Sheet 页数据;
  sheetList.forEach((t) => {
    const importData = XLSX.utils.sheet_to_json(wb.Sheets[t], {
      range: 2,
    });
    arrMap[t] = importData;
  });
  const arr = [];
  for (let t in arrMap) {
    const importData = arrMap[t];
    // importData : 代表每个 Sheet 页的 Excel 数据
  }
  this.importResult = arr;
},

1.4 相关参数

文件读取类型

类型预期输入
base64Base64编码类型字符串
binary二进制字符串(字节n是data.charCodeAt(n))
stringJS字符串(仅适用于UTF-8文本格式)
buffernodejs的buffer类型
array数组
file将被读取的文件路径(仅限nodejs)

常用方法

  • sheet_to_* 函数接受一个工作表和一个可选的options对象,主要是将excel文件转化为对应的数据格式,一般导入excel文件的时候使用
  • *_to_sheet 函数接受一个数据对象和一个可选的options对象,主要是将数据格式转化为excel文件,一般导出文件的时候使用
  • sheet_add_* 函数接受工作表、数据和可选选项。主要用途是更新一个现有的工作表对象

2. 根据已有数据,按需导出Excel

1.1 需求示例

在这里插入图片描述

假如我现在有一个这种查询表格需要导出,因为所有的数据都在表格中,所以不需要调用API也可以实现

1.2 具体实现

import { Workbook } from "exceljs";
import { saveAs } from "file-saver";

try {
  this.loading = true;
  // 创建一个工作簿
  const workbook = new Workbook();
  // columns 需要生成的Excel列 { prop, label, width, sheetName | Detail }
  // sheetName 需要生成的 Sheet 页, 如果只生成一个 Sheet Excel 不用考虑这里
  const sheets = _.uniq(this.columns.map((t) => t.sheetName || "Detail"));
  for (let i = 0; i < sheets.length; i++) {
    const columns = this.columns.filter(
      (t) => (t.sheetName || "Detail") === sheets[i]
    );
    // addWorksheet 添加一个 Sheet 页
    const worksheet = workbook.addWorksheet(sheets[i]);
    worksheet.columns = columns.map((t) => {
      // 需求处理
      const label = t.label ? t.label : this.propToLabel(t.prop);
      return {
        header: this.l(label), // Excel 第一行标题
        key: t.prop,
        width: label.length * 2, // Excel 列的宽度
      };
    });
    // this.list -> 当前 table 数据 
    this.list.forEach((t) => {
      const row = [];
      columns.forEach((x) => {
        row.push(t[x.prop] || "");
      });
      // 生成的 Excel Sheet 添加数据
      worksheet.addRow(row);
    });
    // 第一行 Header 行添加自定义样式
    worksheet.getRow(1).eachCell((cell, colNumber) => {
      cell.fill = {
        type: "pattern",
        pattern: "solid",
        fgColor: {
          argb: "cccccc",
        },
        bgColor: {
          argb: "#96C8FB",
        },
      };
    });
  }
  // 导出的文件名
  const code = this.exportTemple.code || new Date().getTime();
  workbook.xlsx.writeBuffer().then((buffer) => {
    // 调用 第三方库 下载刚生成好的Excel
    saveAs(
      new Blob([buffer], {
        type: "application/octet-stream",
      }),
      code + "." + "xlsx"
    );
    this.loading = false;
  });
} catch (e) {
  console.error("clinet export error", e);
} finally {
  this.loading = false;
}

如果大数据的量导出建议还是后端来实现,前端要用 websocket 做优化,避免长时间 loading 带来不好的用户体验


http://www.niftyadmin.cn/n/5003607.html

相关文章

C++ 命名空间 vector 模板

命名空间 为了区分不同库中相同名称的函数、类、变量等&#xff0c;引入概念&#xff1a;命名空间。它可作为附加信息来帮助区分它们。使用了命名空间即定义了上下文&#xff0c;本质上就是定义了一个范围。 定义命名空间 命名空间的定义使用关键字 namespace&#x…

长胜证券:三大拐点共振 看好智能驾驶新一轮行情

摘要 【长胜证券&#xff1a;三大拐点共振 看好智能驾驭新一轮行情】长胜证券研报指出&#xff0c;全球共振&#xff0c;国内智驾商场正迎来三大拐点&#xff1a;1&#xff09;技能上&#xff0c;“BEV Transformer数据闭环”新架构2023年开端上车&#xff0c;使得不依靠高精地…

初步了解android如何锁键

百年三万六千日&#xff0c;光阴只有瞬息间。 手机下面的三个图形&#xff0c;正方形&#xff0c;园形&#xff0c;三角形分别的什么建&#xff1f;都起到什么功能&#xff1f; 三角形的那个叫返回键&#xff0c;就是可以返回你的上一个操作; 圆形是HOME键&#xff0c;按一下可…

react 初级基础

react基本使用 项目创建 项目的创建命令 npx create-react-app react-basic创建一个基本元素进行渲染 // 1 导入react 和 react-dom import React from "react"; import ReactDOM from "react-dom";// 2 创建 react 元素 React提供了创建元素的api Rea…

基于 Flink CDC 构建 MySQL 和 Postgres 的 Streaming ETL

官方网址&#xff1a;https://ververica.github.io/flink-cdc-connectors/release-2.3/content/%E5%BF%AB%E9%80%9F%E4%B8%8A%E6%89%8B/mysql-postgres-tutorial-zh.html官方教程有些坑&#xff0c;经过自己实测&#xff0c;记录个笔记。 服务器环境&#xff1a; VM虚拟机&am…

您的计算机已被[new_day@torguard.tg].faust 勒索病毒感染?恢复您的数据的方法在这里!

导言&#xff1a; 随着科技的迅速发展&#xff0c;网络空间也变得越来越危险&#xff0c;而勒索病毒则是网络威胁中的一个严重问题。 [ new_daytorguard.tg ].faust 勒索病毒是最新的威胁之一&#xff0c;采用高度复杂的加密技术&#xff0c;将受害者的数据文件锁定&#xff0c…

计算机网络的故事——HTTP报文内的HTTP信息

HTTP报文内的HTTP信息 文章目录 HTTP报文内的HTTP信息一、HTTP 报文二、请求报文及响应报文的结构三、编码提升传输速率 一、HTTP 报文 HTTP报文是由多行&#xff08;CRLF作换行符&#xff09;数据构成的字符串文本&#xff0c;HTTP报文可以分为报文首部和报文主体两部分&…

【学习笔记】C++ 中 static 关键字的作用

目录 前言static 作用在变量上static 作用在全局变量上static 作用在局部变量上static 作用在成员变量上 static 作用在函数上static 作用在函数上static 作用在成员函数上 前言 在 C/C 中&#xff0c;关键字 static 在不同的应用场景下&#xff0c;有不同的作用&#xff0c;这…