import tkinter as tk from tkinter import ttk, filedialog, messagebox import os from docx import Document import threading class WordReplacerApp: def __init__(self, root): self.root = root self.root.title("Word日期替换工具") self.root.geometry("600x560") self.root.resizable(False, False) # 设置样式 style = ttk.Style() style.theme_use('clam') # 创建主框架 main_frame = ttk.Frame(root, padding="20") main_frame.pack(fill=tk.BOTH, expand=True) # 标题 title_label = ttk.Label(main_frame, text="Word文档日期批量替换工具", font=("微软雅黑", 16, "bold")) title_label.pack(pady=(0, 20)) # 说明区域 info_frame = ttk.LabelFrame(main_frame, text="替换规则", padding="10") info_frame.pack(fill=tk.X, pady=(0, 15)) rule1 = ttk.Label(info_frame, text="• 将 \"xx月\" 替换为 \"07月\"") rule1.pack(anchor=tk.W, pady=2) rule2 = ttk.Label(info_frame, text="• 将 \"xx日\" 替换为 \"08日\"") rule2.pack(anchor=tk.W, pady=2) rule3 = ttk.Label(info_frame, text="• 支持同时替换月和日", foreground="gray") rule3.pack(anchor=tk.W, pady=2) # 文件选择区域 file_frame = ttk.LabelFrame(main_frame, text="文件选择", padding="10") file_frame.pack(fill=tk.X, pady=(0, 15)) # 文件路径显示 self.file_path_var = tk.StringVar() self.file_path_var.set("未选择文件") path_entry = ttk.Entry(file_frame, textvariable=self.file_path_var, state='readonly', font=("微软雅黑", 10)) path_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(0, 10)) select_btn = ttk.Button(file_frame, text="选择Word文件", command=self.select_file, width=12) select_btn.pack(side=tk.RIGHT) # 选项区域 options_frame = ttk.LabelFrame(main_frame, text="替换选项", padding="10") options_frame.pack(fill=tk.X, pady=(0, 15)) # 替换月份选项 self.replace_month_var = tk.BooleanVar(value=True) month_check = ttk.Checkbutton(options_frame, text="替换月份 (xx月 → 07月)", variable=self.replace_month_var) month_check.pack(anchor=tk.W, pady=2) # 替换日期选项 self.replace_day_var = tk.BooleanVar(value=True) day_check = ttk.Checkbutton(options_frame, text="替换日期 (xx日 → 08日)", variable=self.replace_day_var) day_check.pack(anchor=tk.W, pady=2) # 进度条 self.progress = ttk.Progressbar(main_frame, mode='indeterminate') self.progress.pack(fill=tk.X, pady=(0, 15)) # 操作按钮区域 btn_frame = ttk.Frame(main_frame) btn_frame.pack(fill=tk.X, pady=(0, 10)) self.process_btn = ttk.Button(btn_frame, text="开始替换", command=self.start_process, width=15) self.process_btn.pack(side=tk.LEFT, padx=(0, 10)) self.save_btn = ttk.Button(btn_frame, text="另存为...", command=self.save_as, width=15, state='disabled') self.save_btn.pack(side=tk.LEFT) # 状态栏 self.status_var = tk.StringVar() self.status_var.set("就绪 - 请选择Word文件") status_label = ttk.Label(main_frame, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W, padding=(5, 2)) status_label.pack(fill=tk.X, pady=(10, 0)) # 存储处理后的文档 self.processed_doc = None self.original_path = None self.output_path = None def select_file(self): """选择Word文件""" file_path = filedialog.askopenfilename( title="选择Word文档", filetypes=[("Word文档", "*.docx"), ("所有文件", "*.*")] ) if file_path: self.file_path_var.set(file_path) self.original_path = file_path self.processed_doc = None self.output_path = None self.save_btn.config(state='disabled') self.status_var.set(f"已选择: {os.path.basename(file_path)}") def start_process(self): """开始处理文档""" if not self.original_path: messagebox.showwarning("警告", "请先选择一个Word文件!") return # 检查文件是否存在 if not os.path.exists(self.original_path): messagebox.showerror("错误", "文件不存在,请重新选择!") return # 检查是否至少选择了一个替换选项 if not self.replace_month_var.get() and not self.replace_day_var.get(): messagebox.showwarning("警告", "请至少选择一种替换选项!") return # 禁用按钮 self.process_btn.config(state='disabled') self.save_btn.config(state='disabled') self.progress.start(10) self.status_var.set("正在处理文档...") # 在新线程中处理 thread = threading.Thread(target=self.process_document) thread.daemon = True thread.start() def process_document(self): """处理文档的核心逻辑""" try: # 加载文档 doc = Document(self.original_path) replace_count = 0 # 遍历所有段落 for paragraph in doc.paragraphs: text = paragraph.text modified = False # 替换月份 if self.replace_month_var.get() and "xx月" in text: text = text.replace("xx月", "07月") modified = True replace_count += 1 # 替换日期 if self.replace_day_var.get() and "xx日" in text: text = text.replace("xx日", "08日") modified = True replace_count += 1 # 如果段落被修改,更新内容 if modified: # 保留原有格式 paragraph.clear() paragraph.add_run(text) # 遍历所有表格中的单元格 for table in doc.tables: for row in table.rows: for cell in row.cells: for paragraph in cell.paragraphs: text = paragraph.text modified = False if self.replace_month_var.get() and "xx月" in text: text = text.replace("xx月", "07月") modified = True replace_count += 1 if self.replace_day_var.get() and "xx日" in text: text = text.replace("xx日", "08日") modified = True replace_count += 1 if modified: paragraph.clear() paragraph.add_run(text) # 保存处理后的文档 self.processed_doc = doc self.replace_count = replace_count # 更新UI self.root.after(0, self.process_complete, replace_count) except Exception as e: self.root.after(0, self.process_error, str(e)) def process_complete(self, count): """处理完成回调""" self.progress.stop() self.process_btn.config(state='normal') self.save_btn.config(state='normal') if count > 0: self.status_var.set(f"处理完成!共替换 {count} 处") messagebox.showinfo("成功", f"文档处理完成!\n共进行了 {count} 处替换。\n请点击'另存为...'保存文件。") else: self.status_var.set("处理完成!未找到需要替换的内容") messagebox.showinfo("提示", "未找到需要替换的 'xx月' 或 'xx日' 内容。") def process_error(self, error_msg): """处理错误回调""" self.progress.stop() self.process_btn.config(state='normal') self.save_btn.config(state='disabled') self.status_var.set(f"错误: {error_msg}") messagebox.showerror("错误", f"处理文档时出错:\n{error_msg}") def save_as(self): """另存为功能""" if not self.processed_doc: messagebox.showwarning("警告", "请先处理文档!") return # 生成默认文件名 base_name = os.path.splitext(os.path.basename(self.original_path))[0] default_name = f"{base_name}_替换后.docx" save_path = filedialog.asksaveasfilename( title="保存文档", defaultextension=".docx", filetypes=[("Word文档", "*.docx"), ("所有文件", "*.*")], initialfile=default_name ) if save_path: try: self.processed_doc.save(save_path) self.output_path = save_path self.status_var.set(f"已保存: {os.path.basename(save_path)}") messagebox.showinfo("成功", f"文档已保存到:\n{save_path}") except Exception as e: messagebox.showerror("错误", f"保存文件时出错:\n{e}") def main(): root = tk.Tk() app = WordReplacerApp(root) root.mainloop() if __name__ == "__main__": main()