| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- 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()
|