Node.js利用js-xlsx处理Excel文件的方法详解
发布时间 - 2026-01-11 02:11:33 点击率:次简介

本文介绍用 Node.js 中的 js-xlsx 库来处理 Excel 文件。
js-xlsx 库是目前 Github 上 star 数量最多的处理 Excel 的库,功能强大,但上手难度稍大。文档有些乱,不适合快速上手。
本文对 js-xlsx 库进行一定的总结,并提供几个实用的例子供读者测试,学习,交流。
安装
$ npm install xlsx
一些概念
在使用这个库之前,先介绍库中的一些概念。
- workbook 对象,指的是整份 Excel 文档。我们在使用 js-xlsx 读取 Excel 文档之后就会获得 workbook 对象。
- worksheet 对象,指的是 Excel 文档中的表。我们知道一份 Excel 文档中可以包含很多张表,而每张表对应的就是 worksheet 对象。
- cell 对象,指的就是 worksheet 中的单元格,一个单元格就是一个 cell 对象。
它们的关系如下:
// workbook
{
SheetNames: ['sheet1', 'sheet2'],
Sheets: {
// worksheet
'sheet1': {
// cell
'A1': { ... },
// cell
'A2': { ... },
...
},
// worksheet
'sheet2': {
// cell
'A1': { ... },
// cell
'A2': { ... },
...
}
}
}
用法
基本用法
- 用
XLSX.readFile打开 Excel 文件,返回 workbook - 用
workbook.SheetNames获取表名 - 用
workbook.Sheets[xxx]通过表名获取表格 - 按自己的需求去处理表格
- 生成新的 Excel 文件
具体用法
读取 Excel 文件
import XLSX from 'xlsx';
const workbook = XLSX.readFile('someExcel.xlsx', opts);
获取 Excel 文件中的表
// 获取 Excel 中所有表名 const sheetNames = workbook.SheetNames; // 返回 ['sheet1', 'sheet2'] // 根据表名获取对应某张表 const worksheet = workbook.Sheets[sheetNames[0]];
通过 worksheet[address] 来操作表格,以 ! 开头的 key 是特殊的字段。
// 获取 A1 单元格对象
let a1 = worksheet['A1']; // 返回 { v: 'hello', t: 's', ... }
// 获取 A1 中的值
a1.v // 返回 'hello'
// 获取表的有效范围
worksheet['!ref'] // 返回 'A1:B20'
worksheet['!range'] // 返回 range 对象,{ s: { r: 0, c: 0}, e: { r: 100, c: 2 } }
// 获取合并过的单元格
worksheet['!merges'] // 返回一个包含 range 对象的列表,[ {s: { r: 0, c: 0 }, c: { r: 2, c: 1 } } ]
实战
解析 Excel 生成 JSON
Tips 事实上,你可以直接通过 XLSX.utils.sheet_to_json(worksheet) 获得同样的结果
注意 本例子中假设表的第一行为字段名
const headers = {};
const data = [];
const keys = Object.keys(worksheet);
keys
// 过滤以 ! 开头的 key
.filter(k => k[0] !== '!')
// 遍历所有单元格
.forEach(k => {
// 如 A11 中的 A
let col = k.substring(0, 1);
// 如 A11 中的 11
let row = parseInt(k.substring(1));
// 当前单元格的值
let value = worksheet[k].v;
// 保存字段名
if (row === 1) {
headers[col] = value;
return;
}
// 解析成 JSON
if (!data[row]) {
data[row] = {};
}
data[row][headers[col]] = value;
});
console.log(data); // [ { '姓名': 'test1', '年龄': 20 }, { '姓名': 'test2', '年龄': 10 } ... ]
合并表格
步骤:
- 读取多份表格
- 合并数组
Tips: 其实合并表格跟 XLSX 没什么关系,只是处理几个数组而已。
sheet1
| id | name | age |
|---|---|---|
| 1 | test1 | 30 |
| 2 | test2 | 20 |
| 3 | test3 | 18 |
sheet2
| id | country | remark |
|---|---|---|
| 1 | China | hello |
| 2 | America | world |
| 3 | Unkonw | ??? |
let sheet1 = XLSX.utils.sheet_to_json(sheet1);
let sheet2 = XLSX.utils.sheet_to_json(sheet2);
// 先合并 sheet1 和 sheet2,再对统一处理
const result = sheet1.concat(sheet2).reduce((prev, next) => {
let index = prev.findIndex((elem, i) => elem.id === next.id);
if (index === -1) {
return prev.concat(next);
} else {
prev[index] = Object.assign({}, prev[index], next);
return prev;
}
}, []);
console.log(result);
// [ { id: '1',
// name: 'test1',
// age: '30',
// country: 'China',
// remark: 'hello' },
// { id: '2',
// name: 'test2',
// age: '20',
// country: 'America',
// remark: 'world' },
// { id: '3',
// name: 'test3',
// age: '18',
// country: 'Unkonw',
// remark: '???' } ]
导出表格
步骤:
- 构建特定的数据结构,如下。
- 调用
XLSX.writeFile(workbook, filename)即可。
// workbook
{
SheetNames: ['mySheet'],
Sheets: {
'mySheet': {
'!ref': 'A1:E4', // 必须要有这个范围才能输出,否则导出的 excel 会是一个空表
A1: { v: 'id' },
...
}
}
}
var _headers = ['id', 'name', 'age', 'country', 'remark']
var _data = [ { id: '1',
name: 'test1',
age: '30',
country: 'China',
remark: 'hello' },
{ id: '2',
name: 'test2',
age: '20',
country: 'America',
remark: 'world' },
{ id: '3',
name: 'test3',
age: '18',
country: 'Unkonw',
remark: '???' } ];
var headers = _headers
// 为 _headers 添加对应的单元格位置
// [ { v: 'id', position: 'A1' },
// { v: 'name', position: 'B1' },
// { v: 'age', position: 'C1' },
// { v: 'country', position: 'D1' },
// { v: 'remark', position: 'E1' } ]
.map((v, i) => Object.assign({}, {v: v, position: String.fromCharCode(65+i) + 1 }))
// 转换成 worksheet 需要的结构
// { A1: { v: 'id' },
// B1: { v: 'name' },
// C1: { v: 'age' },
// D1: { v: 'country' },
// E1: { v: 'remark' } }
.reduce((prev, next) => Object.assign({}, prev, {[next.position]: {v: next.v}}), {});
var data = _data
// 匹配 headers 的位置,生成对应的单元格数据
// [ [ { v: '1', position: 'A2' },
// { v: 'test1', position: 'B2' },
// { v: '30', position: 'C2' },
// { v: 'China', position: 'D2' },
// { v: 'hello', position: 'E2' } ],
// [ { v: '2', position: 'A3' },
// { v: 'test2', position: 'B3' },
// { v: '20', position: 'C3' },
// { v: 'America', position: 'D3' },
// { v: 'world', position: 'E3' } ],
// [ { v: '3', position: 'A4' },
// { v: 'test3', position: 'B4' },
// { v: '18', position: 'C4' },
// { v: 'Unkonw', position: 'D4' },
// { v: '???', position: 'E4' } ] ]
.map((v, i) => _headers.map((k, j) => Object.assign({}, { v: v[k], position: String.fromCharCode(65+j) + (i+2) })))
// 对刚才的结果进行降维处理(二维数组变成一维数组)
// [ { v: '1', position: 'A2' },
// { v: 'test1', position: 'B2' },
// { v: '30', position: 'C2' },
// { v: 'China', position: 'D2' },
// { v: 'hello', position: 'E2' },
// { v: '2', position: 'A3' },
// { v: 'test2', position: 'B3' },
// { v: '20', position: 'C3' },
// { v: 'America', position: 'D3' },
// { v: 'world', position: 'E3' },
// { v: '3', position: 'A4' },
// { v: 'test3', position: 'B4' },
// { v: '18', position: 'C4' },
// { v: 'Unkonw', position: 'D4' },
// { v: '???', position: 'E4' } ]
.reduce((prev, next) => prev.concat(next))
// 转换成 worksheet 需要的结构
// { A2: { v: '1' },
// B2: { v: 'test1' },
// C2: { v: '30' },
// D2: { v: 'China' },
// E2: { v: 'hello' },
// A3: { v: '2' },
// B3: { v: 'test2' },
// C3: { v: '20' },
// D3: { v: 'America' },
// E3: { v: 'world' },
// A4: { v: '3' },
// B4: { v: 'test3' },
// C4: { v: '18' },
// D4: { v: 'Unkonw' },
// E4: { v: '???' } }
.reduce((prev, next) => Object.assign({}, prev, {[next.position]: {v: next.v}}), {});
// 合并 headers 和 data
var output = Object.assign({}, headers, data);
// 获取所有单元格的位置
var outputPos = Object.keys(output);
// 计算出范围
var ref = outputPos[0] + ':' + outputPos[outputPos.length - 1];
// 构建 workbook 对象
var wb = {
SheetNames: ['mySheet'],
Sheets: {
'mySheet': Object.assign({}, output, { '!ref': ref })
}
};
// 导出 Excel
XLSX.writeFile(wb, 'output.xlsx');
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。
出处
http://scarletsky.github.io/2016/01/30/nodejs-process-excel/
参考资料
https://github.com/SheetJS/js-xlsx
http://stackoverflow.com/questions/30859901/parse-xlsx-with-node-and-create-json
# nodejs读取excel文件
# node
# xlsx
# 读取excel
# 导出excel
# @vue/cli4升级@vue/cli5 node.js polyfills错误的解决方式
# 利用Chrome DevTools直接调试Node.js和JavaScript的方法详解(并行)
# Node.js与Sails ~项目结构与Mvc实现及日志机制
# node.js中的fs.lstatSync方法使用说明
# Node.js 构建命令行工具之实现 ls 命令的 -a&n
# 单元格
# 文档
# 几个
# 指的是
# 转换成
# 自己的
# 是一个
# 字段名
# 就会
# 你可以
# 要有
# 遍历
# 数据结构
# 不适合
# 这篇文章
# 谢谢大家
# 参考资料
# 使用这个
# 计算出
# 再对
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Laravel如何使用模型观察者?(Observer代码示例)
jQuery 常见小例汇总
如何将凡科建站内容保存为本地文件?
高防服务器:AI智能防御DDoS攻击与数据安全保障
Laravel Eloquent关联是什么_Laravel模型一对一与一对多关系精讲
如何快速查询域名建站关键信息?
手机网站制作与建设方案,手机网站如何建设?
java ZXing生成二维码及条码实例分享
UC浏览器如何切换小说阅读源_UC浏览器阅读源切换【方法】
Python函数文档自动校验_规范解析【教程】
如何获取PHP WAP自助建站系统源码?
如何有效防御Web建站篡改攻击?
Laravel如何实现多表关联模型定义_Laravel多对多关系及中间表数据存取【方法】
Laravel如何处理CORS跨域问题_Laravel项目CORS配置与解决方案
Laravel怎么实现前端Toast弹窗提示_Laravel Session闪存数据Flash传递给前端【方法】
北京网站制作公司哪家好一点,北京租房网站有哪些?
制作ppt免费网站有哪些,有哪些比较好的ppt模板下载网站?
Laravel Vite是做什么的_Laravel前端资源打包工具Vite配置与使用
三星、SK海力士获美批准:可向中国出口芯片制造设备
Laravel如何发送系统通知?(Notification渠道示例)
如何在香港服务器上快速搭建免备案网站?
Win11怎么查看显卡温度 Win11任务管理器查看GPU温度【技巧】
网站制作软件免费下载安装,有哪些免费下载的软件网站?
JavaScript如何实现路由_前端路由原理是什么
Laravel如何实现文件上传和存储?(本地与S3配置)
Laravel怎么实现支付功能_Laravel集成支付宝微信支付
Laravel如何实现API资源集合?(Resource Collection教程)
佛山网站制作系统,佛山企业变更地址网上办理步骤?
Bootstrap整体框架之JavaScript插件架构
详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)
免费视频制作网站,更新又快又好的免费电影网站?
如何在景安服务器上快速搭建个人网站?
Laravel如何设置定时任务(Cron Job)_Laravel调度器与任务计划配置
在线制作视频的网站有哪些,电脑如何制作视频短片?
公司网站制作需要多少钱,找人做公司网站需要多少钱?
Laravel怎么配置.env环境变量_Laravel生产环境敏感数据保护与读取【方法】
Laravel如何处理文件下载请求?(Response示例)
如何在HTML表单中获取用户输入并用JavaScript动态控制复利计算循环
Laravel如何使用Blade模板引擎?(完整语法和示例)
韩国服务器如何优化跨境访问实现高效连接?
中国移动官方网站首页入口 中国移动官网网页登录
如何用手机制作网站和网页,手机移动端的网站能制作成中英双语的吗?
Win11关机界面怎么改_Win11自定义关机画面设置【工具】
Laravel如何实现本地化和多语言支持_Laravel多语言配置与翻译文件管理
北京网页设计制作网站有哪些,继续教育自动播放怎么设置?
网站制作大概要多少钱一个,做一个平台网站大概多少钱?
美食网站链接制作教程视频,哪个教做美食的网站比较专业点?
Laravel如何使用API Resources格式化JSON响应_Laravel数据资源封装与格式化输出
Laravel如何使用withoutEvents方法临时禁用模型事件
Laravel怎么为数据库表字段添加索引以优化查询

