nodejs处理xlsx文件有好几种方式,这里用的是js-xlsx库;
需求
有一个 xlsx 的文件,里面有几个不同的 sheet,需要读取这个表格中不同 sheet 的数据,并且为每个 sheet 生成对应的 json 文件。
例如有一个名为 template.xlsx
的文件,里面有两个sheet,分别为 错误码
、常见问题
,需要分别读取这两个 sheet 的内容,生成两个名为 errorCode.json
、normalQues.json
的文件。每个 json 文件中都是一个对象数组。
js-xlsx
文章比较长,可以直接拉到最后看最终代码。
首先,需要安装 xlsx 这个包:
npm install xlsx
文本使用的xlsx文件名为 template.xlsx
, 内容如下:
转成json文件的过程
引入 xlsx
并读取本地文件
const xlsx = require("xlsx"); // 想要直接操作本地文件只能采用nodejs的方式,client端无法处理
const workBook = xlsx.readFile("template.xlsx",{}) // 获取整个xlsx文档
workBook包含的内容和属性非常多,下面只截图一部分:
获取 xlsx 文件中所有的sheet的名称
console.log(workBook.SheetNames);
获取 xlsx 文件中所有的sheet的内容
cosnole.log(workBook.Sheets);
这样得到的sheets是包含所有sheet内容的一个对象,格式为:
转成json格式
const {Sheets,SheetNames} = xlsx.readFile("template.xlsx",{}) // 获取整个xlsx文档
let output = []
SheetNames.forEach(item => {
const arr = xlsx.utils.sheet_to_json(Sheets[item])
output.push(arr)
})
console.log(output)
这时会发现输出output后,得到的是这样的一个数组:
这是因为 xlsx.utils.sheet_to_json
中可以传入一些参数,通过这些参数来控制不同的输出:
(图片来源:js-xlsx 使用总结 实现前端解析excel)
针对我们的需求,在这里,我们可以给每行数据加一个表头,再给 xlsx.utils.sheet_to_json
函数加一个 { header: 2 }
的参数就可以达到想要的效果了。不同参数的效果可以参考这篇文章:xlsx.utils.sheet_to_json中header属性的研究
所以我们把刚才的表格改成这样,给它加一个表头,注意这里的表头就是后面生成的 json 文件中每个对象的属性名了。
代码上加入参数:
const xlsx = require("xlsx"); // 想要直接操作本地文件只能采用nodejs的方式,client端无法处理
const {Sheets,SheetNames} = xlsx.readFile("template.xlsx",{}) // 获取整个xlsx文档
let output = []
SheetNames.forEach(item => {
const arr = xlsx.utils.sheet_to_json(Sheets[item],{ header: 2 })
output.push(arr)
})
console.log(output)
这时得到的结果如下图,可以看到这时生成了一个二维数组,上面部分是 错误码
sheet 的输出,下面是 常见问题
sheet 的输出。
生成JSON文件
进行到这一步,json 文件格式已经正确了,接下来我们需要把每个 sheet 对应的数组放到相应的 json 文件中。可以使用 fs
库来生成 json 文件。
const xlsx = require("xlsx"); // 想要直接操作本地文件只能采用nodejs的方式,client端无法处理
const fs = require("fs");
const {Sheets,SheetNames} = xlsx.readFile("template.xlsx",{}) // 获取整个xlsx文档
SheetNames.forEach(item => {
const arr = xlsx.utils.sheet_to_json(Sheets[item],{ header: 2 })
let outputFileName = "";
switch (item) {
case "错误码":
outputFileName = "errorCode"
break;
case "常见问题":
outputFileName = "normalQues"
break;
default:
break;
}
//定义输出文件路径
fs.writeFile(`${outputFileName}.json`, JSON.stringify(arr, '' , ''), (err) => {
if (err) {
console.log(err)
} else {
console.log(`${outputFileName}.json 创建成功!!!`)
}
})
})
这时,在同一目录下,生成了对应的两个 json 文件,已经得到了我们想要的输出,需求已经实现了。
PS:如果之前有重名的文件,或者之前已经运行过一遍生成了两个json文件,再次运行代码时,不会因为之前存在这两个json文件就报错,而是会覆盖之前文件的内容。
额外设置
如果不想在同级目录下生成 JSON 文件,可以通过 path
设置不同的目录:
const path = require("path")
......
//定义输出文件路径
const outputFile = path.join(__dirname, `output/${outputFileName}.json`)
fs.writeFile(outputFile, JSON.stringify(arr, '' , ''), (err) => {
if (err) {
console.log(err)
} else {
console.log(`output/${outputFileName}.json 创建成功!!!`)
}
})
但是要最注意:必须要保证 output 文件夹在运行程序前是存在的,不然会报错:
最终代码
const xlsx = require("xlsx"); // 想要直接操作本地文件只能采用nodejs的方式,client端无法处理
const fs = require("fs");
const path = require("path")
const {Sheets,SheetNames} = xlsx.readFile("template.xlsx",{}) // 获取整个xlsx文档
SheetNames.forEach(item => {
const arr = xlsx.utils.sheet_to_json(Sheets[item],{ header: 2 })
let outputFileName = "";
switch (item) {
case "错误码":
outputFileName = "errorCode"
break;
case "常见问题":
outputFileName = "normalQues"
break;
default:
break;
}
//定义输出文件路径
const outputFile = path.join(__dirname, `output/${outputFileName}.json`)
fs.writeFile(outputFile, JSON.stringify(arr, '' , ''), (err) => {
if (err) {
console.log(err)
} else {
console.log(`output/${outputFileName}.json 创建成功!!!`)
}
})
})