[前端/JavaScript] 实作汇出excel下载按钮的超好用套件:ExcelJS(上)- 基础介绍与教学

简介

官方github连结: 英文文档中文文档

ExcelJS 这个套件可以高弹性的将资料汇出成excel档案
(原理:透过套件转成blob格式,再透过创建URL并触发来触发下载)

也可以汇入excel变成json格式的资料

官方文件中提供了相当多操作的介绍,包括设定样式、插入图片、对资料做处理等等
接下来介绍的内容,只是会简单的讲解如何将资料汇出成excel档案(.xslx、.csv)

有时候真的没有需要那麽华丽
只想要先有一颗可把资料变成excel可供人下载的按钮

而这个套件本身是透过JS ES6的class来把方法封装
让工程师自行使用这些方法来建构你各位想要的excel资料

和按钮啊、画面啊、事件绑定之类的没有关连
这一篇会着重在如何用js去控制你的excel内容

预告:下一篇教学会讲解如何在react中使用这个套件

环境建置

  1. 安装套件 : npm install exceljs --save
  2. 在档案中 import 套件 import ExcelJs from "exceljs";

开始使用

接下来大致上分三个步骤:建立表格、填塞资料、汇出excel并触发下载
而这些步骤都是在触发按下按钮之後所执行的,也就是说机制与流程是:

按下按钮
触发onClick function
在function内建立表格、填塞资料、汇出excel并触发下载

真的懒得看分解的话
最後面也有简易的程序码示范这个onClick function的全貌

那我们先开始分步骤讲解这个onClick function内的内容:

1. 建立表格

这个套件汇出的是一个class,并把所有资料操作、设定方法都封装在class内
所以第一步我们先new出这个class 的实例

const workbook = new ExcelJs.Workbook();

接下来所有操作都会围绕着这个名称为 workbook 的物件上

目前的workbook里面是一个空档案,里面没有任何工作表
所以我们要添加工作表的时候就使用:

const sheet = workbook.addWorksheet('工作表名称');

工作表名称可自订任意type为string的内容
使用addWorksheet 这个方法
会在我们的workbook 物件中增加一个表格,并回传他的物件

顺带解释一下,
所谓的「工作表」就是这个下面像是分页一样的东西
工作表图例

一个试算表里面可以有多个工作表

因此如果要第二个表格就只要继续使用

const sheet2 = workbook.addWorksheet('工作表2'); 这样的形式就可以了

2. 填塞资料

在一个工作表内,可以从任意位置开始塞任意大小的资料
将会使用 sheet.addTable 方法 ,参数塞这个表格的资料与格式,
根据columns和rows 这两个参数提供的阵列(array),在向右和向下的格子里进行绘制

最基本的范例如下

sheet.addTable({
    name: 'table名称',  // 表格内看不到的,算是key值,让你之後想要针对这个table去做额外设定的时候,可以指定到这个table
    ref: 'A1', // 从A1开始
    columns: [{name:'名字'},{name:'年龄'},{name:'电话'}],
    rows: [['小明','20','0987654321'],['小美','23','0912345678']]
});

最基本范例图

根据这个设定,会跑出来的表格长这样
在这个addTable传递的参数里面
还可以设置style、设置一些有的没有的、冻结窗格之类的功能

那些内容有补充在後方,总之我们先创一个最简单的

  • 进阶补充:表格资料可以不止塞一个

    也就是一张sheet中,可以分区块的於各自指定的位置中,新增多个「table」

    sheet.addTable({
        name: 'table2', 
        ref: 'E5', // 从E5开始
        headerRow: true,  // 有没有要放标头那一行 也就是columns的那行资料,如果设为flase就会那行直接无效
        columns: [{name:'栏位1'},{name:'栏位2'},{name:'栏位3'}],
        rows: [['小明','20','0987654321'],['小美','23','0912345678']]
    });
    

    两个表格

    依此类推可以新增多个
    就不用明明是两个不一样的资料表想塞在一个工作表
    硬要想办法算位置让他们错开之类的

3. 汇出excel并触发下载

在塞完所有的资料之後
使用异步的方法:workbook.xlsx.writeBuffer() 来打包资料
打包好的资料会以Promise 的形式回传

可以用.then去接收
也可以把整个onClick function标记成async ,然後使用await来接收
接收资料、创建连结、触发下载的方式如下

// 表格里面的资料都填写完成之後,订出下载的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();
});

整体范例

  • onClick function 定义 (js版本)

    import ExcelJs from "exceljs";
    
      function onClick(){
        const workbook = new ExcelJs.Workbook(); // 创建试算表档案
        const sheet = workbook.addWorksheet('工作表范例1'); //在档案中新增工作表 参数放自订名称
    
    		sheet.addTable({ // 在工作表里面指定位置、格式并用columsn与rows属性填写内容
    	    name: 'table名称',  // 表格内看不到的,让你之後想要针对这个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();
    	  });
    	}
    

    其实就是把那些步骤合在一起变成 onClick function

    实际使用就看你使用什麽框架,或原生js、jQuery + html
    绘制一个button ,绑定onClick事件
    使按钮按下後会进行「建立表格->塞资料->触发下载」的程序

    这边提供一个简易的线上Demo: 下载excel按钮范例(原生js+html)

    下载之後就会得到这样的档案

    成品

进阶:设置表格或栏位样式、以及其他常用的进阶功能

这边不会全部都介绍(真的要全部就去看官方文档,反正有翻译...)
只会提出几个比较实用/常用/简单的功能,
以及讲解到底要怎麽把这些功能设置上去

设置属性的方式

设置 工作簿/工作表/Table/栏位 的属性有两种方式

  • 第一种是在使用workbook.addWorksheet / sheet.addTable 等方法的时候
    用物件的方式把要设定的属性直接塞到Properties里面,例如:

    const sheet = workbook.addWorksheet('sheetName',{
    	views: [{showGridLines: false}]
    });
    
    const table = sheet.addTable({
        name: 'table1',
        headerRow: true,
    });
    
  • 第二种则是先取得操纵该物件的变数,再直接对物件的属性做修改

    取得物件变数的方式,除了储存addWorksheet / addTable创建时返回的变数之外
    都可以用name或是id的方式 ( 注意: id从1开始不是从0开始 )
    使用getWorksheet / getTable / getColumn /getRow 去寻找/指定,例如

    // 按 name 提取工作表
    const sheet = workbook.getWorksheet('My Sheet');
    // 按 id 提取工作表,得到workbook中第一张添加进去的sheet
    const sheet = workbook.getWorksheet(1);
    
    // 按 name 提取Table
    const table = workbook.getTable('My Table');
    // 按 id 提取Table,得到第一个add进去的table
    const table = workbook.getTable(1);
    
    // 按 name 提取(直)行
    const column = workbook.getColumn('My Column');
    // 按 id 提取行 => 取得第一行 (A)
    const column = workbook.getColumn(1);
    
    // 按 name 提取(横)列
    const row = workbook.getRow('My Row');
    // 按 id 提取列 => 取得第一列 (1)
    const row = workbook.getRow(1);
    
    // 然後直接对该物件的属性做赋
    sheet.views = [{showGridLines: false}]
    table.headerRow = true
    

接下来是介绍可以设置的参数们

工作表 (Worksheet) 可设置的参数们

  • 设置样式 views: Array<{[props: string]: any}>

    views属性为一个阵列,阵列内可以有多个物件,
    每个物件为{key: value}的型态

    范例:

    sheet.views = [
    	{showGridLines: false},
    	{state: 'frozen', xSplit: 2, ySplit: 3}
    	// 还可以有其他项目
    ]
    

    以下为views中可设定的{ key: value } 们

    • 是否显示网格 : { showGridLines: boolean }
      预设:true
      若设置为false ⇒ {showGridLines: false}
      表格的网格就会消失,如图

      去除网格范例

    • 冻结窗格: {state: 'frozen', xSplit: number, ySplit: number }
      xSplit: 要冻结的(直)行数,如果只要冻结列,就填0或是不设置(undefined)
      ySplit: 要冻结的(横)列数,如果只要冻结行,就填0或是不设置(undefined)

      范例:{state: 'frozen', xSplit: 1, ySplit: 1} 将冻结第一行&第一列

      冻结窗格范例

  • 设置工作表标签/分页颜色: properties.tabColor : {argb: string}
    预设:undefined
    可以设置工作表的标签颜色 必须吃一个key值为argb的物件
    值则为代表0~255的16进位数值共四组

    argb范例

    范例: sheetproperties.tabColor = {argb: 'FF00FF00'} 则会把标签设为绿色

    效果图:
    https://ithelp.ithome.com.tw/upload/images/20220324/20135750fn4bbjuad3.png
    可以设置不同颜色真的很可爱

  • 预设栏宽 : properties.defaultColWidth : number
    预设: undefined
    可以设置表格的预设栏宽,范例: sheetproperties.tabColor = 30

    预设栏宽

  • 预设栏高: properties.defaultRowHeight: number
    预设: 15

  • 合并储存格: worksheet.mergeCells('start:end')
    范例: worksheet.mergeCells('C1:D1')
    合并储存格范例

  • 针对指定的(直)行设定宽度: sheet.getColumn(number).width
    (其实就是先取得column物件,然後对他的width做赋值)

    范例:sheet.getColumn(3).width = 30
    C行 (第三行)的宽度就会被拉大为30
    https://ithelp.ithome.com.tw/upload/images/20220324/20135750HwMjBP4WFi.png

结语

以上! 希望这一篇可以提供给正在找这个套件教学的各位
下一篇将会示范如何在react中使用这个套件
以及示范将这个按钮包装成一个可重复使用的UI元件

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


<<:  ISO 27001 资讯安全管理系统 【解析】(十八)

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

Dungeon Mizarka 006

程序码端基础建设 Zenject简述 UI的版面配置暂时来说是足够的,接下来要开始将实际的功能逐一加...

XSS&CSRF&Replay

跨站点脚本(Cross-Site Scripting:XSS)和注入(Injection) 输入验证...

Day 26 -资料库应用小程序 设计程序介面

上一篇我们完成了资料库的建置,那麽我们现在就可以来处理如何应用啦! 开始实作 首先我们要先开启之前要...

[神经机器翻译理论与实作] 重新检视有无注意力机制的Encoder-Decoder

前言 今天是个美丽的错误,本来预计将昨日写好的 Encoder 、Decoder 、 LuongAt...

Day 12 - 阴影、透明度使用

威尔猪刚开始学设计时,也曾被老师说你的阴影不行,多观察生活周遭。What...? 当时真的不懂,只...