用python按顺序批量打印PDF文件

问题描述

最近遇到一个需求,帮财务打印报销单。大致工作内容是把财务那边的报销单拿过来,在平台上把报销单的pdf下载下来,然后打印出来再装订到对应的报销文件上。

问题出在打印和最后的匹配上,非常的花时间。因为打印出来的文件是无序的,即使你已经在文件夹里对PDF按时间排序了,打印出来的最终顺序也取决于发送到打印机的快慢。

在windows下最多选择15个一起打印
就算一个一个文件选择,手动去右键打印,出来的顺序也很可能不是你想要的顺序。

如果打印可以按顺序,那我最终的工作就会很节省时间,所以想要解决的问题是:

如何让打印机根据顺序一个个的打印所选文件

win32包执行打印任务

首先,要用python模拟打印工作,这里我们用到win32print,**它来自pypiwin32这个包,我们通过以下语句安装

pip install pypiwin32

以下是进行一个打印任务的简单示例

    # 获取默认打印机名称,例如"3009"
    print_name = win32print.GetDefaultPrinter()
    # 获取打印机的句柄,或者说进程
    handle = win32print.OpenPrinter(print_name)
    # 获取打印机当前状态
    status = win32print.GetPrinter(handle, 2)['Status']
    print("当前状态", status)
    # 获取当前打印机任务
    tasks = win32print.EnumJobs(handle, 0, -1, 1)
    # 执行打印,注意第三个参数是字符串,如果是完整文件路径请转换成字符串
    win32api.ShellExecute(0, "print", "FT_CN000445148884.pdf", '/d:"%s"' % print_name, ".", 0)

选择文件夹,读取所有pdf文件

这里用到了tk库来实现文件夹选择,用os自带的方法应该也可以

def get_files():
    # 创建并隐藏TK窗口
    root = Tk()
    root.withdraw()
    root.attributes('-topmost', True)
    folder = askdirectory(title="请选择PDF文件所在的文件夹")
    print("所选路径是:", folder)
    source_src = Path(folder)
    files = source_src.glob("*.pdf")
    return files

运行效果如下:
在这里插入图片描述

读取文件后进行打印

核心程序如下,获取到文件列表后,循环调用以下程序即可:

def print_file(self, file):
        file = str(file)
        win32api.ShellExecute(0, "print", file, '/d:"%s"' % self.print_name, ".", 0)
        time.sleep(2)
        tasks = win32print.EnumJobs(self.handle, 0, -1, 1)
        if tasks:
            print("打印阻塞,请稍等")
        while tasks:
            time.sleep(1)
            tasks = win32print.EnumJobs(self.handle, 0, -1, 1)

完整程序如下:

from PDF_kayotin_main import get_files
import win32print
import win32api
import time

class PrintPDF:
    def __init__(self, desc=False):
        self.files = get_files()
        self.print_name = win32print.GetDefaultPrinter()
        self.handle = win32print.OpenPrinter(self.print_name)
        if self.print_name == "":
            print("请设置默认打印机")
            return

        self.sort_file_by_time(desc)
        print(f"打印完毕,本次共打印{len(self.files)}个文件")

    def sort_file_by_time(self, desc):
        file_dict = dict()
        for file in self.files:
            file_dict[file] = file.stat().st_mtime
        res = sorted(file_dict.keys(), key=file_dict.get, reverse=desc)
        print("开始打印------")
        for r in res:
            print("正在打印:", r)
            self.print_file(r)

    def print_file(self, file):
        file = str(file)
        win32api.ShellExecute(0, "print", file, '/d:"%s"' % self.print_name, ".", 0)
        time.sleep(2)
        tasks = win32print.EnumJobs(self.handle, 0, -1, 1)
        if tasks:
            print("打印阻塞,请稍等")
        while tasks:
            time.sleep(1)
            tasks = win32print.EnumJobs(self.handle, 0, -1, 1)

if __name__ == '__main__':
    my_pdf_printer = PrintPDF()

get_files方法请见上文

运行效果如下:

在这里插入图片描述

另一种方法:合并PDF

事实上还有另外一种简单粗暴的方法,就是把多个PDF合并成一个,这样打印的时候,必然就是按顺序的了。

PDF页数确认

我这里的打印机设置的是双面打印,所以单数页的pdf文件,需要check一下,给它加一页空白页,函数如下所示

def check_files(self, size=2):
        """检查文件,如果是奇数页,就补足一页空白页"""
        for file in self.files:
            reader = PyPDF2.PdfReader(file)
            if len(reader.pages) % size:
                writer = PyPDF2.PdfWriter()
                for page in reader.pages:
                    writer.add_page(page)
                writer.add_blank_page()
                with open(file, mode='wb') as new_file:
                    writer.write(new_file)

合并

合并没啥好说的,用了PyPDF2来进行合并

def merger_files(self):
        """合并到一个pdf中"""
        file_join = PyPDF2.PdfMerger()
        for file in self.files:
            file_join.append(file)
            self.counts += 1
        file_join.write("已合并.pdf")
        print("pdf文件合并已完成---")
        print(f"本次共合并{self.counts}个pdf文件^ ^")

参考链接

https://blog.csdn.net/zimkeavin/article/details/125872023

完整代码:https://github.com/h-kayotin/PDF_kayotin/tree/master/auto_print

使用Python批量修改PDF文件中的姓名需要借助一些库。以下是参考代码: 1. 首先,我们需要安装`openpyxl`和`PyPDF2`库,以便操作Excel和PDF文件。 ``` pip install openpyxl PyPDF2 ``` 2. 创建一个Excel文件,将需要修改的姓名按照要求填入。Excel文件的第一列应命名为“姓名”,并将要修改的姓名按顺序写在第一列中。 3. 然后,创建一个Python脚本来操作Excel和PDF文件: ```python import openpyxl from PyPDF2 import PdfFileWriter, PdfFileReader # 打开Excel文件,并获取工作簿 workbook = openpyxl.load_workbook('name_list.xlsx') sheet = workbook.active # 遍历Excel中的姓名列,并获取姓名 names = [] for cell in sheet['A'][1:]: names.append(cell.value) # 打开PDF文件,并进行批量修改 with open('original.pdf', 'rb') as file: pdf = PdfFileReader(file) # 创建一个新的PDF写入器 output = PdfFileWriter() # 遍历所有的页数,并进行姓名修改 for i in range(pdf.numPages): page = pdf.getPage(i) # 修改页面中的文本 for j in range(page.getNumAnnots()): # 获取注释内容 content = page.getAnnot(j).getContents() # 遍历Excel中的姓名,如果PDF中的文本与姓名匹配,则进行修改 for name in names: if name in content: modified_content = content.replace(name, '新姓名') page.getAnnot(j).update({ PdfString('/Contents'): Modified_name.encode('latin-1'), }) # 将页面添加到新的PDF写入器中 output.addPage(page) # 输出新的PDF文件 with open('modified.pdf', 'wb') as modified_file: output.write(modified_file) ``` 4. 在代码中的`'name_list.xlsx'`处填入Excel文件的路径,`'original.pdf'`处填入需要修改的PDF文件的路径。 5. 在代码的`modified_content = content.replace(name, '新姓名')`处,将`'新姓名'`修改为你想要的新的姓名。 6. 运行脚本后,将会生成一个新的PDF文件,其中的姓名已经被批量修改为新的姓名。 以上就是使用Python批量修改Excel中的姓名并应用于PDF文件的方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值