Hello, 各位怯懦的小伙伴, 大家好, 我是你们的嘴强王者小五, 身体健康, 脑子没病.
自己有丰盛的脱发技巧, 能让你一跃成为资深大咖.
一看就会一写就废是自己的宗旨, 菜到抠脚是自己的特点, 低微中透着一丝丝坚强, 傻人有傻福是对我最大的刺激.
欢送来到
小五
的随笔系列
之前端导出 Excel 在线指北
.
写在后面
双手奉上代码链接 传送门 – ajun568
双脚奉上最终效果图
观前揭示
👺 本文最终实现成果如上图, 具体性能为: 导出 Excel + 多个 Sheet + 可合并的多行表头
. 代码局部采纳 React+TS
作为工具进行编写.
筹备工作
👺 装置 xlsx.js npm install xlsx
👺 写入 Excel 文件: XLSX.write(workbook, writeOpts)
workbook 👇
- SheetNames
@types string[]
: 以后 Sheet 的名称 - Sheets: 以后 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: '不喜爱',
},
...
]
头部数据处理
👺 剖析
- Header 数据为树形构造, 其深度为头部所占行数
- Header 数据要转换成 Data 数据的格局, 并与 Data 数组合并, 独特解决成导出所需格局
- 转换对象的 key 应为最小叶子结点的 key
- 转换对象的 value 应为以后层级的 value (即导出后以后行所显示的 value )
- 既然是树, 果决递归, 准没错
🧟♂️ Code
🧟♂️ Image
Merged 数据
{
s: { // start
r: x, // row
c: y, // column
},
e: {...} // end
}
👺 剖析
- 将解决后的头部数据看成一个矩阵
- 行或列中, 相邻元素若雷同, 则进行合并
tips: 本文采纳的是判断相邻 value 值是否相等进行合并, 若有需要, 倡议改写为对象模式加以欠缺.
🧟♂️ Code
🧟♂️ Image
生成 sheet 数据
- 利用
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
, 应用办法与本文统一. 大家可参照文档自行添加款式局部.
参考🔗链接
[[Github] SheetJS ~ js-xlsx](https://github.com/SheetJS/sh…
[[mySoul] 优雅 | 前后端优雅的导入导出 Excel](https://juejin.cn/post/687237…
[[Seefly] 前端应用 xlsx.js 导出有简单表头的 excel](http://www.seefly.top/archive…