Hello, 各位勇敢的小伙伴, 你们好, 我是大家的嘴强王者小五, 身体健康, 脑子没病.前端
本人有丰富的脱发技巧, 能让你一跃成为资深大咖.git
一看就会一写就废是本人的主旨, 菜到抠脚是本人的特色, 卑微中透着一丝丝刚强, 傻人有傻福是对我最大的安慰.github
欢迎来到
小五
的随笔系列
之前端导出Excel在线指北
.npm
双手奉上代码连接 传送门 - ajun568后端
双脚奉上最终效果图数组
观前提醒工具
👺 本文最终实现效果如上图, 具体功能为: 导出Excel + 多个Sheet + 可合并的多行表头
. 代码部分采用 React+TS
做为工具进行编写.post
👺 安装 xlsx.js npm install xlsx
搜索引擎
👺 写入Excel文件: XLSX.write(workbook, writeOpts)
编码
workbook 👇
@types string[]
: 当前 Sheet 的名称[SheetNames]: { "!refs": "A1:G7", // 表示从 第1行第A列 到 第7行第G列 "!cols": [{wpx: 80} ... ], // 表示 列宽 80px "!rows": [{hpx: 20} ... ], // 表示 行高 20px "!merges": [{s: {r: 0, c: 2}, e: {r: 0, c: 3}} ... ], // 表示 将 第0行第2列 和 第0行第3列 进行合并 (s: start, e: end, c: column, r: row) "A1": {v: "姓名"}, // 表示第1行第A列 显示数据为 "姓名", 以此类推 ... ... }
writeOpts 👇
{ type, // 数据编码, 本文采用 binary 二进制格式 bookType, // 导出类型, 本文采用 xlsx 类型 compression, // 是否使用 Gzip 压缩 }
想要下载文件, 我小A第一个表示不服, 申请出战 <a 标签的 download 属性>
经过 URL.createObjectURL(Object) 来建立下载所需的 URL. 因为每次调用都会产生新的 URL 对象, 故使用后记得释放, 释放方法 URL.revokeObjectURL(FileUrl)
经过模拟 click 事件触发 a 标签, 以实现下载
const saveAs = (obj: Blob, fileName?: string): void => { const temp = document.createElement('a') temp.download = fileName || 'download' temp.href = URL.createObjectURL(obj) temp.click() setTimeout(() => { URL.revokeObjectURL(temp.href) }, 100) }
Mock数据: 详细数据请跳转 Github, 在 mock.ts
中查看
Header 部分数据格式
[ ... { key: 'animal', value: '动物', child: [ { key: 'dog', value: '狗', child: [ { key: 'corgi', value: '柯基', }, { key: 'husky', value: '哈士奇', }, ], }, { key: 'tiger', value: '老虎', }, ], }, ... ]
Data 部分数据格式
[ { name: '黄刀小五', desc: '基于搜索引擎的复制粘贴攻城狮', watermelon: '喜欢', banana: '不喜欢', corgi: '喜欢', husky: '喜欢', tiger: '不喜欢', }, ... ]
👺 分析
🧟♂️ Code
🧟♂️ Image
{ s: { // start r: x, // row c: y, // column }, e: { ... } // end }
👺 分析
tips: 本文采用的是判断相邻 value 值是否相等进行合并, 如有需求, 建议改写为对象形式加以完善.
🧟♂️ Code
🧟♂️ Image
Object.assign
进行对象合并String.fromCharCode(65 + i)
对列进行大写字母的转换🧟♂️ Code
🧟♂️ Image
利用 new ArrayBuffer(str) 建立一个缓冲区, 使用 new Uint8Array(buf)
引用
由于 unicode 编码是 0~65535, 而 Uint8Array 范围为 0~255, 故须要按位与 0xFF, 以保持位数一致
const s2ab = (str: string): ArrayBuffer => { let buf = new ArrayBuffer(str.length) let view = new Uint8Array(buf) for (let i = 0; i !== str.length; ++i) { view[i] = str.charCodeAt(i) & 0xFF } return buf }
结合前文 准备工做 部分所讲, 导出的代码逻辑就出来了, 直接上代码
开源版本不支持设置样式, 如有需求, 可采用 付费版本 或使用 xlsx-style
, 使用方法与本文一致. 你们可参照文档自行添加样式部分.