公司手机话费报销需要每个人的电子发票作为报销依据,并且电子发票需要规范命名,包括帐期、手机号码、姓名等三个关健值。过完年回来发现电信的业务系统升级了,有点坑的是电子发票文件名的格式变了,上述关健值一个都没有。和电信的业务经理沟通无果,略微生气,想让我一个个手动命名,那是不可能的。于是开始入坑……
一开始想用C语言写,写完打包成exe可执行文件,便于后续使用。一番搜索之后发现,是我太天真了。C不行、Java不会,python又半吊子水那只能JS了。幸好,一番搜索之后发现了pdf2json这个npm包,并且能满足使用。
二、需求1.读取PDF内容
2.根据PDF中的帐期 、手机号码、姓名等关键字匹配出需要的值
3.构造新的符合规范的文件名
4.重命名PDF文件并生成账单
三、实现 1.安装依赖包需要node-xlsx、pdf2json两个npm包,安装指令:
npm i node-xlsx npm i pdf2json2.引入模块
需要下述三个:
const fs = require('fs')
const PDFParser = require('pdf2json')
const xlsx = require('node-xlsx')
3.完整示例
集成终端中执行js文件即会将目录下的PDF电子发票命名为“帐期_手机号码_姓名”格式,并且生成一份Excel表格,记录每个文件中的账期、手机号码、姓名、发票金额,形成账单。
虽然实现了功能满足了需求,但代码写得好烂,自己都不想看。
只适合PDF文件少的情况,多了估计会崩……
const fs = require('fs')
const PDFParser = require('pdf2json')
const xlsx = require('node-xlsx')
//对象存放电话名单
var number = {
13388886666:'张三',
16688886666:'李四',
……
}
//存放读取到PDF的数据:帐期、手机号码、发票金额
let tableObj = [
{
name:'Sheet1',
data:[]
}
]
//封装PDF文件读取并重命名函数,第一个参数是相对路径,第二个参数是相对路径+原文件名,第三个参数是备注
async function renamePDF(dir, oldPath, remark){
console.log("step 2")
var pdfParser = new PDFParser(this, 1) //注意:要在函数内定义,不然会报错aync问题
pdfParser.loadPDF(oldPath)
pdfParser.on("pdfParser_dataError", errData => console.log(errData.parserError))
pdfParser.on("pdfParser_dataReady", pdfData => {
console.log("step 3")
//读取PDF,转换成TXT文本内容
let dataTXT = pdfParser.getRawTextContent()
//正则:删除空白字符和.符号
let dataTXTs = dataTXT.replace(/(s|.)+/g,'')
//正则:匹配并返回号码、账期、发票金额
let dataTarget = dataTXTs.match(/(?<=(号码.|帐期.|¥))[0-9]*/g)
//构造新文件名,根据手机号码匹配姓名
console.log(dataTarget[4])
Object.keys(number).forEach((key)=>{
if (key == dataTarget[4]) {
let newPath = `${dir}/${dataTarget[3]}_${dataTarget[4]}_${number[key]}.pdf`
//fs内置模块重命名文件
fs.rename(oldPath, newPath, (error)=>{
if(error) throw error
console.log("step 4")
console.log('重命名成功')
})
}
})
//将结果写到xlsx表格中,注意这里会重复写需要优化
tableObj[0].data.push(dataTarget)
console.log("step 7")
console.log(tableObj)
let dataTargetBuffer = xlsx.build(tableObj)
fs.writeFileSync('./dataTarget.xlsx', dataTargetBuffer, 'binary')
})
}
//封装重命名文件函数
function renameTicket(dir, remark){
//读取dir目录下的所有PDF文件名
fs.readdir(dir, (error, content)=>{
content.forEach((value,index)=>{
oldPath = `${dir}/${value}`
console.log("step 1")
//异步调用PDF重命名函数,并发执行,注意并发数
renamePDF(dir, oldPath, remark)
})
console.log("step 5")
console.log("forEach Done.")
})
console.log("step 6")
console.log("readdir Done.")
}
//调用重名文件函数,第一个参数是相对路径,第二个是号码之后的内容
renameTicket('./filesPDF', '备注')
4.参考内容
(1)npm包pdf2json
(2)菜鸟教程-正则表达式语法



