在公司报销的时候虽然已经有了电子发票,但是贴票还是需要将发票打印出来贴上,如果只有一两张也就算了,如果几十张.. 呵呵,光胶水我都不够用的,找了好多工具、在线版本都不合心意,烦死,自己做个自己喜欢的吧。
二次更新 : 发票PDF在线合并来啦
查了下lib库,看了下API 开干。
准备
- nodejs 环境
- pdf-lib module
- N张发票PDF文件
文档准备
本来想着,将pdf读成图片然后缩放在一个PDF中,结果发现pdf-lib
直接就可以将pdf进行缩放,到时省事了。
pdf-lib github地址: https://github.com/Hopding/pdf-lib
代码
这里用到的API很少,主要有以下几个:
embedPdf : 嵌入PDF文档
scale : 将PDF进行缩放
addPage : 添加一个新的pdf页面
drawPage : 将PDF写入新pdf页面
完整代码:
/**
* 年底,将12个月份的发票合并在一个pdf中。
* ps.在线的各种不中意,线下的各种收费加水印。
* npm i pdf-lib
*/
const pdfLib = require('pdf-lib')
const PDFDocument = pdfLib.PDFDocument
// import { PDFDocument } from 'pdf-lib'
const fs = require('fs')
const path = require('path')
//这里需要修改为自己的路径
const folderPath = `I:\\huafei\\huafei\\2020pdf`
; (async function () {
// Create a new PDFDocument
const pdfDoc = await PDFDocument.create()
// Add a blank page to the document
let page = pdfDoc.addPage()
let lineNum = 1 //每行几张发票
let fileList = fs.readdirSync(folderPath)
let i = 0
fileList.sort((a, b) => {
let aa = path.basename(a)
let bb = path.basename(b)
return aa - bb
})
for (let file of fileList) {
let filePath = path.join(folderPath, file)
let fileStream = fs.readFileSync(filePath)
const [americanFlag] = await pdfDoc.embedPdf(fileStream)
const dims = americanFlag.scale(1 / lineNum)
// Draw the JPG image in the center of the page
let opts = {
...dims,
x: (i % lineNum) * (dims.width - 20) - 5,
y:
page.getHeight() -
Math.floor(i / lineNum) * (dims.height + 5) -
dims.height,
}
//如果当前高度不足,则创建新页面
console.log(opts)
if (opts.y < 0) {
//换页面
page = pdfDoc.addPage()
i = 0
opts = {
...dims,
x: (i % lineNum) * (dims.width - 20) - 5,
y:
page.getHeight() -
Math.floor(i / lineNum) * (dims.height + 5) -
dims.height,
}
}
page.drawPage(americanFlag, opts)
i++
}
// Serialize the PDFDocument to bytes (a Uint8Array)
const pdfBytes = await pdfDoc.save()
fs.writeFileSync(path.join(folderPath, 'total.pdf'), pdfBytes)
})()
以上,核心代码在github都有,直接拿过来稍微改动即可。
接下来,准备将这个小工具做成web服务,扔到我的小工具中...