最近有一大批发票需要提交,但打印机只能一张 a4 纸打印一张发票,很费纸,并且大小不符合提交的需求,因此产生了将两张发票合并成一张的想法,以下是实现的代码
项目结构(data 和 target 是文件夹)
.
├── data
├── merge.py
└── target
实现需要使用到 pymupdf、fitz
import os, fitz
pdf_folder = os.getcwd() + "/data"
merged_pdf_folder = os.getcwd() + "/target"
# 获取 pdf 文件的名称
pdf_names = []
for file in os.scandir(pdf_folder):
if file.is_file() and file.name.endswith(".pdf"):
pdf_names.append(file.name)
# 生成 pdf 所需的参数
width, height = fitz.paper_size("a4")
a4_ratio = 210 / 297
r = fitz.Rect(0, 0, width, height)
rx = r * a4_ratio
r1 = fitz.Rect(0, 0, r.width, rx.width)
r2 = fitz.Rect(0, rx.width, r.width, r.height)
r_tab = [r1, r2]
# 获取所有 pdf 文件
src = fitz.open()
for name in pdf_names:
read_pdf = fitz.open(pdf_folder + '/' + name)
src.insert_pdf(read_pdf)
def merge_two_pdf(pdf_tuple: list, id: str):
if len(pdf_tuple) != 1 and len(pdf_tuple) != 2:
return
doc_manager = fitz.open()
page = doc_manager.new_page(-1, width = width, height = height)
for spage in pdf_tuple:
if spage.rect.width > spage.rect.height:
page.show_pdf_page(r_tab[spage.number % 2], src, spage.number, rotate = 0)
else:
page.show_pdf_page(r_tab[spage.number % 2], src, spage.number, rotate = 90)
doc_manager.save(merged_pdf_folder + '/' + id.replace('.pdf', '') + '.pdf', garbage = 4, deflate = True)
def merge_all_pdf():
if len(src) == 0:
return
doc_manager = fitz.open()
page = None
for spage in src:
if spage.number % 2 == 0:
page = doc_manager.new_page(-1, width = width, height = height)
if spage.rect.width > spage.rect.height:
page.show_pdf_page(r_tab[spage.number % 2], src, spage.number, rotate = 0)
else:
page.show_pdf_page(r_tab[spage.number % 2], src, spage.number, rotate = 90)
doc_manager.save(merged_pdf_folder + '/all.pdf', garbage = 4, deflate = True)
代码的功能是获取 data 文件夹里面的原始 pdf,合并后保存在 target 目录下。注意,上面的代码只适用于 mac,windows 文件路径的书写下可能会有所不同
由于公司的打印机无法设置单面打印,我就只能设置 2 张发票合并成一个只有一页的 pdf,即调用 merge_two_pdf
for i in range(0, len(src), 2):
try:
merge_two_pdf([src[i], src[i + 1]], pdf_names[i] + '_' + pdf_names[i + 1])
except IndexError:
print(i)
merge_two_pdf([src[i]], pdf_names[i])
如果你们公司打印机能设置单面打印的话,直接调用 merge_all_pdf 即可