纯前端实现 Excel 表格的读取与生成(json 转 xlsx,xlsx 转 json)

需求

利用现有的查询和新增接口,如何在不改后端的情况下给页面增加导入和导出功能?

前端查询到数据,可以生成 xlsx 文件吗?

前端可以读取用户选择的 xlsx 文件,然后调用新增接口向后端写入数据吗?

可以!

安装 xlsx 库

通过 npm 安装

1
npm install xlsx

或者通过 CDN 引入(不推荐)

1
<script src="https://unpkg.com/xlsx/dist/xlsx.full.min.js"></script>

我安装的是 0.18.5 版本

编写导入功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import { utils, read } from 'xlsx'

/**
* xlsx 转 js 对象
* @param {File} file 可以从 <input type="file"> 的 change 事件中获取到,可以参考项目使用的 UI 库的文档,这里省略具体步骤
* @returns {Promise<Array<Object>>}
*/
function importXlsx(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onload = (event) => {
try {
const data = event.target.result
// 读取工作簿
const workbook = read(data, { type: 'binary' })
// 读取第一个工作表,如需读取指定工作表,请改为 workbook.Sheets['工作表名称']
const sheet = workbook.Sheets[workbook.SheetNames[0]]
// 将工作表转为 js 对象
const json = utils.sheet_to_json(sheet)
resolve(json)
} catch (e) {
reject(e)
}
}
reader.onerror = reject
reader.readAsBinaryString(file)
})
}

通过以上方法得到的是一个 js Array 对象,表头会自动转化为对象键,表内容会自动转化为对象值,例如——

工号姓名
1000张三
1001李四

会被转换为——

1
2
3
4
5
6
7
8
9
10
[
{
工号: '1000',
姓名: '张三',
},
{
工号: '1001',
姓名: '李四',
}
]

编写导出功能

1
2
3
4
5
6
7
8
9
10
11
12
import { utils, writeFile } from 'xlsx'

/**
* js 对象转 xlsx,如果在浏览器中运行会触发文件下载
* @param {Array<Object>} data
*/
function exportXlsx(data) {
const book = utils.book_new()
const sheet = utils.json_to_sheet(data)
utils.book_append_sheet(book, sheet)
writeFile(book, 'imaegoo.xlsx')
}

与前面的导入功能正好相反,导出时对象键会自动转化为表头,对象值会自动转化为表内容——

1
2
3
4
5
6
7
8
9
10
[
{
id: '1000',
name: '张三',
},
{
id: '1001',
name: '李四',
}
]

会被转换为——

idname
1000张三
1001李四

为了规范导出的表头,建议先通过 map 方法生成好导出对象结构,再调用导出方法——

1
2
3
4
5
6
7
8
9
10
11
/**
* 生成导出对象结构
*/
function parseData(data) {
return data.map((r) => {
return {
工号: r.id,
姓名: r.name
}
})
}

有意思的是,xlsx.writeFile 方法同时支持 node.js 和浏览器环境,在 node.js 环境运行会将文件写入当前路径,在浏览器环境运行会触发文件下载。

纯前端实现 Excel 表格的读取与生成(json 转 xlsx,xlsx 转 json)

https://www.imaegoo.com/2022/xlsx-js/

作者

iMaeGoo

发布于

2022-06-27

更新于

2022-06-27

许可协议

CC BY 4.0

评论