[前端/JavaScript] 实作汇出excel下载按钮的超好用套件:ExcelJS(下)- 用React汇出exce

有关于ExcelJS这个套件的教学与说明,请先看我的上一篇文章:
[前端/ES6] 实作汇出excel下载按钮的超好用套件:ExcelJS(上)- 基础介绍

这一篇呢,我们着重于在react中使用这个套件
以及要来发挥我们react的优点,把这个按钮包装成一个通用的 UI component

会特别写这篇的原因也主要是我自己一开始在查 「react export excel」、「react 汇出excel」
找到的文件我觉得不够详尽,而且没有一个现成的、包装好的UI可以使用
好啦,废话不多说,先来做一个最基础的範例吧!

React + ExcelJS

让我们把上次的onClick function和react直接做一个简单的结合如下

react + 事件定义 (js版本)
线上 codesandbox Demo: 简易react + onClick範例

import React from "react";import ExcelJs from "exceljs";function ExportExcelButton (){  function onClick(){    const workbook = new ExcelJs.Workbook(); // 创建试算表档案    const sheet = workbook.addWorksheet('工作表範例1'); //在档案中新增工作表 参数放自订名称sheet.addTable({ // 在工作表里面指定位置、格式并用columsn与rows属性填写内容    name: 'table名称',  // 表格内看不到的,算是key值,让你之后想要针对这个table去做额外设定的时候,可以指定到这个table    ref: 'A1', // 从A1开始    columns: [{name:'名字'},{name:'年龄'},{name:'电话'}],    rows: [['小明','20','0987654321'],['小美','23','0912345678']]});    // 表格里面的资料都填写完成之后,订出下载的callback function// 异步的等待他处理完之后,创建url与连结,触发下载  workbook.xlsx.writeBuffer().then((content) => {const link = document.createElement("a");    const blobData = new Blob([content], {      type: "application/vnd.ms-excel;charset=utf-8;"    });    link.download = '测试的试算表.xlsx';    link.href = URL.createObjectURL(blobData);    link.click();  });}  return (      <button onClick={onClick}> 下载excel </button>    )};

你会发现其实这个就是把那些上次的function直接複製过来
然后render 一个button ,按下后会触发

一样是按下之后,就会得到这样的档案

成品

包装成一个通用的 Component

TS版本
(markdown好像没有支援TSX所以我只能先选typescript, 最后面return元件的语法颜色有点跑掉)

import React, { CSSProperties } from "react";import ExcelJs from "exceljs";export type SheetData = {sheetName: string,  // 工作表名称    thead: Array<string>,  // 栏位标题,例如:['姓名','年龄','电话']    tbody: Array<Array<string>>,     // 内容,例如:[['小明','20','0987654321'],['小美','23','0912345678']]    columnWidths?: Array<{number: number, width: number}> //用来指定栏宽的}interface ExportExcelButtonProps {    fileName: string, // 档案名称    sheetDatas:Array<SheetData> , // 要汇出的表格资料     disabled?: boolean, // 是不是要禁止按钮动作    buttonRef?: React.MutableRefObject<any>, // 外面用useRef传进来    style?: CSSProperties // 按钮的style}export function ExportExcelButton (props: ExportExcelButtonProps){  function onClick(){    const workbook = new ExcelJs.Workbook();    props.sheetDatas.forEach((sheetData: SheetData)=>{        const sheet = workbook.addWorksheet(sheetData.sheetName);        sheet.addTable({            name: sheetData.sheetName,            ref: `A1`, // 从A1开始            headerRow: true,            columns: sheetData.thead.map((s)=>{ return {name: s}}),            rows: sheetData.tbody        });        if (sheetData.columnWidths) {          sheetData.columnWidths.forEach((column)=>{              sheet.getColumn(column.number).width = column.width          });        }    })    // 表格里面的资料都填写完成之后,订出下载的callback function// 异步的等待他处理完之后,创建url与连结,触发下载    workbook.xlsx.writeBuffer().then((content: ExcelJs.Buffer) => {      const link = document.createElement("a");      const blob = new Blob([content], {        type: "application/vnd.ms-excel;charset=utf-8;"      });      link.download = `${props.fileName}.xlsx`;      link.href = URL.createObjectURL(blob);      link.click();    });  };  const style: CSSProperties = {      borderRadius: '5px',      ...props.style  }  return (      <button          ref={props.buttonRef}          disabled={props.disabled}          onClick={onClick}          style={style}      >        汇出excel      </button>    )};export default ExportExcelButton;

JS版本

import React from "react";import ExcelJs from "exceljs";export function ExportExcelButton (props){  function onClick(){    const workbook = new ExcelJs.Workbook();    props.sheetDatas.forEach((sheetData)=>{        const sheet = workbook.addWorksheet(sheetData.sheetName);        sheet.addTable({            name: sheetData.sheetName,            ref: `A1`, // 从A1开始            headerRow: true,            columns: sheetData.thead.map((s)=>{ return {name: s}}),            rows: sheetData.tbody        });        if (sheetData.columnWidths) {          sheetData.columnWidths.forEach((column)=>{              sheet.getColumn(column.number).width = column.width          });        }    })    // 表格里面的资料都填写完成之后,订出下载的callback function// 异步的等待他处理完之后,创建url与连结,触发下载    workbook.xlsx.writeBuffer().then((content) => {      const link = document.createElement("a");      const blob = new Blob([content], {        type: "application/vnd.ms-excel;charset=utf-8;"      });      link.download = `${props.fileName}.xlsx`;      link.href = URL.createObjectURL(blob);      link.click();    });  };  const style = {      borderRadius: '5px',      ...props.style  }  return (      <button          ref={props.buttonRef}          disabled={props.disabled}          onClick={onClick}          style={style}      >        汇出excel      </button>    )};export default ExportExcelButton;

使用範例

import ExportExcelButton from "./ExportExcelButton";function App(){const downloadData = [        {           sheetName: `工作表1`,      thead: ['姓名','年龄','电话'],      tbody: [['小明','20','0987654321'],['小美','23','0912345678']],      columnWidths: [{number: 1, width:20},{number: 2, width:10},{number: 3, width:40}]},        {           sheetName: `工作表2`,      thead: ['姓名','座号'],      tbody: [['小明','1'],['小美','2']],      columnWidths: [{number: 1, width:20}]}];return (<ExportExcelButton  fileName={'测试的试算表'}  sheetDatas={downloadData}/>)}

如此一来,就可以将JSON格式的资料,转成excel下载
而且对component外来说,只要整理好格式,试算表里面就能够有好几张工作表

这边也一样提供以上的完整範例
线上codesandbox demo: TS component 、JS component

也欢迎大家根据这个示範,去準备自己的UI库

踩到的坑

我个人是使用react搭配 nx 这套toolchain 来进行开发的
题外话提一下nx这套toolchain
他有好用的环境建置,能做应用整合、共用LIB、方便搭配jest、e2e等优点
创建应用之后会有设置production这个configurations,帮忙分出测试的打包配置与正式发布的配置
但事情就这么发生了。

错误讯息:webpack.WebpackError is not a constructor

使用环境: 使用nx 这套toolchain 建置react专案

问题发生: import 这个套件之后,就发现build专案时,只要选择production 配置
就会执行失败,并喷出错误讯息: webpack.WebpackError is not a constructor

解决方式:
主要是引入该套件之后,会产生大量warning
而预设设定在webpack.json中的production参数如下
http://img2.58codes.com/2024/201357504JaarSBcZk.png
注意到budgets的部分,里面的maximumWarning 设置了最大warning为2mb
所以只要把这个数值拉高就可以了 (个人把他直接拉高到10mb)

等等,就这样?

对。就这样。我从错误讯息中根本看不出来是喷很多警告的关係,所以他花了我一小时在那边爬文
如果各位引入套件之后,有类似的情形,可以先找找你家的webpack.json
把警告和错误讯息的上限拉高看看

结语

exceljs这个套件就介绍到这边
本来有想要示範怎么用react做一个可以异步取得资料的按钮
不过想想感觉已经跟这个套件本身脱离关係了
比较像是迁就他 触发 => 建立表格、塞资料、触发下载
这个机制所必须做的行为,跟..react 还有promise比较有关

如果有人有留言敲碗的话,我再写一篇好了
就这样!希望文章都有帮助到大家~让大家少踩一点坑
还有让exceljs的文章多一点繁体字的介绍...

喜欢这篇文的话可以帮我点一个喜欢~ 我会很开心XDD (真是虚荣的女人

以上!


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章