「强烈推荐」告别Word手动排版焦虑!这款Python智能排版神器杀疯了,一键智能搞定格式,打工人准时下班就靠它!



“带你横跨办公自动化的数据江海”
@摸鱼


闻道有先后,术业有专攻。
各位大佬好!
~我依旧是你们的老朋友摸鱼~
♥ 1
在职场摸爬滚打的这十多年里,我用Python悄悄干了不少“正事”——不知不觉攒下了一整套办公自动化的实用项目技巧。去年10月初创立了公众号 「码海听潮」 ,初衷很简单:把重复的劳动交给代码,把摸鱼的时间留给生活。
目前已经吭哧吭哧更新了近100篇原创文章,每一篇都是实操干货,不讲虚的,只聊怎么用代码真正解放双手,帮大家早点下班、准点摸鱼
♥ 2
♥ 3好叻,多了不说,少了不唠,咱直接上干货。
办公需求场景
从崩溃到优雅的进化
有一个神秘的word文件夹,其中包含20个格式完全一致的Word文档。现在的需求是:按照下方列出的具体要求,对所有文档进行统一格式化处理:
• 主标题:方正小标宋简体,二号(22磅),行距33,加粗
• 一级标题(一、二、三…):黑体,三号(16磅),行距28,加粗
• 二级标题((一)(二)…):楷体,三号(16磅),行距28,加粗
• 三级标题(1. 2. 3. …):仿宋,三号(16磅),行距28,加粗
• 四级标题((1)(2)…):仿宋,三号(16磅),行距28,加粗
• 正文:仿宋,三号(16磅)
• 表格标题字体:黑体,四号(14磅)
• 图标题字体:黑体,四号(14磅)
• 附件字体:黑体,三号(16磅)
• 页边距设置为:上边距3.7cm,下边距3.5cm,左边距2.8cm,右边距2.6cm
要是这种类似的需求你的Big Boss安排你去完成,请问阁下该如何应对?
-
需求的word文件列表

-
需求word文档

办公痛点分析

01
痛点一:效率低下与耗时严重
-
人工逐一打开20个文档,对照要求手动调整字体、段落、页边距、标题样式等格式,需要重复操作20次。即便每个文档只需5分钟,总计也接近2小时。这种重复劳动极其枯燥,且占用了本可用于更有价值工作的时间。
02
痛点二:易出错且难以保证一致性
-
人工操作极易疲劳或分心,很可能出现以下问题:某个文档遗漏了一个格式要求(如忘记统一行距)、字号设置成18而非要求的16、或者某个标题样式应用错误。由于是手工操作,很难保证20个文档的格式完完全全一致,最终导致输出质量参差不齐。
由此可见若的话若操作成千上百个word文档,整个操作流程繁琐且耗时,高频次的鼠标点击和键盘输入使操作者手指疲劳,堪称”键盘敲冒烟”式的体力劳动,加上人工疲劳操作极易导致遗漏文件夹。于是乎这时候,按以往的 “解题套路”,Python 的专属 BGM 该响起来了 ——go~ go~ go~,救苦救难的大救星这不就来了!!
@摸鱼
问题拆解思路
1.遍历word文件夹,提取word文档路径列表→
2.循环word路径列表,用python-docx操作word,设置指定的标题段落正文等格式
3.保存设置好格式的word内容
下面,我就用python代码让微信见识一下,什么叫”传统文化遇上赛博效率”(仅展示部分代码,非完整代码,需完整代码看文章末尾说明~)
import tkinter as tkfrom tkinter import ttk, filedialog, messagebox, scrolledtextfrom tkinterdnd2 import DND_FILES, TkinterDnDclass WordFormatterGUI:def __init__(self, master):self.master = mastermaster.title("Word文档智能排版工具 v3.0.0")master.geometry("850x650")self.entries = {}self.set_outline_var = tk.BooleanVar(value=True)self.apply_heading_styles_var = tk.BooleanVar(value=True)self.sync_styles_var = tk.BooleanVar(value=False)self.enable_attachment_var = tk.BooleanVar(value=True)self.force_a4_var = tk.BooleanVar(value=False)self.create_widgets()self.master.bind('<Map>', self._on_first_show)def _on_first_show(self, event=None):self.master.unbind('<Map>')self.master.update_idletasks()total_width = self.main_pane.winfo_width()if total_width > 0:self.main_pane.sashpos(0, int(total_width * 0.3))def create_widgets(self):self.main_pane = ttk.PanedWindow(self.master, orient=tk.HORIZONTAL)self.main_pane.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)# ========== 左侧操作区 ==========left_container = ttk.LabelFrame(self.main_pane, text="操作区", padding=5)self.main_pane.add(left_container, weight=30)file_frame = ttk.LabelFrame(left_container, text="待处理文件(支持拖拽文件或文件夹)")file_frame.pack(fill=tk.X, expand=False, pady=5)list_container = ttk.Frame(file_frame, height=200)list_container.pack(fill=tk.X, expand=False)list_container.pack_propagate(False)scrollbar = ttk.Scrollbar(list_container, orient=tk.VERTICAL)self.file_listbox = tk.Listbox(list_container, yscrollcommand=scrollbar.set, selectmode=tk.EXTENDED)scrollbar.config(command=self.file_listbox.yview)scrollbar.pack(side=tk.RIGHT, fill=tk.Y)self.file_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)self.file_listbox.drop_target_register(DND_FILES)self.file_listbox.dnd_bind('<<Drop>>', self.handle_drop)self.placeholder_label = ttk.Label(self.file_listbox, text="📎 拖拽文件或文件夹到这里", foreground="grey")file_button_frame = ttk.Frame(left_container)file_button_frame.pack(fill=tk.X, pady=5)ttk.Button(file_button_frame, text="❌ 移除选中", command=self.remove_files).pack(side=tk.LEFT, fill=tk.X, expand=True, padx=2)ttk.Button(file_button_frame, text="🗑️ 清空列表", command=self.clear_list).pack(side=tk.LEFT, fill=tk.X, expand=True, padx=2)log_frame = ttk.LabelFrame(left_container, text="处理日志")log_frame.pack(fill=tk.BOTH, expand=True, pady=(5, 0))self.debug_text = scrolledtext.ScrolledText(log_frame, state='disabled', wrap=tk.WORD, font=('Consolas', 9))self.debug_text.pack(fill=tk.BOTH, expand=True)# ========== 右侧参数设置区 ==========right_container = ttk.LabelFrame(self.main_pane, text="参数设置区", padding=5)self.main_pane.add(right_container, weight=70)# 右侧内容容器right_content = ttk.Frame(right_container)right_content.pack(fill=tk.BOTH, expand=True)# 可滚动区域scrollable_frame = ttk.Frame(right_content)scrollable_frame.pack(fill=tk.BOTH, expand=True)# 创建Canvas和滚动条right_canvas = tk.Canvas(scrollable_frame, highlightthickness=0)right_scrollbar = ttk.Scrollbar(scrollable_frame, orient="vertical", command=right_canvas.yview)right_scrollable_frame = ttk.Frame(right_canvas)right_scrollable_frame.bind("<Configure>",lambda e: right_canvas.configure(scrollregion=right_canvas.bbox("all")))right_canvas.create_window((0, 0), window=right_scrollable_frame, anchor="nw", width=right_canvas.winfo_width())def _configure_scrollable_frame(event):right_canvas.itemconfig(1, width=event.width)right_canvas.bind("<Configure>", _configure_scrollable_frame)right_canvas.configure(yscrollcommand=right_scrollbar.set)def _on_mousewheel(event):right_canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")right_canvas.bind("<Enter>", lambda e: right_canvas.bind_all("<MouseWheel>", _on_mousewheel))right_canvas.bind("<Leave>", lambda e: right_canvas.unbind_all("<MouseWheel>"))right_canvas.pack(side="left", fill="both", expand=True)right_scrollbar.pack(side="right", fill="y")# Notebookright_notebook = ttk.Notebook(right_scrollable_frame)right_notebook.pack(fill=tk.X, expand=False)# 各标签页page_tab = ttk.Frame(right_notebook)right_notebook.add(page_tab, text='📄 页面设置')self._create_page_settings(page_tab)title_tab = ttk.Frame(right_notebook)right_notebook.add(title_tab, text='📌 标题样式')self._create_title_settings(title_tab)body_tab = ttk.Frame(right_notebook)right_notebook.add(body_tab, text='📖 正文与层级')self._create_body_settings(body_tab)other_tab = ttk.Frame(right_notebook)right_notebook.add(other_tab, text='🔧 其他元素')self._create_other_settings(other_tab)regex_tab = ttk.Frame(right_notebook)right_notebook.add(regex_tab, text='🔍 识别规则')self._create_regex_settings(regex_tab)options_tab = ttk.Frame(right_notebook)right_notebook.add(options_tab, text='⚙️ 全局选项')self._create_options_settings(options_tab)config_tab = ttk.Frame(right_notebook)right_notebook.add(config_tab, text='💾 配置管理')self._create_config_settings(config_tab)# ========== 底部按钮 ==========bottom_frame = ttk.Frame(right_content)bottom_frame.pack(fill=tk.X, pady=(10, 0))ttk.Separator(bottom_frame, orient='horizontal').pack(fill=tk.X, pady=(0, 10))style = ttk.Style()style.configure('Success.TButton', font=('微软雅黑', 11, 'bold'))ttk.Button(bottom_frame, text="🚀 开始排版", style='Success.TButton',command=self.start_processing).pack(fill=tk.X, ipady=10)self._update_listbox_placeholder()def _create_section_label(self, parent, text, help_text=None):frame = ttk.Frame(parent)frame.pack(fill=tk.X, pady=(10, 5))label = ttk.Label(frame, text=text, font=('微软雅黑', 10, 'bold'))label.pack(side=tk.LEFT)if help_text:help_label = ttk.Label(frame, text=" ❓", foreground="blue", cursor="hand2", font=('Arial', 10))help_label.pack(side=tk.LEFT, padx=(5, 0))help_label.bind("<Button-1>", lambda e: self._show_help_tooltip("帮助", help_text))separator = ttk.Separator(parent, orient='horizontal')separator.pack(fill=tk.X, pady=(0, 5))return framedef _create_input_row(self, parent, label, var_name, row, col=0, width=15):frame = ttk.Frame(parent)frame.grid(row=row, column=col, sticky='ew', padx=5, pady=3)ttk.Label(frame, text=label, width=12).pack(side=tk.LEFT)entry = ttk.Entry(frame, width=width)entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(5, 0))self.entries[var_name] = entryreturn entrydef _create_combo_row(self, parent, label, var_name, options, row, col=0, width=18):frame = ttk.Frame(parent)frame.grid(row=row, column=col, sticky='ew', padx=5, pady=3)ttk.Label(frame, text=label, width=12).pack(side=tk.LEFT)combo = ttk.Combobox(frame, values=options, state='normal', width=width)combo.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(5, 0))self.entries[var_name] = comboreturn combodef _create_font_size_row(self, parent, label, var_name, row, col=0):font_sizes = ['一号 (26pt)', '小一 (24pt)', '二号 (22pt)', '小二 (18pt)','三号 (16pt)', '小三 (15pt)', '四号 (14pt)', '小四 (12pt)','五号 (10.5pt)', '小五 (9pt)']frame = ttk.Frame(parent)frame.grid(row=row, column=col, sticky='ew', padx=5, pady=3)ttk.Label(frame, text=label, width=12).pack(side=tk.LEFT)combo = ttk.Combobox(frame, values=font_sizes, width=15)combo.pack(side=tk.LEFT, padx=(5, 0))self.entries[var_name] = comboreturn combodef _create_page_settings(self, parent):container = ttk.Frame(parent)container.pack(fill=tk.X, padx=10, pady=10)self._create_section_label(container, "页边距设置", "设置文档的上下左右边距和页脚距离(单位:厘米)")margin_frame = ttk.Frame(container)margin_frame.pack(fill=tk.X, pady=5)row = 0self._create_input_row(margin_frame, "上边距(cm):", 'margin_top', row, 0)self._create_input_row(margin_frame, "下边距(cm):", 'margin_bottom', row, 1)row += 1self._create_input_row(margin_frame, "左边距(cm):", 'margin_left', row, 0)self._create_input_row(margin_frame, "右边距(cm):", 'margin_right', row, 1)row += 1self._create_input_row(margin_frame, "页脚距(cm):", 'footer_distance', row, 0)ttk.Checkbutton(margin_frame, text="强制设置为A4纸张", variable=self.force_a4_var).grid(row=row, column=1, sticky='w', padx=5, pady=5)self._create_section_label(container, "页码设置", "设置页码的对齐方式和字体格式")page_frame = ttk.Frame(container)page_frame.pack(fill=tk.X, pady=5)row = 0self._create_combo_row(page_frame, "页码对齐:", 'page_number_align', ['奇偶分页', '居中'], row, 0)row += 1self._create_combo_row(page_frame, "页码字体:", 'page_number_font', ['宋体', 'Times New Roman'], row, 0)row += 1self._create_font_size_row(page_frame, "页码字号:", 'page_number_size', row, 0)def _create_title_settings(self, parent):container = ttk.Frame(parent)container.pack(fill=tk.X, padx=10, pady=10)help_text = "主标题识别规则:\n• 识别文档开头的连续【居中】且【字体字号相同】的段落\n\n副标题识别规则:\n• 主标题下方,同样【居中】但【字体字号与主标题不同】的段落"self._create_section_label(container, "主标题设置", help_text)title_frame = ttk.Frame(container)title_frame.pack(fill=tk.X, pady=5)row = 0self._create_combo_row(title_frame, "题目字体:", 'title_font',['方正小标宋简体', '方正小标宋_GBK', '华文中宋'], row, 0)row += 1self._create_font_size_row(title_frame, "题目字号:", 'title_size', row, 0)row += 1self._create_input_row(title_frame, "行距(磅):", 'title_line_spacing', row, 0)self._create_section_label(container, "副标题设置")subtitle_frame = ttk.Frame(container)subtitle_frame.pack(fill=tk.X, pady=5)row = 0self._create_combo_row(subtitle_frame, "副标题字体:", 'subtitle_font',['楷体_GB2312', '方正楷体_GBK', '楷体', '方正楷体简体', '华文楷体'], row, 0)row += 1self._create_font_size_row(subtitle_frame, "副标题字号:", 'subtitle_size', row, 0)row += 1self._create_input_row(subtitle_frame, "行距(磅):", 'subtitle_line_spacing', row, 0)def _create_body_settings(self, parent):container = ttk.Frame(parent)container.pack(fill=tk.X, padx=10, pady=10)heading_notebook = ttk.Notebook(container)heading_notebook.pack(fill=tk.X, pady=5)h1_frame = ttk.Frame(heading_notebook)heading_notebook.add(h1_frame, text="一级标题")row = 0self._create_combo_row(h1_frame, "字体:", 'h1_font',['黑体', '方正黑体_GBK', '方正黑体简体', '华文黑体'], row, 0)row += 1self._create_font_size_row(h1_frame, "字号:", 'h1_size', row, 0)h2_frame = ttk.Frame(heading_notebook)heading_notebook.add(h2_frame, text="二级标题")row = 0self._create_combo_row(h2_frame, "字体:", 'h2_font',['楷体_GB2312', '方正楷体_GBK', '楷体', '方正楷体简体', '华文楷体'], row, 0)row += 1self._create_font_size_row(h2_frame, "字号:", 'h2_size', row, 0)h3_frame = ttk.Frame(heading_notebook)heading_notebook.add(h3_frame, text="三级标题")row = 0self._create_combo_row(h3_frame, "字体:", 'h3_font',['仿宋_GB2312', '方正仿宋_GBK', '仿宋', '方正仿宋简体', '华文仿宋'], row, 0)row += 1self._create_font_size_row(h3_frame, "字号:", 'h3_size', row, 0)h4_frame = ttk.Frame(heading_notebook)heading_notebook.add(h4_frame, text="四级标题")row = 0self._create_combo_row(h4_frame, "字体:", 'h4_font',['仿宋_GB2312', '方正仿宋_GBK', '仿宋', '方正仿宋简体', '华文仿宋'], row, 0)row += 1self._create_font_size_row(h4_frame, "字号:", 'h4_size', row, 0)self._create_section_label(container, "正文设置")body_frame = ttk.Frame(container)body_frame.pack(fill=tk.X, pady=5)row = 0self._create_combo_row(body_frame, "正文字体:", 'body_font',['仿宋_GB2312', '方正仿宋_GBK', '仿宋', '方正仿宋简体', '华文仿宋'], row, 0)row += 1self._create_font_size_row(body_frame, "正文字号:", 'body_size', row, 0)row += 1self._create_input_row(body_frame, "行距(磅):", 'line_spacing', row, 0)self._create_section_label(container, "段落缩进")indent_frame = ttk.Frame(container)indent_frame.pack(fill=tk.X, pady=5)row = 0self._create_input_row(indent_frame, "左缩进(cm):", 'left_indent_cm', row, 0)self._create_input_row(indent_frame, "右缩进(cm):", 'right_indent_cm', row, 1)def _create_other_settings(self, parent):container = ttk.Frame(parent)container.pack(fill=tk.X, padx=10, pady=10)help_text = "图表标题识别:\n• 自动查找图片或表格上方/下方最近的、居中的、以\"图\"或\"表\"开头的段落\n\n附件标识识别:\n• 识别\"附件1\"、\"附件:\"等独立段落\n• 启用后将自动段前分页并按主副标题规则识别其自身标题"self._create_section_label(container, "图表标题", help_text)caption_frame = ttk.Frame(container)caption_frame.pack(fill=tk.X, pady=5)row = 0self._create_combo_row(caption_frame, "表格标题字体:", 'table_caption_font',['黑体', '宋体', '仿宋_GB2312'], row, 0)row += 1self._create_font_size_row(caption_frame, "表格标题字号:", 'table_caption_size', row, 0)row += 1self._create_combo_row(caption_frame, "图形标题字体:", 'figure_caption_font',['黑体', '宋体', '仿宋_GB2312'], row, 0)row += 1self._create_font_size_row(caption_frame, "图形标题字号:", 'figure_caption_size', row, 0)self._create_section_label(container, "附件设置")attachment_frame = ttk.Frame(container)attachment_frame.pack(fill=tk.X, pady=5)ttk.Checkbutton(attachment_frame, text="启用附件格式化", variable=self.enable_attachment_var).pack(anchor='w', pady=5)row = 0attach_inner = ttk.Frame(attachment_frame)attach_inner.pack(fill=tk.X)self._create_combo_row(attach_inner, "附件字体:", 'attachment_font',['黑体', '宋体', '仿宋_GB2312'], row, 0)row += 1self._create_font_size_row(attach_inner, "附件字号:", 'attachment_size', row, 0)def _create_regex_preset_buttons(self, parent):preset_frame = ttk.LabelFrame(parent, text="快速预设")preset_frame.pack(fill=tk.X, pady=10)button_frame = ttk.Frame(preset_frame)button_frame.pack(fill=tk.X, padx=10, pady=10)row1_frame = ttk.Frame(button_frame)row1_frame.pack(fill=tk.X, pady=2)ttk.Button(row1_frame, text="🇨🇳 中文数字格式", width=18).pack(side=tk.LEFT, padx=2)ttk.Button(row1_frame, text="🔢 阿拉伯数字格式", width=18).pack(side=tk.LEFT, padx=2)ttk.Button(row1_frame, text="🔄 混合格式", width=18).pack(side=tk.LEFT, padx=2)row2_frame = ttk.Frame(button_frame)row2_frame.pack(fill=tk.X, pady=2)ttk.Button(row2_frame, text="⚖️ 法律文书格式", width=18).pack(side=tk.LEFT, padx=2)ttk.Button(row2_frame, text="📚 学术论文格式", width=18).pack(side=tk.LEFT, padx=2)desc_text = "📌 预设说明:\n• 中文数字:一、二、三... / (一)(二)... / 1. 2. 3. / (1)(2)\n• 阿拉伯数字:1. 2. 3. / 1.1 1.2... / 1.1.1...\n• 混合格式:第一章、第二章... / (一)(二)... / 1. 2. 3.\n• 法律文书:一、二、三... / (一)(二)... / 1. 2. 3. / (1)(2)\n• 学术论文:1 Heading / 1.1 Heading / 1.1.1 Heading"desc_label = ttk.Label(preset_frame, text=desc_text, justify=tk.LEFT, foreground="gray")desc_label.pack(fill=tk.X, padx=10, pady=(0, 10))def _create_regex_settings(self, parent):container = ttk.Frame(parent)container.pack(fill=tk.X, padx=10, pady=10)self._create_regex_preset_buttons(container)regex_notebook = ttk.Notebook(container)regex_notebook.pack(fill=tk.X, pady=5)title_regex_tab = ttk.Frame(regex_notebook)regex_notebook.add(title_regex_tab, text="标题识别")self._create_title_regex_tab(title_regex_tab)attachment_regex_tab = ttk.Frame(regex_notebook)regex_notebook.add(attachment_regex_tab, text="附件识别")self._create_attachment_regex_tab(attachment_regex_tab)caption_regex_tab = ttk.Frame(regex_notebook)regex_notebook.add(caption_regex_tab, text="图表标题")self._create_caption_regex_tab(caption_regex_tab)self._create_section_label(container, "正则表达式测试")test_frame = ttk.Frame(container)test_frame.pack(fill=tk.X, pady=5)ttk.Label(test_frame, text="测试文本:").grid(row=0, column=0, sticky='w', padx=5, pady=5)self.test_entry = ttk.Entry(test_frame, width=50)self.test_entry.grid(row=0, column=1, sticky='ew', padx=5, pady=5)ttk.Button(test_frame, text="测试匹配").grid(row=0, column=2, padx=5, pady=5)self.test_result_label = ttk.Label(test_frame, text="", foreground="gray")self.test_result_label.grid(row=1, column=0, columnspan=3, padx=5, pady=5)test_frame.columnconfigure(1, weight=1)def _create_title_regex_tab(self, parent):help_text = "自定义标题识别正则表达式\n\n一级标题示例:\n• 中文数字+顿号:^[一二三四五六七八九十百千万零]+\\s*、\n• 大写数字+点:^[一二三四五六七八九十]+[、..]\n\n二级标题示例:\n• 括号中文数字:(一)、(二)\n• 正则表达式:^[(\\(][一二三四五六七八九十百千万零]+[)\\)]\n\n三级标题示例:\n• 阿拉伯数字+点:1.、2.\n• 正则表达式:^\\d+\\s*[\\..]\n\n四级标题示例:\n• 括号阿拉伯数字:(1)、(2)\n• 正则表达式:^[(\\(]\\d+[)\\)]\n\n注意:正则表达式中的反斜杠需要转义,如 \\\\d 表示数字"self._create_section_label(parent, "标题识别正则表达式", help_text)regex_frame = ttk.Frame(parent)regex_frame.pack(fill=tk.X, pady=5)row = 0ttk.Label(regex_frame, text="一级标题:").grid(row=row, column=0, sticky='w', padx=5, pady=5)h1_entry = ttk.Entry(regex_frame, width=50)h1_entry.grid(row=row, column=1, sticky='ew', padx=5, pady=5)h1_entry.insert(0, r'^[一二三四五六七八九十百千万零]+\s*、')self.entries['h1_pattern'] = h1_entryttk.Button(regex_frame, text="恢复默认").grid(row=row, column=2, padx=5, pady=5)row += 1ttk.Label(regex_frame, text="二级标题:").grid(row=row, column=0, sticky='w', padx=5, pady=5)h2_entry = ttk.Entry(regex_frame, width=50)h2_entry.grid(row=row, column=1, sticky='ew', padx=5, pady=5)h2_entry.insert(0, r'^[(\(][一二三四五六七八九十百千万零]+[)\)]')self.entries['h2_pattern'] = h2_entryttk.Button(regex_frame, text="恢复默认").grid(row=row, column=2, padx=5, pady=5)row += 1ttk.Label(regex_frame, text="三级标题:").grid(row=row, column=0, sticky='w', padx=5, pady=5)h3_entry = ttk.Entry(regex_frame, width=50)h3_entry.grid(row=row, column=1, sticky='ew', padx=5, pady=5)h3_entry.insert(0, r'^\d+\s*[\..]')self.entries['h3_pattern'] = h3_entryttk.Button(regex_frame, text="恢复默认").grid(row=row, column=2, padx=5, pady=5)row += 1ttk.Label(regex_frame, text="四级标题:").grid(row=row, column=0, sticky='w', padx=5, pady=5)h4_entry = ttk.Entry(regex_frame, width=50)h4_entry.grid(row=row, column=1, sticky='ew', padx=5, pady=5)h4_entry.insert(0, r'^[(\(]\d+[)\)]')self.entries['h4_pattern'] = h4_entryttk.Button(regex_frame, text="恢复默认").grid(row=row, column=2, padx=5, pady=5)regex_frame.columnconfigure(1, weight=1)def _create_attachment_regex_tab(self, parent):help_text = "自定义附件识别正则表达式\n\n附件示例:\n• 附件1\n• 附件一\n• 附件:\n• 附件一:\n• 附件1:\n\n正则表达式示例:\n• ^附件\\s*(\\d+|[一二三四五六七八九十百千万零]+)?\\s*[::]?$\n\n注意:正则表达式中的反斜杠需要转义,如 \\\\d 表示数字"self._create_section_label(parent, "附件识别正则表达式", help_text)regex_frame = ttk.Frame(parent)regex_frame.pack(fill=tk.X, pady=5)row = 0ttk.Label(regex_frame, text="附件标识:").grid(row=row, column=0, sticky='w', padx=5, pady=5)attachment_entry = ttk.Entry(regex_frame, width=60)attachment_entry.grid(row=row, column=1, sticky='ew', padx=5, pady=5)attachment_entry.insert(0, r'^附件\s*(\d+|[一二三四五六七八九十百千万零]+)?\s*[::]?$')self.entries['attachment_pattern'] = attachment_entryttk.Button(regex_frame, text="恢复默认").grid(row=row, column=2, padx=5, pady=5)regex_frame.columnconfigure(1, weight=1)def _create_caption_regex_tab(self, parent):help_text = "自定义图表标题识别正则表达式\n\n图标题示例:\n• 图1\n• 图 1\n• 图1-1\n\n表标题示例:\n• 表1\n• 表 1\n• 表1-1\n\n正则表达式示例:\n• 图标题:^图\\s*\\d+\n• 表标题:^表\\s*\\d+\n\n注意:正则表达式中的反斜杠需要转义,如 \\\\d 表示数字"self._create_section_label(parent, "图表标题识别正则表达式", help_text)regex_frame = ttk.Frame(parent)regex_frame.pack(fill=tk.X, pady=5)row = 0ttk.Label(regex_frame, text="图标题:").grid(row=row, column=0, sticky='w', padx=5, pady=5)figure_entry = ttk.Entry(regex_frame, width=60)figure_entry.grid(row=row, column=1, sticky='ew', padx=5, pady=5)figure_entry.insert(0, r'^图\s*\d+')self.entries['figure_caption_pattern'] = figure_entryttk.Button(regex_frame, text="恢复默认").grid(row=row, column=2, padx=5, pady=5)row += 1ttk.Label(regex_frame, text="表标题:").grid(row=row, column=0, sticky='w', padx=5, pady=5)table_entry = ttk.Entry(regex_frame, width=60)table_entry.grid(row=row, column=1, sticky='ew', padx=5, pady=5)table_entry.insert(0, r'^表\s*\d+')self.entries['table_caption_pattern'] = table_entryttk.Button(regex_frame, text="恢复默认").grid(row=row, column=2, padx=5, pady=5)regex_frame.columnconfigure(1, weight=1)def _create_options_settings(self, parent):container = ttk.Frame(parent)container.pack(fill=tk.X, padx=10, pady=10)self._create_section_label(container, "大纲与样式", "大纲级别用于生成导航目录,标题样式便于生成Word目录")options_frame = ttk.Frame(container)options_frame.pack(fill=tk.X, pady=10)ttk.Checkbutton(options_frame, text="自动设置大纲级别(用于生成导航目录)",variable=self.set_outline_var).pack(anchor='w', pady=5)ttk.Checkbutton(options_frame, text="应用Word内置标题样式(推荐,便于生成目录)",variable=self.apply_heading_styles_var).pack(anchor='w', pady=5)ttk.Checkbutton(options_frame, text="同步自定义字体到标题样式",variable=self.sync_styles_var).pack(anchor='w', pady=5)self._create_section_label(container, "安全提示")tip_frame = ttk.Frame(container)tip_frame.pack(fill=tk.X, pady=10)tip_text = "🔒 本工具不会修改您的任何原始文件!\n所有操作都在后台的临时副本上进行,确保源文件100%安全。\n\n⚠️ 处理前请关闭所有已打开的Word和WPS文档,\n以免未保存的工作丢失。"tip_label = ttk.Label(tip_frame, text=tip_text, foreground="gray", justify=tk.LEFT)tip_label.pack(anchor='w')def _create_config_settings(self, parent):container = ttk.Frame(parent)container.pack(fill=tk.X, padx=10, pady=10)self._create_section_label(container, "配置管理", "保存和加载配置方案,方便在不同场景间切换")config_frame = ttk.Frame(container)config_frame.pack(fill=tk.X, pady=20)btn_frame = ttk.Frame(config_frame)btn_frame.pack()ttk.Button(btn_frame, text="📂 加载配置", width=20).grid(row=0, column=0, padx=5, pady=5)ttk.Button(btn_frame, text="💾 保存配置", width=20).grid(row=0, column=1, padx=5, pady=5)ttk.Button(btn_frame, text="⭐ 保存为默认", width=20).grid(row=1, column=0, padx=5, pady=5)ttk.Button(btn_frame, text="🔄 恢复内置默认", width=20).grid(row=1, column=1, padx=5, pady=5)self._create_section_label(container, "使用说明")help_frame = ttk.Frame(container)help_frame.pack(fill=tk.X, pady=10)help_text = "📋 快速上手:\n1. 拖拽文件或文件夹到上方列表\n2. 在各标签页中调整格式参数\n3. 在\"识别规则\"标签页可自定义各种匹配规则,或使用快速预设\n4. 点击\"开始排版\"按钮\n5. 选择输出位置,等待处理完成\n\n💡 小技巧:\n• 可以将常用的参数配置保存为默认,下次启动自动加载\n• 支持拖拽文件和文件夹到文件列表\n• 点击各分区旁的❓图标可查看详细识别规则\n• 在识别规则页可以测试自定义的正则表达式\n• 使用快速预设可以一键应用常用的识别规则"help_label = ttk.Label(help_frame, text=help_text, justify=tk.LEFT)help_label.pack(anchor='w')# ========== 占位方法 ==========def _show_help_tooltip(self, title, message):messagebox.showinfo(title, message)def _update_listbox_placeholder(self):if self.file_listbox.size() == 0:self.placeholder_label.place(in_=self.file_listbox, relx=0.5, rely=0.5, anchor=tk.CENTER)else:self.placeholder_label.place_forget()def handle_drop(self, event):passdef remove_files(self):passdef clear_list(self):passdef start_processing(self):messagebox.showinfo("提示", "开始排版功能")def log_to_debug_window(self, message):self.debug_text.config(state='normal')self.debug_text.insert(tk.END, message + '\n')self.debug_text.config(state='disabled')self.debug_text.see(tk.END)if __name__ == "__main__":root = TkinterDnD.Tk()app = WordFormatterGUI(root)root.mainloop()
最终所有word文档都进行了统一的格式化处理,实现了之前既定的需求….

通过上面Python自动化脚本,仅用几分钟的时间就完成原需手动操作数小时甚至数天的工作任务。从最初准备手动人工机械操作的麻木到用python实现高效自动化的畅快,工作效率获得指数级提升,终于实现了不加班熬夜的自由!
大佬们也可以举一反三,参照上面的代码思路根据自己工作中的实际情况来具体问题具体分析,实现自己定制化的需求。
结语
当Python遇见办公,牛马打工人终于笑出了猪叫声
【职场人必看】每天早上一睁眼,想到又要面对:
1.📊 堆积如山的Excel表格
2.📑 机械重复的复制粘贴
3.✍️ 永远改不完的各类文档
4.诸如此类的更多……..
是不是连Ctrl+Alt+Delete的心都有了?
别慌!别急,摸鱼这位“职场外挂”已经带着Python代码来拯救你了!
友情提示:考虑到没有python环境的朋友需要打包好的成品exe,摸鱼早已贴心打包好,本篇文章代码打包的exe截图如下:

另外,《码海听潮》公众号所有文章码和exe程序已打包好上传绿联nas私有云,有需要的大佬扫一扫上面博主的个人微信二维码,需要的大佬需支付9.9元永久拥有公众号资源(写原创干货费时费力,属实不易),邀请您进入社区群获取下载链接!!,群内提供python办公自动化交流问题,解决问题,且码海听潮微信公众号文章发布会第一时间会更新到群里,非诚勿扰哈!

码海听潮官方社区群如下:


赶紧微信扫一扫下方二维码添加摸鱼君微信

夜雨聆风