python实现PDF/Word转换、PDF文件合并与拆分等功能,生成可执行文件(EXE)
一、功能说明
1. PDF与Word格式互转
2.PDF文件合并与拆分
3.支持批量操作
二、开发环境
1.测试python版本:Python 3.8
2.PyInstaller生成可执行文件(EXE)
三、使用说明
功能1:PDF转Word:
- 点击"输入文件"旁的"浏览"按钮,选择要转换的PDF文件(可多选)
- 选择输出目录
- 点击"开始转换",转换后的Word文档将保存在输出目录
功能2:Word转PDF:
- 点击"输入文件"旁的"浏览"按钮,选择要转换的Word文档(可多选)
- 选择输出目录
- 点击"开始转换",转换后的PDF文件将保存在输出目录
功能3:合并PDF:
- 点击"输入文件"旁的"浏览"按钮,选择要合并的PDF文件(至少2个)
- 指定输出文件路径(需包含文件名)
- 点击"开始合并"
功能4:拆分PDF:
- 选择要拆分的PDF文件
- 指定输出目录
- 输入页码范围(示例格式):
- 1-3 → 拆分1到3页
- 5 → 拆分第5页
- 1-3,5,7-9 → 拆分多个范围
- 点击"开始拆分"
四、注意事项
- Word转PDF需要电脑安装Microsoft Office或者WPS软件
- 页码从1开始计数
- 处理大文件时请耐心等待
- 输出目录不要使用中文路径(推荐使用英文路径)
五、完整代码
import os
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
from PyPDF2 import PdfMerger, PdfReader, PdfWriter
from pdf2docx import Converter
import pythoncom
import win32com.client as win32
# PDF转Word功能
def pdf_to_word():
input_files = input_pdf_to_word_var.get().split(';')
output_dir = output_pdf_to_word_var.get()
if not input_files or not output_dir:
messagebox.showwarning("温馨提示", "请选择输入文件和输出目录")
"""如果其中任何一个为空,条件为真,执行后续的代码"""
return
try:
os.makedirs(output_dir, exist_ok=True)
"""确保某个目录存在时,可以使用 os.makedirs() 来创建它,而不必担心目录是否已经存在"""
for pdf_path in input_files:# 遍历输入目录中的所有PDF文件
if not os.path.isfile(pdf_path):
"""如果 pdf_path 不是一个文件(例如它是一个目录或不存在),则条件为 True,否则为 False"""
raise FileNotFoundError(f"文件不存在: {pdf_path}")
docx_name = os.path.splitext(os.path.basename(pdf_path))[0] + ".docx"
docx_path = os.path.join(output_dir, docx_name)
# 转换PDF文件,创建 Converter 对象,传入 PDF 文件路径
cv = Converter(pdf_path)
# 调用 convert 方法,将 PDF 转换为 Word 文档
cv.convert(docx_path)
# 关闭转换器
cv.close()
messagebox.showinfo("完成", "PDF转Word完成!")
except Exception as e:
messagebox.showerror("错误", str(e))
# Word转PDF功能
def word_to_pdf():
input_files = input_word_to_pdf_var.get().split(';')
output_dir = output_word_to_pdf_var.get()
if not input_files or not output_dir:
messagebox.showwarning("温馨提示", "请选择输入文件和输出目录")
return
try:
os.makedirs(output_dir, exist_ok=True)
pythoncom.CoInitialize() # 初始化 COM 库
def get_word_app():
# 按优先级尝试创建 Word 应用程序对象
prog_ids = [
"Kwps.Application", # WPS 专业版
"Word.Application", # Microsoft Office
"Wps.Application", # WPS 教育版/个人版
"ET.Application", # 兼容 WPS 表格的备用方案
]
for prog_id in prog_ids:
try:
app = win32.gencache.EnsureDispatch(prog_id)
app.Visible = False # 测试可用性
print(f"成功连接: {prog_id}")
return app
except Exception as e:
print(f"连接 {prog_id} 失败: {str(e)}")
continue
raise Exception("未找到可用的 Word/WPS 应用程序")
word=get_word_app()
for docx_path in input_files:
if not os.path.isfile(docx_path):
raise FileNotFoundError(f"文件不存在: {docx_path}")
pdf_name = os.path.splitext(os.path.basename(docx_path))[0] + ".pdf"
pdf_path = os.path.join(output_dir, pdf_name)
doc = word.Documents.Open(docx_path)
doc.SaveAs(pdf_path, FileFormat=17)#17 对应于 PDF 格式。
doc.Close()
messagebox.showinfo("完成", "Word转PDF完成!")
except Exception as e:
messagebox.showerror("错误", str(e))
finally:
word.Quit()
pythoncom.CoUninitialize() # 释放资源
# 合并PDF功能
def merge_pdf():
input_files = input_merge_var.get().split(';')
output_path = output_merge_var.get()
if len(input_files) < 2:
messagebox.showwarning("温馨提示", "请选择至少2个PDF文件")
return
if not output_path:
messagebox.showwarning("温馨提示", "请选择输出文件路径")
return
try:
merger = PdfMerger()
for pdf_path in input_files:
if not os.path.isfile(pdf_path):
raise FileNotFoundError(f"文件不存在: {pdf_path}")
merger.append(pdf_path)
merger.write(output_path)
merger.close()
messagebox.showinfo("完成", "PDF合并完成!")
except Exception as e:
messagebox.showerror("错误", str(e))
"""解析页码范围字符串,返回页码范围列表"""
def parse_page_ranges(s):
sections = []
parts = s.replace(',', ',').split(',')
"""将字符串 s 中的中文逗号 ',' 替换为英文逗号 ',',然后根据英文逗号 ','将字符串分割成一个列表 parts """
for part in parts:
part = part.strip()
"""遍历 parts 列表中的每一个元素,去除每个字符串开头和结尾的空白字符(包括空格、制表符和换行符等)"""
if not part: #检查 part 是否为 False 或空值
continue
if '-' in part:
try:
start, end = map(int, part.split('-', 1))
if start < 1 or end < start:
raise ValueError
sections.append((start, end))
except:
raise ValueError(f"无效的页码范围: {part}")
else:
try:
page = int(part)
if page < 1:
raise ValueError
sections.append((page, page))#将一个元组 (page, page) 添加到列表 sections 的末尾
except:
raise ValueError(f"无效的页码: {part}")
return sections
# 拆分PDF功能
def split_pdf():
input_path = input_split_var.get()
output_dir = output_split_var.get()
page_ranges = page_range_var.get()
if not input_path or not output_dir or not page_ranges:
messagebox.showwarning("温馨提示", "请填写所有必填项")
return
try:
sections = parse_page_ranges(page_ranges)
except ValueError as e:
messagebox.showwarning("温馨提示","""输入页码范围(示例格式):
- 1-3 → 拆分1到3页
- 5 → 拆分第5页
- 1-3,5,7-9 → 拆分多个范围""")
return
try:
reader = PdfReader(input_path)
total_pages = len(reader.pages)
base_name = os.path.splitext(os.path.basename(input_path))[0]
os.makedirs(output_dir, exist_ok=True)
for i, (start, end) in enumerate(sections):
if start > total_pages or end > total_pages:
raise ValueError(f"页码范围{start}-{end}超出总页数({total_pages})")
writer = PdfWriter()
for page_num in range(start - 1, end):
writer.add_page(reader.pages[page_num])
output_path = os.path.join(
output_dir,
f"{base_name}_part_{i + 1}_p{start}-{end}.pdf"
)
with open(output_path, "wb") as f:
writer.write(f)
messagebox.showinfo("完成", f"成功拆分为{len(sections)}个文件!")
except Exception as e:
messagebox.showerror("错误", str(e))
# 界面布局
root = tk.Tk()
root.title("PDF/Word 转换工具V1.0")
root.geometry("400x620")
style = ttk.Style()
style.configure("TLabel", padding=5)
style.configure("TButton", padding=5)
style.configure("TEntry", padding=5)
# 创建StringVar变量
input_pdf_to_word_var = tk.StringVar()
output_pdf_to_word_var = tk.StringVar()
input_word_to_pdf_var = tk.StringVar()
output_word_to_pdf_var = tk.StringVar()
input_merge_var = tk.StringVar()
output_merge_var = tk.StringVar()
input_split_var = tk.StringVar()
output_split_var = tk.StringVar()
page_range_var = tk.StringVar()
# PDF转Word区域
frame_pdf2word = ttk.LabelFrame(root, text="PDF转Word")
frame_pdf2word.pack(fill="x", padx=10, pady=5)
ttk.Label(frame_pdf2word, text="输入文件:").grid(row=0, column=0, sticky="e")
ttk.Entry(frame_pdf2word, textvariable=input_pdf_to_word_var, width=50).grid(row=0, column=1)
ttk.Button(frame_pdf2word, text="浏览", command=lambda: input_pdf_to_word_var.set(';'.join(
filedialog.askopenfilenames(filetypes=[("PDF文件", "*.pdf")])))).grid(row=0, column=2)
ttk.Label(frame_pdf2word, text="输出目录:").grid(row=1, column=0, sticky="e")
ttk.Entry(frame_pdf2word, textvariable=output_pdf_to_word_var, width=50).grid(row=1, column=1)
ttk.Button(frame_pdf2word, text="浏览", command=lambda: output_pdf_to_word_var.set(
filedialog.askdirectory())).grid(row=1, column=2)
ttk.Button(frame_pdf2word, text="开始转换", command=pdf_to_word).grid(row=2, column=1, pady=5)
# Word转PDF区域
frame_word2pdf = ttk.LabelFrame(root, text="Word转PDF")
frame_word2pdf.pack(fill="x", padx=10, pady=5)
ttk.Label(frame_word2pdf, text="输入文件:").grid(row=0, column=0, sticky="e")
ttk.Entry(frame_word2pdf, textvariable=input_word_to_pdf_var, width=50).grid(row=0, column=1)
ttk.Button(frame_word2pdf, text="浏览", command=lambda: input_word_to_pdf_var.set(';'.join(
filedialog.askopenfilenames(filetypes=[("Word文件", "*.docx")])))).grid(row=0, column=2)
ttk.Label(frame_word2pdf, text="输出目录:").grid(row=1, column=0, sticky="e")
ttk.Entry(frame_word2pdf, textvariable=output_word_to_pdf_var, width=50).grid(row=1, column=1)
ttk.Button(frame_word2pdf, text="浏览", command=lambda: output_word_to_pdf_var.set(
filedialog.askdirectory())).grid(row=1, column=2)
ttk.Button(frame_word2pdf, text="开始转换", command=word_to_pdf).grid(row=2, column=1, pady=5)
# 合并PDF区域
frame_merge = ttk.LabelFrame(root, text="合并PDF")
frame_merge.pack(fill="x", padx=10, pady=5)
ttk.Label(frame_merge, text="输入文件:").grid(row=0, column=0, sticky="e")
ttk.Entry(frame_merge, textvariable=input_merge_var, width=50).grid(row=0, column=1)
ttk.Button(frame_merge, text="浏览", command=lambda: input_merge_var.set(';'.join(
filedialog.askopenfilenames(filetypes=[("PDF文件", "*.pdf")])))).grid(row=0, column=2)
ttk.Label(frame_merge, text="输出文件:").grid(row=1, column=0, sticky="e")
ttk.Entry(frame_merge, textvariable=output_merge_var, width=50).grid(row=1, column=1)
ttk.Button(frame_merge, text="浏览", command=lambda: output_merge_var.set(
filedialog.asksaveasfilename(defaultextension=".pdf", filetypes=[("PDF文件", "*.pdf")]))).grid(row=1, column=2)
ttk.Button(frame_merge, text="开始合并", command=merge_pdf).grid(row=2, column=1, pady=5)
# 拆分PDF区域
frame_split = ttk.LabelFrame(root, text="拆分PDF")
frame_split.pack(fill="x", padx=10, pady=5)
ttk.Label(frame_split, text="输入文件:").grid(row=0, column=0, sticky="e")
ttk.Entry(frame_split, textvariable=input_split_var, width=50).grid(row=0, column=1)
ttk.Button(frame_split, text="浏览", command=lambda: input_split_var.set(
filedialog.askopenfilename(filetypes=[("PDF文件", "*.pdf")]))).grid(row=0, column=2)
ttk.Label(frame_split, text="输出目录:").grid(row=1, column=0, sticky="e")
ttk.Entry(frame_split, textvariable=output_split_var, width=50).grid(row=1, column=1)
ttk.Button(frame_split, text="浏览", command=lambda: output_split_var.set(
filedialog.askdirectory())).grid(row=1, column=2)
ttk.Label(frame_split, text="页码范围:").grid(row=2, column=0, sticky="e")
ttk.Entry(frame_split, textvariable=page_range_var, width=50).grid(row=2, column=1)
ttk.Button(frame_split, text="开始拆分", command=split_pdf).grid(row=3, column=1, pady=5)
# 配置网格权重
for frame in [frame_pdf2word, frame_word2pdf, frame_merge, frame_split]:
frame.columnconfigure(1, weight=1)
def show_instructions():
instructions = """【使用说明】
一、PDF转Word:
1. 点击"输入文件"旁的"浏览"按钮,选择要转换的PDF文件(可多选)
2. 选择输出目录
3. 点击"开始转换",转换后的Word文档将保存在输出目录
二、Word转PDF:
1. 点击"输入文件"旁的"浏览"按钮,选择要转换的Word文档(可多选)
2. 选择输出目录
3. 点击"开始转换",转换后的PDF文件将保存在输出目录
三、合并PDF:
1. 点击"输入文件"旁的"浏览"按钮,选择要合并的PDF文件(至少2个)
2. 指定输出文件路径(需包含文件名)
3. 点击"开始合并"
四、拆分PDF:
1. 选择要拆分的PDF文件
2. 指定输出目录
3. 输入页码范围(示例格式):
- 1-3 → 拆分1到3页
- 5 → 拆分第5页
- 1-3,5,7-9 → 拆分多个范围
4. 点击"开始拆分"
【注意事项】
1. Word转PDF需要电脑安装Microsoft Office或者WPS软件
2. 页码从1开始计数
3. 处理大文件时请耐心等待
4. 输出目录不要使用中文路径(推荐使用英文路径)
"""
win = tk.Toplevel()
win.title("使用说明")
win.geometry("450x600")
text = tk.Text(win, wrap="word", font=("微软雅黑", 10), padx=10, pady=10)
text.pack(fill="both", expand=True)
text.insert("end", instructions)
text.configure(state="disabled")
btn = ttk.Button(win, text="关闭", command=win.destroy)
btn.pack(pady=10)
def show_about():
about_info = """
PDF/Word转换工具
功能说明:
- PDF与Word格式互转
- PDF文件合并与拆分
- 支持批量操作
开发环境:
- 测试环境 Python 3.8
- 打包工具 PyInstaller
作者:python_geek
最后更新:2025-03-02
"""
messagebox.showinfo("关于本程序", about_info)
# 创建菜单栏
menubar = tk.Menu(root)
help_menu = tk.Menu(menubar, tearoff=0)
help_menu.add_command(label="使用说明", command=show_instructions)
help_menu.add_separator()
help_menu.add_command(label="关于", command=show_about)
menubar.add_cascade(label="帮助", menu=help_menu)
root.config(menu=menubar)
root.mainloop()
要将你的Python程序生成可执行文件(EXE),推荐使用 PyInstaller。以下是详细操作步骤:
打包前建议
1.确保已安装所有依赖:
pip install pyinstaller PyPDF2 pdf2docx pywin32 pythoncom
2.推荐在虚拟环境中打包:
使用 PyInstaller(命令行)生成 EXE 文件
pyinstaller --onefile --noconsole --hidden-import win32com --hidden-import pythoncom --icon=你的图标.ico 你的脚本.py
- –onefile:打包为单个EXE文件
- –noconsole:运行时不显示控制台窗口(适合GUI程序)
- –hidden-import:显式声明隐藏依赖
- –icon=xxx.ico:可选,设置EXE图标