python实现PDF/Word转换、PDF文件合并与拆分等功能,生成可执行文件

一、功能说明

1. PDF与Word格式互转

2.PDF文件合并与拆分

3.支持批量操作

二、开发环境

1.测试python版本:Python 3.8
2.PyInstaller生成可执行文件(EXE)

三、使用说明

功能1:PDF转Word:

  1. 点击"输入文件"旁的"浏览"按钮,选择要转换的PDF文件(可多选)
  2. 选择输出目录
  3. 点击"开始转换",转换后的Word文档将保存在输出目录

功能2:Word转PDF:

  1. 点击"输入文件"旁的"浏览"按钮,选择要转换的Word文档(可多选)
  2. 选择输出目录
  3. 点击"开始转换",转换后的PDF文件将保存在输出目录

功能3:合并PDF:

  1. 点击"输入文件"旁的"浏览"按钮,选择要合并的PDF文件(至少2个)
  2. 指定输出文件路径(需包含文件名)
  3. 点击"开始合并"

功能4:拆分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. 输出目录不要使用中文路径(推荐使用英文路径)

五、完整代码

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图标

打包完成后,可在 dist/ 目录找到生成的可执行文件。建议在 Windows 10/11 环境下打包以获得最佳兼容性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值