善用程序员的长处,解决工作中的一些小问题,最近财会部门报销规则改变,提交电子发票时需要将发票的名字按照规则改写,规则如下:
发票代码-发票号码-发票金额-报销人姓名.pdf。
我们来看下发票:
看图中用蓝框全选的部分是需要提取的信息,读取pdf文件,并提取信息,看着有点眼熟啊,我们在做软件开发时时常读取excel、word文件的内容,pdf能不能读取呢?当然是可以的,我为什么会想到用程序来解决呢?因为我积攒了好多发票,有话费、打车、地铁充值、京东购买的电子产品等等,中国五六十张发票,这些发票我要是一张张修改文件名称,估计得疯掉。
于是我就想,能不能开发个小工具呢?当然可以,但是用什么开发呢,js python bash,最后选定了用js来开发,因为笔者最熟悉js,然后就去npm去查找有没有能读取pdf的npm包,果然找到了,pdf2json,演示代码如下:
let fs = require('fs'),
PDFParser = require("pdf2json");
let pdfParser = new PDFParser();
pdfParser.on("pdfParser_dataError", errData => console.error(errData.parserError) );
pdfParser.on("pdfParser_dataReady", pdfData => {
let data = pdfParser.getRawTextContent();
console.log(data);
});
pdfParser.loadPDF("./pdf2json/test/pdf/fd/form/F1040EZ.pdf");
上面的代码就可以独处pdf中的信息了,读出的信息有一定规律,但是规律不是很有规范,需要在代码中处理一下,我将处理pdf的功能封装成了一个函数,并导出,代码如下:
const PDFParser = require('pdf2json');
const fs = require('fs');
const path = require('path');
function checkRate(input) {
var re = /^[0-9]+.?[0-9]*/;//判断字符串是否为数字//判断正整数/[1−9]+[0−9]∗]∗/
if (!re.test(input)) {
return false
}
return true
}
let n=0;
async function dealPDF(p){
console.log("p:",p)
console.log(++n)
var pdfParser = new PDFParser(this, 1);
pdfParser.loadPDF(p);
let result = await new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve()
},2000)
pdfParser.on('pdfParser_dataError', errData => reject(new Error(errData.parserError)));
pdfParser.on('pdfParser_dataReady', () => {
let data = pdfParser.getRawTextContent();
console.log(data);
let arr = data.split(/\r\n/)
let brage = 0
let brage1 = '';
let code ='';
let num = ''
for (let i = 0; i < arr.length; i++) {
if (checkRate(arr[i])) {
brage = i;
break;
}
}
code = arr[brage];
num = arr[brage + 1];
console.log(arr[brage])
console.log(arr[brage + 1])
let reg = /^[¥][0-9]+[.]?[0-9]+[\u4e00-\u9fa5]+$/
let reg2 = /\d+(\.\d+)?/ig
for (let j = 0; j < arr.length; j++) {
if (reg.test(arr[j])) {
brage1 = arr[j];
break;
}
}
let money = brage1.match(reg2)[0];
console.log(money)
fs.copyFileSync(p, `./pdf2/${code}-${num}-${money}-陈黎明.pdf`);
fs.unlinkSync(p);
resolve()
});
})
return result;
}
module.exports = dealPDF;
上面代码做了如下几件事:
1、接收路径参数,根据路径读取对应的pdf文件,将内容按照换行切分数组,
2、根据输出的规律找到数组中第一个数字,此处就是发票代码,紧挨着的是发票号码,将二者摘出来。
3、接着用正则将金额匹配出来。
4、将处理完的文件拷贝到其它文件目录,删除原件。
然后看入口文件:
const fs = require('fs');
const path = require('path');
const arr = fs.readdirSync('./pdf');
const dealPDF = require('./utils');
var exec = require('child_process').exec;
var cmdStr = `rm -rf ${path.join(__dirname,'pdf2')}`;
(async()=>{
await new Promise((resolve,reject)=>{
exec(cmdStr, function (err, stdout, srderr) {
if (err) {
console.log(srderr);
resolve()
} else {
console.log(stdout);
resolve()
}
})
})
fs.mkdirSync('pdf2')
let newarr = arr.slice(1,arr.length)
console.log(newarr);
for (let i = 0; i < newarr.length; i++) {
let p = path.join(__dirname, 'pdf', newarr[i])
await dealPDF(p)
}
})()
入口文件就很简单了,首先删除pdf2目录,之后建立一个新的pdf2目录,之后循环遍历所有待处理的pdf文件,最后得到结果全部在pdf文件目录中。
这样就完成了,但是这个工具只能我自己来用,我想让其他人来使用,该如何使用呢?
我的想法是将这个工具成一个全局命令行工具,就是是全局npm包,类似wepack、nvm的工具包。
这就涉及到了如何发布一个全局npm包,这里涉及两个知识:
1、如何发布npm包。
2、如何开发全局npm包。
我们下篇文章再见。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。