二进制数组实战 - 纯前端导出Excel文件

以往在处理数据导出相关工作时,个人习惯使用脚本语言来完成,例如nodejs、ruby等,但它们对环境都有一定依赖。在浏览器的环境下,如何完成该类型操作?下面会给出一种简单且兼容性较好的方案。

Excel的基本概念

在进行Excel导出之前,先介绍一下它的基本概念:

  • Workbook 每个Workbook对应一个Excel文件

  • Worksheet 一个Excel文件中可以同时包含多个Worksheet

使用工具

这次我们会选用SheetJS来进行Excel表格的导出

这是一个同时适用于Browser/Nodejs环境的电子表格编辑库,主要功能包括:

  • 读取并解析Excel文件
  • 编辑表格内容
  • 将数据以Excel文件形式导出

操作流程

使用SheetJS进行Excel文件的导出大致可以分为以下几步:

Step1.组织数据

首先我们将需要导出的数据组织好,推荐使用模板引擎生成,最终形成一个table节点,形如:

    <table id="user_info">
    	<thead>
    		<tr>
    			<th>序号</th>
    			<th>名字</th>
    			<th>性别</th>
    			<th>爱好</th>
    		</tr>
    	</thead>
    	<tbody>
    		<tr>
    			<td>1</td>
    			<td>Alice</td>
    			<td>女</td>
    			<td>看电影</td>
    		</tr>
    		<tr>
    			<td>2</td>
    			<td>Zacks</td>
    			<td>男</td>
    			<td>看书</td>
    		</tr>
    	</tbody>
    </table>
复制代码

Step2.使用SheetJS将dom节点或html文本转换成Workbook

// 生成一个新的workbook,然后往workbook追加worksheet
const cleanWorkbook = XLSX.utils.book_new();
const table = document.getElementById('user_info');
const worksheet = XLSX.utils.table_to_sheet(table);
XLSX.utils.book_append_sheet(cleanWorkbook, worksheet, "sheet2");

// 只需要一个worksheet的时候可以直接read method生成workbook,此时worksheet名称默认为"Sheet1"
const directWorkbook = XLSX.read(table.outerHTML, {
	type: 'string'
});

复制代码

Step3.将workbook转换为二进制

const stringToArrayBuffer = function (string) {
	const buffer = new ArrayBuffer(string.length);
	const view = new Uint8Array(buffer);
	for (let i = 0, i !== string.length; ++i) {
		view[i] = string.charCodeAt(i) & 0xFF;
	}
	return buffer;
}
const ab = stringToArrayBuffer(XLSX.write(cleanWorkbook, {
	bookType: 'xlsx',
	type: 'binary'
}));
const tmpDown = new Blob([ab], { type: '' });
复制代码

Step4.触发Excel文件的自动下载

const a = document.createElement('a');
// 利用URL.createObjectURL()方法为a元素生成blob URL
a.href = URL.createObjectURL(tmpDown)  // 创建对象超链接
a.download = 'demo.xlsx';
a.click();
复制代码

就这样,浏览器就会将生成的Excel文件自动下载到本地,下面是实际效果。

二进制数组

在上面的例子里面,我们使用了ArrayBuffer进行二进制数据的操纵,下面简单展开一下:

使用过WebGL的同学应该知道,这是浏览器与显卡之间的通信接口,为了满足JavaScript与显卡之间大量且实时的数据交换,它们之间的通信数据必须是二进制,而不能是传统的文本格式。如果以文本格式传递一个32位整数,两端都要进行数据转换,这个部分的时间损耗是不可忽略的,因此愿景还是能够直接传输二进制数据,二进制数组就是在这个背景之下诞生的。

它的组成有以下三部分:

  • ArrayBuffer对象: 代表内存之中的一段二进制数据,但不能直接操作,必须通过建立视图来进行数据操纵。
  • TypedArray对象: 通过传递ArrayBuffer的实例生成对应的内存视图,视图的数据格式共有9种,例如:Uint8Array(无符号8位整数)数组视图, Int16Array(16位整数)数组视图, Float32Array(32位浮点数)数组视图。
  • DataView对象: 与TypedArray对象类似,不同的地方在于这个对象可以自定义格式和字节序,比如第一个字节是Uint8(无符号8位整数)、第二个字节是Int16(16位整数)、第三个字节是Float32(32位浮点数)等等。
const stringToArrayBuffer = function (string) {
    const buffer = new ArrayBuffer(string.length);
    const view = new Uint8Array(buffer);
    for (let i = 0, i !== string.length; ++i) {
        view[i] = string.charCodeAt(i) & 0xFF;
    }
    return buffer;
}
复制代码

在这个转换函数里面,我们先是通过ArrayBuffer申请了一段与待转换字符串字节数等长的内存,然后通过建立Uint8的视图将二进制数据按字节装载到这段内存里面,这就是一个比较简单的js二进制数据操纵例子。

小结

通过上面的介绍,我们可以发现纯前端进行数据导出还是比较简单的。 在日常的使用中,我们需要针对不同场景来进行技术选型,从架构搭建的成本来看,纯前端的实现方案能够在不依赖服务端能力和网络的情况下完成数据导出。虽然如此,数据量较大的时候,站在性能及用户交互体验的角度考虑,在服务端完成会是更优雅的解法。

猜你喜欢

转载自juejin.im/post/5c31a5086fb9a04a102f6f50