当前位置:首页 » 《关注互联网》 » 正文

纯前端实现 导入 与 导出 Excel

1 人参与  2024年04月18日 12:25  分类 : 《关注互联网》  评论

点击全文阅读


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

导入分类:

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

导出分类:

调用API 完全由后端来生成Excel,前端获得 API 返回的文件名,下载即可;前端根据 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://zhangshiyu.com/post/97036.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1