基于Python實(shí)現(xiàn)PDF批量轉(zhuǎn)化工具
一、開(kāi)發(fā)的緣由
最近,有網(wǎng)友想讓我?guī)退鲆粋€(gè)批量把png, docx, doc, pptx, ppt, xls, xlsx文件轉(zhuǎn)化為PDF格式的軟件,完全傻瓜式的操作,把文件拖進(jìn)去就進(jìn)行轉(zhuǎn)化那種,簡(jiǎn)單實(shí)用。之前,有過(guò)一個(gè)vbs的文件,可以轉(zhuǎn)docx, xlsx, pptx,但是對(duì)于圖片無(wú)能為力,為了完成這個(gè)任務(wù)還是要請(qǐng)出Python這個(gè)強(qiáng)大的利器。
二、開(kāi)發(fā)的過(guò)程
1. 為了能夠?qū)崿F(xiàn)拖動(dòng)的功能,我首先想到要設(shè)計(jì)一個(gè)UI界面,然后可以直接接受拖動(dòng)的文件。另外,因?yàn)槭桥坎僮?,需要一定的時(shí)間來(lái)完成操作,最好是可以添加一個(gè)進(jìn)度條,讓用戶(hù)知道是否已經(jīng)完成了轉(zhuǎn)化。
2. 軟件的外觀本來(lái)想著簡(jiǎn)化,但是想著得讓用戶(hù)看到轉(zhuǎn)化文件名的路徑和文件名,避免轉(zhuǎn)錯(cuò)了,同時(shí)還得可以刪除選中的條目。所以我就設(shè)計(jì)了一個(gè)listbox控件,一個(gè)刪除按鈕、一個(gè)生成文件按鈕,還有一個(gè)導(dǎo)入文件的按鈕,為的是不習(xí)慣進(jìn)行拖動(dòng)的用戶(hù)設(shè)計(jì)。
3. 由于tkinter是系統(tǒng)自帶的,所以可以使軟件更小一點(diǎn)。另外,讀取圖片用到PIL這個(gè)模塊,而其它如docx, pptx, xlsx文件的轉(zhuǎn)化則需要依靠win32com.client這個(gè)模塊。
4. 我嘗試了多種方法來(lái)執(zhí)行拖動(dòng)的功能,但是打包以后發(fā)現(xiàn)無(wú)法實(shí)現(xiàn),于時(shí)最終采用了windnd這個(gè)模塊,為了防止拖動(dòng)時(shí)程序假死,我還用了多線程的方法。
三、成品介紹
我們這個(gè)軟件最終起名為PDF批量轉(zhuǎn)化器,它是一款支持多種文件格式批量轉(zhuǎn)換為PDF格式的工具,特別適用于Word、Excel、PowerPoint、圖片文件的轉(zhuǎn)換。它提供了一個(gè)直觀的界面,允許用戶(hù)通過(guò)拖拽文件或通過(guò)文件選擇器導(dǎo)入文件,支持多線程處理,提升了文件轉(zhuǎn)換的效率。主要特點(diǎn)有:
- 多文件格式支持:支持轉(zhuǎn)換Word、Excel、PowerPoint和圖片文件到PDF格式。
- 拖拽功能:用戶(hù)可以直接將文件拖拽至程序界面,簡(jiǎn)化操作流程。
- 進(jìn)度條顯示:轉(zhuǎn)換過(guò)程中,進(jìn)度條實(shí)時(shí)顯示,用戶(hù)可以了解轉(zhuǎn)換的進(jìn)度。
- 批量處理:一次可以處理多個(gè)文件,節(jié)省時(shí)間和操作精力。
- 文件管理:提供文件導(dǎo)入、刪除等操作,幫助用戶(hù)管理文件列表。
- 后臺(tái)處理:采用多線程方式處理文件轉(zhuǎn)換,避免界面卡頓。
此外,為了增強(qiáng)用戶(hù)體驗(yàn),我們還增加了二個(gè)小功能,一是把生成的PDF文件統(tǒng)一放在一個(gè)PDF文件夾里面,另外就是如果發(fā)現(xiàn)同名PDF文件,就自動(dòng)跳過(guò)這個(gè)文件,從而避免重復(fù)操作。
四、程序源碼
為了幫助大家,特地放上這個(gè)源碼,供大家調(diào)試使用,里面有豐富的知識(shí)點(diǎn),認(rèn)真學(xué)習(xí)或許還會(huì)有意想不到的收獲。
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批量轉(zhuǎn)化器 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 = "請(qǐng)把文件拖拽到本界面上,然后點(diǎn)生成文件", 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="導(dǎo)入文件",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", "請(qǐng)先選擇要?jiǎng)h除的文件!") 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() #---------------定義一個(gè)drop_files,然后用thread_it------------- def drop_files(self,files): self.thread_it(self.drop_files2,files) #--------------找開(kāi)文件對(duì)話(huà)框的代碼-------------- 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") # 檢查目標(biāo)文件是否已經(jīng)存在 if os.path.exists(pdf_path): print(f"文件 {pdf_path} 已經(jīng)存在,跳過(guò)轉(zhuǎn)換。") return False # 文件已經(jīng)存在,不進(jìn)行轉(zhuǎn)換 # 如果文件不存在,繼續(xù)轉(zhuǎn)換 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 # 重置進(jìn)度條 self.progress_bar['maximum'] = total_files # 設(shè)置進(jìn)度條最大值 self.progress_bar['value'] = 0 # 重置進(jìn)度條當(dāng)前值為0 self.label.config(text="正在處理中...") # 更新提示標(biāo)簽 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 # 更新處理結(jié)果 self.label.config(text=f"轉(zhuǎn)化{excel_count}個(gè)Excel,{word_count}個(gè)Word," f"{ppt_count}個(gè)PPT,{img_count}個(gè)圖 ") 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()
五、注意事項(xiàng)
1. 文件類(lèi)型限制:僅支持特定文件類(lèi)型的轉(zhuǎn)換,如:doc, docx, ppt, pptx, xls, xlsx和常見(jiàn)圖片格式png,jpg格式,其他文件類(lèi)型暫不適用。
2. 軟件依賴(lài):需要安裝pywin32和Pillow庫(kù),且轉(zhuǎn)換Word、Excel、PowerPoint等文件格式時(shí)依賴(lài)安裝Microsoft Office。
3. 路徑問(wèn)題:確保文件路徑不包含特殊字符,否則可能導(dǎo)致路徑無(wú)法識(shí)別。
4. 文件覆蓋:如果轉(zhuǎn)換后的PDF文件已存在,程序會(huì)跳過(guò)該文件以避免覆蓋。
以上就是基于Python實(shí)現(xiàn)PDF批量轉(zhuǎn)化工具的詳細(xì)內(nèi)容,更多關(guān)于Python PDF批量轉(zhuǎn)化的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
3種Python 實(shí)現(xiàn)酷炫進(jìn)度條的實(shí)用方法
這篇文章主要介紹了3種Python 實(shí)現(xiàn)酷炫進(jìn)度條的實(shí)用方法,文章圍繞Python的相關(guān)資料展開(kāi)對(duì)實(shí)現(xiàn)進(jìn)度條的介紹,需要的小伙伴可以參考一下2022-04-04python如何爬取網(wǎng)站數(shù)據(jù)并進(jìn)行數(shù)據(jù)可視化
這篇文章主要介紹了python爬取拉勾網(wǎng)數(shù)據(jù)并進(jìn)行數(shù)據(jù)可視化,爬取拉勾網(wǎng)關(guān)于python職位相關(guān)的數(shù)據(jù)信息,并將爬取的數(shù)據(jù)已csv各式存入文件,然后對(duì)csv文件相關(guān)字段的數(shù)據(jù)進(jìn)行清洗,并對(duì)數(shù)據(jù)可視化展示,包括柱狀圖展示、直方圖展示,需要的朋友可以參考下2019-07-07python初學(xué)之用戶(hù)登錄的實(shí)現(xiàn)過(guò)程(實(shí)例講解)
下面小編就為大家分享一篇python初學(xué)之用戶(hù)登錄的實(shí)現(xiàn)過(guò)程(實(shí)例講解),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12卷積神經(jīng)網(wǎng)絡(luò)經(jīng)典模型及其改進(jìn)點(diǎn)學(xué)習(xí)匯總
這篇文章主要為大家介紹了卷積神經(jīng)網(wǎng)絡(luò)經(jīng)典模型及其改進(jìn)點(diǎn)學(xué)習(xí)匯總,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05Python控制windows系統(tǒng)音量實(shí)現(xiàn)實(shí)例
這篇文章主要介紹了Python控制windows系統(tǒng)音量實(shí)現(xiàn)實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2023-01-01一文詳解如何實(shí)現(xiàn)PyTorch模型編譯
這篇文章主要為大家介紹了如何實(shí)現(xiàn)PyTorch?模型編譯詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04