有关于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参数如下
注意到budgets的部分,里面的maximumWarning 设置了最大warning为2mb
所以只要把这个数值拉高就可以了 (个人把他直接拉高到10mb)
等等,就这样?
对。就这样。我从错误讯息中根本看不出来是喷很多警告的关係,所以他花了我一小时在那边爬文
如果各位引入套件之后,有类似的情形,可以先找找你家的webpack.json
档
把警告和错误讯息的上限拉高看看
结语
exceljs这个套件就介绍到这边
本来有想要示範怎么用react做一个可以异步取得资料的按钮
不过想想感觉已经跟这个套件本身脱离关係了
比较像是迁就他 触发
=> 建立表格、塞资料、触发下载
这个机制所必须做的行为,跟..react 还有promise比较有关
如果有人有留言敲碗的话,我再写一篇好了
就这样!希望文章都有帮助到大家~让大家少踩一点坑
还有让exceljs的文章多一点繁体字的介绍...
喜欢这篇文的话可以帮我点一个喜欢~ 我会很开心XDD (真是虚荣的女人
以上!