当前位置: 代码网 > it编程>前端脚本>Python > 基于Python实现PDF批量转化工具

基于Python实现PDF批量转化工具

2024年12月10日 Python 我要评论
一、开发的缘由最近,有网友想让我帮他做一个批量把png, docx, doc, pptx, ppt, xls, xlsx文件转化为pdf格式的软件,完全傻瓜式的操作,把文件拖进去就进行转化那种,简单实

一、开发的缘由

最近,有网友想让我帮他做一个批量把png, docx, doc, pptx, ppt, xls, xlsx文件转化为pdf格式的软件,完全傻瓜式的操作,把文件拖进去就进行转化那种,简单实用。之前,有过一个vbs的文件,可以转docx, xlsx, pptx,但是对于图片无能为力,为了完成这个任务还是要请出python这个强大的利器。

二、开发的过程

1. 为了能够实现拖动的功能,我首先想到要设计一个ui界面,然后可以直接接受拖动的文件。另外,因为是批量操作,需要一定的时间来完成操作,最好是可以添加一个进度条,让用户知道是否已经完成了转化。

2. 软件的外观本来想着简化,但是想着得让用户看到转化文件名的路径和文件名,避免转错了,同时还得可以删除选中的条目。所以我就设计了一个listbox控件,一个删除按钮、一个生成文件按钮,还有一个导入文件的按钮,为的是不习惯进行拖动的用户设计。

3. 由于tkinter是系统自带的,所以可以使软件更小一点。另外,读取图片用到pil这个模块,而其它如docx, pptx, xlsx文件的转化则需要依靠win32com.client这个模块。

4. 我尝试了多种方法来执行拖动的功能,但是打包以后发现无法实现,于时最终采用了windnd这个模块,为了防止拖动时程序假死,我还用了多线程的方法。

三、成品介绍

我们这个软件最终起名为pdf批量转化器,它是一款支持多种文件格式批量转换为pdf格式的工具,特别适用于word、excel、powerpoint、图片文件的转换。它提供了一个直观的界面,允许用户通过拖拽文件或通过文件选择器导入文件,支持多线程处理,提升了文件转换的效率。主要特点有:

  • 多文件格式支持:支持转换word、excel、powerpoint和图片文件到pdf格式。
  • 拖拽功能:用户可以直接将文件拖拽至程序界面,简化操作流程。
  • 进度条显示:转换过程中,进度条实时显示,用户可以了解转换的进度。
  • 批量处理:一次可以处理多个文件,节省时间和操作精力。
  • 文件管理:提供文件导入、删除等操作,帮助用户管理文件列表。
  • 后台处理:采用多线程方式处理文件转换,避免界面卡顿。

此外,为了增强用户体验,我们还增加了二个小功能,一是把生成的pdf文件统一放在一个pdf文件夹里面,另外就是如果发现同名pdf文件,就自动跳过这个文件,从而避免重复操作。

四、程序源码

为了帮助大家,特地放上这个源码,供大家调试使用,里面有丰富的知识点,认真学习或许还会有意想不到的收获。

import tkinter as tk
from tkinter import messagebox,ttk,filedialog
from pil import image
import os
import windnd
from threading import thread
import win32com.client  # pywin32 for word, excel, ppt processing
class wordprocessorapp:
    def __init__(self, root):
        self.root = root
        self.root.title("pdf批量转化器 v1.2 gordon ")
        self.root.attributes("-topmost", true)
        windnd.hook_dropfiles(self.root,func=self.drop_files)
        self.file_list = []
        self.create_widgets()
        os.makedirs("pdf文件", exist_ok=true)
 
        self.path = "pdf文件"
 
    def create_widgets(self):
        self.frame = tk.frame()
        self.frame.pack()
 
        # 使用combobox代替checkbutton
        self.label = tk.label(self.frame, text = "请把文件拖拽到本界面上,然后点生成文件", font=("宋体", 11), width=38)
        self.label.pack(side=tk.left)
   
        self.file_listbox = tk.listbox(self.root,width=48,font = ("宋体",11))
        self.file_listbox.pack()
        
        self.import_button = tk.button(self.frame, text="导入文件",font = ("宋体",11), command=self.import_file)
        self.import_button.pack(sid=tk.left)
        
        frame1 = tk.frame()
        frame1.pack()
                # progress bar
        self.progress_bar = ttk.progressbar(frame1, orient="horizontal", length=400, mode="determinate")
        self.progress_bar.pack()
        
        self.delete_button = tk.button(frame1, text="删除选中", font=("宋体", 11), command=self.delete_selected)
        self.delete_button.pack(side=tk.left,padx = 30)
        
        self.generate_button = tk.button(frame1, text="生成文件",font = ("宋体",11), command=self.generate_files)
        self.generate_button.pack(side=tk.left,padx = 30)
        
        self.quit_button = tk.button(frame1, text="退出程序",font = ("宋体",11), command=self.ui_quit)
        self.quit_button.pack(side=tk.left,padx = 30)
    def ui_quit(self):
        self.root.destroy()
        
    def delete_selected(self):
        selected_indices = self.file_listbox.curselection()
        if not selected_indices:
            messagebox.showwarning("warning", "请先选择要删除的文件!")
            return
        for index in reversed(selected_indices):
            self.file_listbox.delete(index)
            del self.file_list[index]
    
    def thread_it(self,func,*args):
        self.thread1=thread(target=func,args=args)
        self.thread1.setdaemon(true) 
        self.thread1.start()
    #---------------定义一个drop_files,然后用thread_it-------------
    def drop_files(self,files):
        self.thread_it(self.drop_files2,files)
 
    #--------------找开文件对话框的代码--------------
    def drop_files2(self,files=none):
        for file_path in files:
            file_path=file_path.decode("gbk") 
            file_path = file_path.replace('\\', '/')
            if file_path not in self.file_listbox.get(0, tk.end):
                # 将文件路径添加到listbox中
                self.file_listbox.insert(tk.end, file_path)
                self.file_list.append(file_path)
        return
 
    def import_file(self):
        filename = filedialog.askopenfilename(filetypes=[("word files", "*.docx")])
        if filename:
            self.file_list.append(filename)
            self.file_listbox.insert(tk.end, filename)
 
    def generate_files(self):
        if not self.file_list:
            messagebox.showerror("error", "文件列表为空!")
            return
        
#         for filename in self.file_list:
        else:
            self.convert_files()
            
    def process_file(self, file_path, convert_func, update_progress):
        path_without_extension = os.path.splitext(os.path.basename(file_path))[0]
        pdf_path = os.path.join(os.path.abspath(self.path), path_without_extension + ".pdf")
        
        # 检查目标文件是否已经存在
        if os.path.exists(pdf_path):
            print(f"文件 {pdf_path} 已经存在,跳过转换。")
            return false  # 文件已经存在,不进行转换
        
        # 如果文件不存在,继续转换
        if convert_func(file_path, pdf_path, update_progress):
            return true
        return false
 
    def convert_files(self):
        files = self.file_listbox.get(0, tk.end)  # 获取列表框中的所有文件
        total_files = len(files)
        processed_files = 0
 
        # 重置进度条
        self.progress_bar['maximum'] = total_files  # 设置进度条最大值
        self.progress_bar['value'] = 0  # 重置进度条当前值为0
        self.label.config(text="正在处理中...")  # 更新提示标签
 
        def update_progress():
            nonlocal processed_files
            processed_files += 1
            self.progress_bar['value'] = processed_files
            self.root.update_idletasks()  # 更新ui
 
        # 处理文件
        excel_count = 0
        word_count = 0
        ppt_count = 0
        img_count = 0
 
        for file_path in files:
            if file_path.lower().endswith((".xls", ".xlsx")):  # excel file
                if self.process_file(file_path, self.excel_to_pdf, update_progress):
                    excel_count += 1
            elif file_path.lower().endswith((".docx", ".doc")):  # word file
                if self.process_file(file_path, self.word_to_pdf, update_progress):
                    word_count += 1
            elif file_path.lower().endswith((".pptx", ".ppt")):  # powerpoint file
                if self.process_file(file_path, self.ppt_to_pdf, update_progress):
                    ppt_count += 1
            elif file_path.lower().endswith((".jpg", ".png")):  # image file
                if self.process_file(file_path, self.img_to_pdf, update_progress):
                    img_count += 1
 
        # 更新处理结果
        self.label.config(text=f"转化{excel_count}个excel,{word_count}个word,"
                             f"{ppt_count}个ppt,{img_count}个图 ")
 
 
    def excel_to_pdf(self, input_file, output_file, update_progress):
        try:
            excel = win32com.client.dispatch("excel.application")
            excel.visible = false
            wb = excel.workbooks.open(input_file)
            wb.exportasfixedformat(0, output_file)
            wb.close()
            excel.quit()
            update_progress()  # update progress after conversion
            return true
        except exception as e:
            print(f"error converting excel to pdf: {e}")
            return false
 
    def word_to_pdf(self, input_file, output_file, update_progress):
        try:
            word = win32com.client.dispatch("word.application")
            doc = word.documents.open(input_file)
            doc.saveas(output_file, fileformat=17)  # fileformat=17 for pdf
            doc.close()
            word.quit()
            update_progress()  # update progress after conversion
            return true
        except exception as e:
            print(f"error converting word to pdf: {e}")
            return false
 
    def ppt_to_pdf(self, input_file, output_file, update_progress):
        try:
            ppt = win32com.client.dispatch("powerpoint.application")
            ppt.visible = false
            presentation = ppt.presentations.open(input_file)
            presentation.saveas(output_file, 32)  # 32 for pdf format
            presentation.close()
            ppt.quit()
            update_progress()  # update progress after conversion
            return true
        except exception as e:
            print(f"error converting powerpoint to pdf: {e}")
            return false
 
    def img_to_pdf(self, input_file, output_file, update_progress):
        try:
            img = image.open(input_file)
            img.save(output_file, "pdf", resolution=100.0)
            update_progress()  # update progress after conversion
            return true
        except exception as e:
            print(f"error converting image to pdf: {e}")
            return false
 
if __name__ == "__main__":
    root = tk.tk()
    app = wordprocessorapp(root)
    root.mainloop()

五、注意事项

1. 文件类型限制:仅支持特定文件类型的转换,如:doc, docx, ppt, pptx, xls, xlsx和常见图片格式png,jpg格式,其他文件类型暂不适用。

2. 软件依赖:需要安装pywin32和pillow库,且转换word、excel、powerpoint等文件格式时依赖安装microsoft office。

3. 路径问题:确保文件路径不包含特殊字符,否则可能导致路径无法识别。

4. 文件覆盖:如果转换后的pdf文件已存在,程序会跳过该文件以避免覆盖。

以上就是基于python实现pdf批量转化工具的详细内容,更多关于python pdf批量转化的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com