乐于分享
好东西不私藏

分享一个word文档专业排版工具,附源码

分享一个word文档专业排版工具,附源码

正 文 开 始

相逢即是缘,关注⭐星标不错过~,每天分享实操教程和技巧。


📄 完整代码 (含自定义字体与WPS适配)

import tkinter as tk
from tkinter import filedialog, messagebox, ttk
from docx import Document
from docx.shared import Pt, Cm
from docx.oxml.ns import qn
from docx.enum.text import WD_ALIGN_PARAGRAPH, WD_LINE_SPACING
import os
import re
import sys

# --- 1. 环境检测与 .doc 转换模块 (仅Windows有效) ---
if sys.platform.startswith('win'):
try:
import win32com.client
        CONVERT_ENABLED = True
except ImportError:
        CONVERT_ENABLED = False
print("提示: 如需处理 .doc 文件,请安装 pywin32: pip install pywin32")
else:
    CONVERT_ENABLED = False

defconvert_doc_to_docx(doc_path):
"""将旧版 .doc 转换为 .docx"""
ifnot CONVERT_ENABLED:
returnFalse"非Windows环境,无法转换 .doc 文件"

    word = None
try:
# 优先尝试 WPS
        word = win32com.client.Dispatch("Kwps.Application")
except:
try:
# 备选尝试 Office
            word = win32com.client.Dispatch("Word.Application")
except:
returnFalse"未检测到WPS或Office软件"

try:
        doc = word.Documents.Open(doc_path)
        docx_path = doc_path + "x"
# WPS和Office通用的保存格式代码 (wdFormatXMLDocument)
        doc.SaveAs(docx_path, 12
        doc.Close()
        word.Quit()
returnTrue, docx_path
except Exception as e:
if word: word.Quit()
returnFalsef"转换失败: {str(e)}"

# --- 2. 核心配置 (初始化默认值) ---
CONFIG = {
"margin": (2.542.543.173.17),
"western_font""Times New Roman",
"line_height": Pt(28.95),
"line_rule": WD_LINE_SPACING.EXACTLY,
"fonts": {
"title""方正小标宋_GBK",
"heading_1""黑体",
"heading_2""楷体_GB2312",
"heading_3""仿宋_GB2312",
"body""仿宋_GB2312"
    },
"font_sizes": {
"title"22,
"heading_1"16,
"heading_2"16,
"heading_3"16,
"body"16
    }
}

defset_font(run, chinese_font, western_font):
"""强制设置字体 (解决WPS中字体不生效的问题)"""
    run.font.name = western_font
    r = run._element.rPr
if r isnotNone:
# 移除旧的东亚字体设置
        rFonts = r.find(qn('w:eastAsia'))
if rFonts isnotNone:
            r.remove(rFonts)
# 添加新的东亚字体
        new_rFonts = r.makeelement(qn('w:eastAsia'), {})
        new_rFonts.set(qn('w:val'), chinese_font)
        r.append(new_rFonts)

defprocess_document(input_path, output_path):
"""核心处理逻辑"""
# --- 步骤1: 处理文件格式 ---
    file_ext = os.path.splitext(input_path)[1].lower()
    temp_docx_path = None

if file_ext == ".doc":
print("转换中: .doc -> .docx")
        success, result = convert_doc_to_docx(input_path)
ifnot success:
returnFalse, result
        temp_docx_path = result
        process_path = temp_docx_path
elif file_ext == ".docx":
        process_path = input_path
else:
returnFalse"不支持的文件格式"

try:
        doc = Document(process_path)

# 设置页边距
for section in doc.sections:
            section.top_margin = Cm(CONFIG["margin"][0])
            section.bottom_margin = Cm(CONFIG["margin"][1])
            section.left_margin = Cm(CONFIG["margin"][2])
            section.right_margin = Cm(CONFIG["margin"][3])

# --- 步骤2: 遍历段落并应用自定义样式 ---
for para in doc.paragraphs:
ifnot para.text.strip():
continue

            text = para.text.strip()

# 标题1: 匹配 "一、" 格式
if re.match(r'^[一二三四五六七八九十]、', text):
                pf = para.paragraph_format
                pf.first_line_indent = Pt(0# 取消缩进
                pf.alignment = WD_ALIGN_PARAGRAPH.LEFT
                pf.line_spacing_rule = CONFIG["line_rule"]
                pf.line_spacing = CONFIG["line_height"]

for run in para.runs:
                    set_font(run, CONFIG["fonts"]["heading_1"], CONFIG["western_font"])
                    run.font.size = Pt(CONFIG["font_sizes"]["heading_1"])
                    run.font.bold = False

# 标题2: 匹配 "(一)" 格式
elif re.match(r'^[((][\u4e00-\u9fa5]+[))]', text):
                pf = para.paragraph_format
                pf.first_line_indent = Pt(0)
                pf.alignment = WD_ALIGN_PARAGRAPH.LEFT
                pf.line_spacing_rule = CONFIG["line_rule"]
                pf.line_spacing = CONFIG["line_height"]

for run in para.runs:
                    set_font(run, CONFIG["fonts"]["heading_2"], CONFIG["western_font"])
                    run.font.size = Pt(CONFIG["font_sizes"]["heading_2"])
                    run.font.bold = False

# 标题3: 匹配 "1." 或 "1、" 格式
elif re.match(r'^\d+[\.、]', text):
                pf = para.paragraph_format
                pf.first_line_indent = Pt(0)
                pf.alignment = WD_ALIGN_PARAGRAPH.LEFT
                pf.line_spacing_rule = CONFIG["line_rule"]
                pf.line_spacing = CONFIG["line_height"]

for run in para.runs:
                    set_font(run, CONFIG["fonts"]["heading_3"], CONFIG["western_font"])
                    run.font.size = Pt(CONFIG["font_sizes"]["heading_3"])
                    run.font.bold = True

# 正文: 默认样式
else:
                pf = para.paragraph_format
                pf.first_line_indent = Cm(0.74# 首行缩进2字符
                pf.alignment = WD_ALIGN_PARAGRAPH.JUSTIFY
                pf.line_spacing_rule = CONFIG["line_rule"]
                pf.line_spacing = CONFIG["line_height"]

for run in para.runs:
                    set_font(run, CONFIG["fonts"]["body"], CONFIG["western_font"])
                    run.font.size = Pt(CONFIG["font_sizes"]["body"])
                    run.font.bold = False

# --- 步骤3: 处理文档大标题 (第1段) ---
iflen(doc.paragraphs) > 0:
            first_para = doc.paragraphs[0]
if first_para.text.strip():
                pf = first_para.paragraph_format
                pf.alignment = WD_ALIGN_PARAGRAPH.CENTER
                pf.space_after = Pt(12)

for run in first_para.runs:
                    set_font(run, CONFIG["fonts"]["title"], CONFIG["western_font"])
                    run.font.size = Pt(CONFIG["font_sizes"]["title"])
                    run.font.bold = False

        doc.save(output_path)

# 清理临时文件
if temp_docx_path and os.path.exists(temp_docx_path):
            os.remove(temp_docx_path)

returnTruef"成功! 保存至: {output_path}"

except Exception as e:
if temp_docx_path and os.path.exists(temp_docx_path):
            os.remove(temp_docx_path)
returnFalsef"处理异常: {str(e)}"

# --- 3. 美观的GUI界面 (含自定义配置) ---
classModernTypesettingApp:
def__init__(self, root):
self.root = root
self.root.title("🖋️ WPS 智能排版大师 (含自定义)")
self.root.geometry("750x600")
self.root.resizable(TrueTrue)

self.setup_styles()
self.create_widgets()

defsetup_styles(self):
        style = ttk.Style()
        style.configure("TLabel", font=("微软雅黑"10))
        style.configure("TButton", font=("微软雅黑"9))
self.root.configure(bg='#f5f5f5')

defcreate_widgets(self):
        notebook = ttk.Notebook(self.root)
        notebook.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

# --- Tab 1: 主操作界面 ---
        tab_main = ttk.Frame(notebook)
        notebook.add(tab_main, text="📄 文档处理")

        main_frame = ttk.LabelFrame(tab_main, text=" 任务配置 ", padding=20)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

# 输入输出
        tk.Label(main_frame, text="输入文件:", font=("微软雅黑"10)).grid(row=0, column=0, sticky=tk.W, pady=10)
self.input_entry = tk.Entry(main_frame, width=40, font=("Consolas"10), relief="solid")
self.input_entry.grid(row=0, column=1, padx=10, pady=10, sticky=tk.EW)
        tk.Button(main_frame, text="📂 选择文件", command=self.browse_input, bg="#007ACC", fg="white").grid(row=0, column=2, padx=10)

        tk.Label(main_frame, text="输出目录:", font=("微软雅黑"10)).grid(row=1, column=0, sticky=tk.W, pady=10)
self.output_entry = tk.Entry(main_frame, width=40, font=("Consolas"10), relief="solid")
self.output_entry.grid(row=1, column=1, padx=10, pady=10, sticky=tk.EW)
        tk.Button(main_frame, text="📁 选择文件夹", command=self.browse_output, bg="#28A745", fg="white").grid(row=1, column=2, padx=10)

# 控制按钮
        btn_frame = tk.Frame(main_frame)
        btn_frame.grid(row=2, column=0, columnspan=3, pady=30)

self.start_btn = tk.Button(btn_frame, text="🚀 开始排版"
                                  command=self.start_process, 
                                  bg="#DC3545", fg="white", width=15, height=2, font=("微软雅黑"10"bold"))
self.start_btn.pack(side=tk.LEFT, padx=20)

        tk.Button(btn_frame, text="❌ 退出", command=self.root.quit, 
                 width=15, height=2).pack(side=tk.LEFT, padx=20)

# 状态栏
self.status_var = tk.StringVar()
self.status_var.set("就绪: 支持 .doc 和 .docx 格式")
        status_bar = tk.Label(self.root, textvariable=self.status_var, relief="sunken"
                             bg="#e9ecef", fg="gray", font=("Consolas"9))
        status_bar.pack(side=tk.BOTTOM, fill=tk.X)

# --- Tab 2: 字体配置界面 ---
        tab_config = ttk.Frame(notebook)
        notebook.add(tab_config, text="🎨 字体配置")

        config_frame = ttk.LabelFrame(tab_config, text=" 自定义样式设置 ", padding=20)
        config_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

# 字体选择行
        tk.Label(config_frame, text="字体名称", font=("微软雅黑"10"bold")).grid(row=0, column=1, padx=40)
        tk.Label(config_frame, text="字号(磅)", font=("微软雅黑"10"bold")).grid(row=0, column=2, padx=20)

# 标题配置
        tk.Label(config_frame, text="文档大标题:", fg="blue").grid(row=1, column=0, sticky=tk.W, pady=10)
self.title_font = ttk.Combobox(config_frame, values=[
'方正小标宋_GBK''黑体''宋体''微软雅黑'
        ], width=15)
self.title_font.set(CONFIG["fonts"]["title"])
self.title_font.grid(row=1, column=1)

self.title_size = ttk.Combobox(config_frame, values=[16182022242628], width=8)
self.title_size.set(CONFIG["font_sizes"]["title"])
self.title_size.grid(row=1, column=2)

# 一级标题
        tk.Label(config_frame, text="一级标题(一、):", fg="darkgreen").grid(row=2, column=0, sticky=tk.W, pady=10)
self.l1_font = ttk.Combobox(config_frame, values=[
'黑体''方正小标宋_GBK''楷体_GB2312'
        ], width=15)
self.l1_font.set(CONFIG["fonts"]["heading_1"])
self.l1_font.grid(row=2, column=1)

self.l1_size = ttk.Combobox(config_frame, values=[1415161718], width=8)
self.l1_size.set(CONFIG["font_sizes"]["heading_1"])
self.l1_size.grid(row=2, column=2)

# 二级标题
        tk.Label(config_frame, text="二级标题((一)):", fg="purple").grid(row=3, column=0, sticky=tk.W, pady=10)
self.l2_font = ttk.Combobox(config_frame, values=[
'楷体_GB2312''仿宋_GB2312''黑体'
        ], width=15)
self.l2_font.set(CONFIG["fonts"]["heading_2"])
self.l2_font.grid(row=3, column=1)

self.l2_size = ttk.Combobox(config_frame, values=[1415161718], width=8)
self.l2_size.set(CONFIG["font_sizes"]["heading_2"])
self.l2_size.grid(row=3, column=2)

# 正文配置
        tk.Label(config_frame, text="正文/三级标题:", fg="gray").grid(row=4, column=0, sticky=tk.W, pady=10)
self.body_font = ttk.Combobox(config_frame, values=[
'仿宋_GB2312''宋体''黑体'
        ], width=15)
self.body_font.set(CONFIG["fonts"]["body"])
self.body_font.grid(row=4, column=1)

self.body_size = ttk.Combobox(config_frame, values=[1415161718], width=8)
self.body_size.set(CONFIG["font_sizes"]["body"])
self.body_size.grid(row=4, column=2)

# 操作按钮
        opt_frame = tk.Frame(config_frame)
        opt_frame.grid(row=5, column=0, columnspan=3, pady=30)

        tk.Button(opt_frame, text="💾 保存配置", command=self.save_config, 
                 bg="#17A2B8", fg="white", width=15).pack(side=tk.LEFT, padx=20)
        tk.Button(opt_frame, text="🔙 恢复默认", command=self.reset_config, 
                 bg="#6C757D", fg="white", width=15).pack(side=tk.LEFT, padx=20)

defbrowse_input(self):
        file_path = filedialog.askopenfilename(
            title="选择Word文档",
            filetypes=[("Word文档""*.docx *.doc"), ("All Files""*.*")]
        )
if file_path:
self.input_entry.delete(0, tk.END)
self.input_entry.insert(0, file_path)

defbrowse_output(self):
        dir_path = filedialog.askdirectory()
if dir_path:
self.output_entry.delete(0, tk.END)
self.output_entry.insert(0, dir_path)

defsave_config(self):
"""保存用户自定义的字体设置"""
try:
            CONFIG["fonts"]["title"] = self.title_font.get()
            CONFIG["fonts"]["heading_1"] = self.l1_font.get()
            CONFIG["fonts"]["heading_2"] = self.l2_font.get()
            CONFIG["fonts"]["body"] = self.body_font.get()

            CONFIG["font_sizes"]["title"] = int(self.title_size.get())
            CONFIG["font_sizes"]["heading_1"] = int(self.l1_size.get())
            CONFIG["font_sizes"]["heading_2"] = int(self.l2_size.get())
            CONFIG["font_sizes"]["body"] = int(self.body_size.get())

self.status_var.set("✅ 配置已更新,下次处理生效")
            messagebox.showinfo("成功""字体配置已保存!")
except Exception as e:
            messagebox.showerror("错误"f"配置保存失败: {e}")

defreset_config(self):
"""恢复默认配置"""
# 这里直接写死默认值
self.title_font.set('方正小标宋_GBK')
self.l1_font.set('黑体')
self.l2_font.set('楷体_GB2312')
self.body_font.set('仿宋_GB2312')

self.title_size.set(22)
self.l1_size.set(16)
self.l2_size.set(16)
self.body_size.set(16)

self.save_config()
self.status_var.set("⚙️ 已恢复默认设置")

defstart_process(self):
        input_file = self.input_entry.get()
        output_dir = self.output_entry.get()

ifnot input_file ornot output_dir:
            messagebox.showwarning("警告""请输入文件路径和输出目录!")
return

ifnot os.path.exists(input_file):
            messagebox.showerror("错误""输入文件不存在!")
return

# 生成输出路径
        filename = os.path.basename(input_file)
        name, ext = os.path.splitext(filename)
        output_file = os.path.join(output_dir, f"{name}_已排版{ext}")

self.status_var.set("🔄 正在处理中 (可能需要几秒)...")
self.root.update_idletasks()

        success, msg = process_document(input_file, output_file)

if success:
self.status_var.set("✅ 处理完成!")
            messagebox.showinfo("成功"f"任务完成!\n\n{msg}")
else:
self.status_var.set("❌ 处理失败")
            messagebox.showerror("错误"f"处理失败:\n{msg}")

if __name__ == "__main__":
    root = tk.Tk()
    app = ModernTypesettingApp(root)
    root.mainloop()

💡 使用前准备

  1. 1. 安装依赖
    如果你有 .doc 文件需要处理,请务必在终端运行:

    pip install pywin32

    (如果没有 .doc 文件,只处理 .docx,则不需要安装)

  2. 2. 字体库
    代码中使用了 仿宋_GB2312 和 楷体_GB2312。如果你的电脑(特别是非Windows系统)没有这些字体,WPS 可能会显示异常。如果报错,可以在配置界面手动选择系统中已有的字体(如“仿宋”、“楷体”)。

🛠️ 功能说明

  • • Tab 1 (文档处理):选择你的 .doc 或 .docx 文件,点击开始。
  • • Tab 2 (字体配置):你可以在这里修改“文档大标题”、“一级标题”、“二级标题”和“正文”的字体及大小。修改后点击“保存配置”,下次处理文档时就会生效。
👍 有用就点赞+收藏+转发 三连支持💬 有问题?评论区见,每条必回
⚠️ 免责声明:本文提供的配置建议仅供参考,生产环境部署前请在测试环境充分验证。因配置不当导致的业务中断,责任自负。
【如有疏漏,敬请指正!】