当前位置: 首页 > 后端技术 > Node.js

使用nodejs实现,json文件自动转excel的工具

时间:2023-04-03 13:55:05 Node.js

项目这段时间,需要给业务人员翻译json格式的文档。每次都手动翻译很麻烦,所以想写一篇高质量的。自动化工具来实现这一点。说到实现,最初的想法是用“json2excelstart”这样的命令,然后自己运行。和vue一样,react运行命令。首先我们npminit新建一个项目project,创建我们项目的核心文件json2excel.js,运行nodejson2exce.js,然后控制台就可以打印东西了。将一个文件转换成另一个文件,我们需要知道文件的路径和保存的位置,所以命令设计为:json2excelstartinpathoutpath我们使用一个非常好用的命令行辅助包“commander”来提示对于命令输入,json2excel.js如下,constprogram=require('commander')//定义当前版本程序.version(require('../package').version)//定义命令方法程序。usage('[inPath][toPath]')program.command('start[paths...]').description('从JSON到csv的转换').alias('-s').action(paths=>require('./command/j2c')(paths))program.parse(process.argv)if(!program.args.length){program.help()}然后运行??nodejson2excel.js你会看(bin还没有安装command,所以用nodejson2excel代替json2excel),很wow的操作,可以看到命令提示符。.command()是定义命令及其背后的参数。我们定义了paths.description()是描述。alias()是命令的别名。action()是运行命令时要执行的操作,路径是命令中传递的参数我们新建一个../command/j2c.js,当我们在.action()中接受命令参数时module.exports=(paths)=>{//这将获取输入和输出路径let[inPath,outPath]=paths}如果命令参数不附带吗?例如:nodejson2excelstart没有路径然后回车,那么我们再引导用户输入,使用co和co-prompt这两个工具来编码:../command/j2c.jsconstco=require('co')constprompt=require('co-prompt')module.exports=(paths)=>{co(function*(){let[inPath,outPath]=paths//处理用户输入inPath=inPath?inPath:yieldprompt('Inputfiledirectory:')outPath=outPath?outPath:(yieldprompt('Outputfiledirectory:'))||inPath})}co接受generator函数,主要写在异步操作用于同步处理。运行nodejson2excelstart这样就可以得到输入输出的路径,用户体验满满的,太棒了。接下来就是通过获取的输入路径获取json文件,使用“glob”工具,通过正则匹配获取inpath路径下的所有json文件。站在巨人的肩膀上,事半功倍。代码如下:拿到json文件,我们开始转换成Excel,csv是和json一样简单的数据结构,我们把json转换成csv格式。下面是json格式和csv格式的对比。这样看,转换并不困难。左边是json数据格式,右边是字符串,可以这样理解。我们使用的是“json2csv”包,大家有时间也可以自己转换拼接。读取json文件并将其转换为scv:constJson2csvParser=require('json2csv').Parserfor(letfilenameinfiles){//同步读取文件letjsonData=fs.readFileSync(files[filename])jsonData=JSON.parse(jsonData)//json2csv转换constfields=Object.keys(jsonData[0])constjson2csvParser=newJson2csvParser({fields})constcsvData=json2csvParser.parse(jsonData)//写入的文件名constoutputFileName=`${outPath}/${filename}.csv`//写入文件consterr=fs.writeFileSync(outputFileName,csvData)if(err){returnconsole.log(err)}else{console.log(`-${filename}.json转换成功!`)}}运行后可以得到一个.csv文件,一个简单的实现就完成了。优化细节实现:办公室会显示乱码,必须定义为UTF-8存储格式。//OfficeExcel需要BOM表头来定义UTF-8编码格式constBOM=Buffer.from('\uFEFF')constcsvData=Buffer.concat([BOM,Buffer.from(csvData)])如果输出路径不存在,存储不会成功,必须先创建目录//如果没有文件夹,则创建if(!fs.existsSync(outPath)){fs.mkdirSync(outPath)}JSON格式数据,有是对象和数组,如果是对象就转成数组//如果是对象就把对象的每个键值对转成'key','value'的数组项letjsonData,fieldsif(Object.prototype.toString.call(jsonData)==='[objectObject]'){jsonData=Object.keys(jsonData).map(key=>({key:key,value:jsonData[key]}))fields=['key','value']}if(Object.prototype.toString.call(jsonData)==='[objectArray]'){jsonData=jsonDatafields=Object.keys(jsonData[0])}operationwithhintsandoutputtextwithcolor//使用一个非常方便的工具chalkconstchalk=require('chalk')//比如在开始转换之前添加提示console.log(chalk.green('StartConversion:'))存储显示文件存储成功的路径,退出进程//提示输出文件目录console.log(chalk.blue(`-请去查看文件:${chalk.underline(path.join(process.cwd(),outPath))}`))//退出进程process.exit()的完整代码如下:'usestrict'constfs=要求('fs')constpath=require('path')constchalk=require('chalk')constglob=require('glob')constco=require('co')constprompt=require('co-prompt')constJson2csvParser=require('json2csv').Parser//获取多个文件的方法constgetMultiEntry=function(globPath){letentries={}glob.sync(globPath).forEach(function(entry){constbasename=path.basename(entry,path.extname(entry))entries[basename]=entry})returnentries}module.exports=(paths)=>{co(function*(){let[inPath,outPath]=路径//处理用户输入inPath=inPath?inPath:yieldprompt('Inputfiledirectory:')outPath=outPath?outPath:(yieldprompt('Outputfiledirectory:'))||inPath//遍历得到json文件constfiles=getMultiEntry(`${inPath}/*.json`)//如果指定目录下没有json文件,输出提示信息并退出流程if(!Object.keys(files).length){console.log(chalk.red('\nx指定fo中没有json文件lder'))process.exit()}//开始转换文件console.log('\n')console.log(chalk.green('StartConversion:'))for(letfilenameinfiles){//同步读取文件letjsonData=fs.readFileSync(files[filename])jsonData=JSON.parse(jsonData)/**判断csv可接受的数据结构*如果是json对象,取key和value作为列*如果是是json数组,然后读取第一行的所有key**/letjData,fieldsif(Object.prototype.toString.call(jsonData)==='[objectObject]'){jData=Object.keys(jsonData).map(key=>({key:key,value:jsonData[key]}))fields=['key','value']}if(Object.prototype.toString.call(jsonData)==='[objectArray]'){jData=jsonDatafields=Object.keys(jsonData[0])}//json格式=>csv格式constjson2csvParser=newJson2csvParser({fields})constcsvData=json2csvParser.parse(jData)//OfficeExcel需要BOM头来定义UTF-8编码格式constBOM=Buffer.from('\uFEFF')constbomCsv=Buffer.concat([BOM,Buffer.from(csvData)])//要写入的文件名constoutputFileName=`${outPath}/${filename}.csv`//如果没有文件夹则创建if(!fs.existsSync(outPath)){fs.mkdirSync(outPath)}//写入文件consterr=fs.writeFileSync(outputFileName,bomCsv)if(err){returnconsole.log(err)}else{console.log(chalk.green(`-${filename}.json转换成功!`))}}//提示输出文件目录console.log('\n')console.log(chalk.blue(`-请去查看文件:${chalk.underline(path.join(process.cwd(),outPath))}`))process.exit()})}是使用命令,如何安装和使用命令?包.jsonbin命令实现。在项目根目录下创建一个bin目录,package.json定义一个bin命令。在bin/json2excel.js文件的开头写入#!/usr/bin/env。在安装node项目包的时候,npm会在/node_modules/.bin中安装一个bin命令,这样就可以使用json2excel命令了,执行json2excelstart*如果是全局安装,那么在任何地方都可以使用。至此,一个json转csv的工具就完美实现了。我们正在将json转成csv,如果得到csv如何恢复成json呢?修改命令json2excelstart[paths]:将jsontocsv的名称改为json2excelj2c[paths]增加命令json2excelc2j[paths]将csv转json和将csv转json的实现方式和之前类似,只是区别在格式转换方面(使用“csvtojson”工具),这里不再写。完整代码请查看https://github.com/zwzou/json2excel#readme。至此,一个完整的json-excel(csv)格式转换工具就完成了。期待在未来扩展其他Excel格式