当点击执行第三行按钮"执行宏命令分析"后禁用按钮直到百分比标签显示为100%时再启用按钮:import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import os
import win32com.client as win32
import time
from datetime import datetime
import threading
import re
class VBAExecutorApp:
def __init__(self, root):
self.root = root
self.root.title("WPS Excel宏执行器")
self.root.geometry("600x280") # 减小整体高度
self.root.resizable(True, True)
# 创建自定义样式
self.style = ttk.Style()
# 配置按钮正常状态样式"Run.TButton"
self.style.configure("Run.TButton",
foreground="white",
background="#4CAF50", # 绿色背景
font=("Arial", 10, "bold"),
padding=6)
# 配置按钮禁用状态样式"Run.TButton"
self.style.map("Run.TButton",
foreground=[('disabled', 'gray')],
background=[('disabled', '#CCCCCC')]) # 灰色背景
# 创建网格布局
self.root.columnconfigure((0, 1, 2), weight=1)
self.root.rowconfigure((0, 1, 2), weight=1)
# 第一行标题
self.create_label("日志文件选择:", 0, 0, "黑体", 12) # 减小字体大小
self.create_label("分析模块选择:", 0, 1, "黑体", 12)
self.create_label("宏主程序读取:", 0, 2, "黑体", 12)
# 第二行文件选择
self.excel_path = tk.StringVar()
self.bas_path = tk.StringVar()
self.create_file_entry(1, 0, self.excel_path, [("Excel文件", "*.xls *.xlsx")])
self.create_file_entry(1, 1, self.bas_path, [("BAS文件", "*.bas")])
# 宏函数下拉框 - 使用更紧凑的样式
self.macro_var = tk.StringVar()
self.macro_combobox = ttk.Combobox(
self.root,
textvariable=self.macro_var,
state="readonly",
height=8 # 下拉列表高度
)
self.macro_combobox.grid(row=1, column=2, padx=5, pady=2, sticky="ew") # 减小填充
# 第三行按钮
self.run_button = ttk.Button(
self.root,
text="执行宏命令分析",
command=self.start_execution,
width=22,
style="Run.TButton" # 应用自定义样式"Run.TButton"
)
self.run_button.grid(row=2, column=0,ipadx=0,ipady=0,padx=5, pady=(5,10), sticky="w")
# 添加悬停效果绑定
self.run_button.bind("<Enter>", self.on_enter)
self.run_button.bind("<Leave>", self.on_leave)
# 添加按下效果绑定
self.run_button.bind("<ButtonPress-1>", self.on_press)
self.run_button.bind("<ButtonRelease-1>", self.on_release)
# 创建水平对齐的容器
progress_container = ttk.Frame(self.root)
progress_container.grid(row=2, column=1, columnspan=2, padx=5, pady=0, sticky="ew")
progress_container.columnconfigure(0, weight=1) # 进度条列可扩展
progress_container.columnconfigure(1, weight=0) # 百分比标签列固定宽度
# 进度条 - 放在左侧
self.progress_var = tk.DoubleVar()
self.progress_bar = ttk.Progressbar(
progress_container,
variable=self.progress_var,
maximum=100,
mode="determinate",
style="Compact.Horizontal.TProgressbar",
length=200 # 可以调整进度条长度
)
self.progress_bar.grid(row=0, column=0, padx=(0, 5), sticky="ew") # 右侧留出间距
# 百分比标签 - 放在右侧
self.percent_label = ttk.Label(
progress_container,
text="0%",
font=("Arial", 11),
width=5 # 固定宽度确保对齐
)
self.percent_label.grid(row=0, column=1, sticky="e")
# 绑定事件
self.bas_path.trace_add("write", self.parse_bas_file)
self.progress_var.trace_add("write", self.update_percent_label)
def update_percent_label(self, *args):
"""更新百分比标签显示"""
progress_value = self.progress_var.get()
self.percent_label.config(text=f"{int(progress_value)}%")
# 根据进度改变标签颜色
if progress_value < 30:
self.percent_label.config(foreground="red")
elif progress_value < 70:
self.percent_label.config(foreground="orange")
else:
self.percent_label.config(foreground="green")
def create_label(self, text, row, column, font, size):
label = tk.Label(
self.root, text=text,
font=(font, size), anchor="w"
)
label.grid(row=row, column=column, padx=5, pady=(20,0), sticky="w") # 减小填充
return label
def create_file_entry(self, row, column, text_var, filetypes):
frame = ttk.Frame(self.root)
frame.grid(row=row, column=column, padx=5, pady=2, sticky="ew") # 减小填充
frame.columnconfigure(1, weight=1)
entry = ttk.Entry(frame, textvariable=text_var)
entry.grid(row=0, column=0, sticky="ew", padx=(0, 2)) # 减小间距
browse = ttk.Button(frame, text="浏览", command=lambda: self.browse_file(text_var, filetypes))
browse.grid(row=0, column=1, padx=(0, 0))
def browse_file(self, text_var, filetypes):
file_path = filedialog.askopenfilename(filetypes=filetypes)
if file_path:
text_var.set(file_path)
def parse_bas_file(self, *args):
bas_path = self.bas_path.get()
if not bas_path or not os.path.exists(bas_path):
return
try:
# 使用UTF-8和GBK尝试解码,处理中文字符
try:
with open(bas_path, "r", encoding="utf-8") as f:
content = f.read()
except UnicodeDecodeError:
with open(bas_path, "r", encoding="gbk") as f:
content = f.read()
# 使用正则表达式查找Main_开头的宏函数
macro_pattern = r"Sub\s+(Main_\w+)\s*\(\)"
macros = re.findall(macro_pattern, content)
if macros:
self.macro_combobox["values"] = macros
if self.macro_combobox["values"]:
self.macro_combobox.current(0)
except Exception as e:
messagebox.showerror("错误", f"解析BAS文件失败: {str(e)}")
def start_execution(self): #按钮点击事件处理函数
if not self.excel_path.get() or not self.bas_path.get():
messagebox.showerror("错误", "请先选择需要分析的文件或宏模块")
return
# 禁用按钮防止重复点击
self.run_button.config(state=tk.DISABLED)
# 模拟执行过程
print("开始执行宏命令分析...")
self.root.after(5000, self.enable_button) # 5秒后启用按钮
# 在后台线程中执行以避免UI冻结
threading.Thread(target=self.execute_macro, daemon=True).start()
def enable_button(self):
"""启用按钮"""
self.run_button.config(state=tk.NORMAL)
print("执行完成!")
def on_enter(self, event):
"""鼠标悬停效果"""
self.style.configure("Run.TButton", background="#45a049") # 深绿色
def on_leave(self, event):
"""鼠标离开效果"""
self.style.configure("Run.TButton", background="#4CAF50") # 恢复原绿色
def on_press(self, event):
"""按钮按下效果"""
self.style.configure("Run.TButton", background="#2E7D32") # 更深的绿色
def on_release(self, event):
"""按钮释放效果"""
self.style.configure("Run.TButton", background="#45a049") # 悬停状态的绿色
def execute_macro(self):
try:
self.run_button["state"] = "disabled"
self.progress_var.set(0)
# 初始化WPS Excel
excel = win32.gencache.EnsureDispatch("Excel.Application")
excel.Visible = False # 后台运行
excel.DisplayAlerts = False
# 打开Excel文件
wb = excel.Workbooks.Open(os.path.abspath(self.excel_path.get()))
self.update_progress(20)
# 导入BAS文件
vb_project = wb.VBProject
vb_project.VBComponents.Import(os.path.abspath(self.bas_path.get()))
self.update_progress(40)
# 执行宏
macro_name = self.macro_var.get()
excel.Application.Run(macro_name)
self.update_progress(70)
time.sleep(1) # 模拟执行时间
# 另存为新文件
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
save_path = filedialog.asksaveasfilename(
defaultextension=".xlsx",
filetypes=[("Excel文件", "*.xlsx"), ("Excel 97-2003", "*.xls")],
initialfile=f"result_{timestamp}"
)
if save_path:
wb.SaveAs(save_path)
self.update_progress(90)
messagebox.showinfo("成功", f"文件已保存至: {save_path}")
wb.Close(False)
excel.Quit()
self.update_progress(100)
except Exception as e:
messagebox.showerror("执行错误", f"宏执行失败: {str(e)}")
finally:
self.run_button["state"] = "normal"
def update_progress(self, value):
"""更新进度条值并刷新界面"""
self.progress_var.set(value)
self.root.update_idletasks()
if __name__ == "__main__":
root = tk.Tk()
app = VBAExecutorApp(root)
root.mainloop()