- Added detailed logging functionality to init_full_sync.py and run_incremental_sync.py for better tracking of synchronization processes. - Updated configuration mappings in config.py to include additional Access database tables. - Improved error handling and user feedback in vbareplace.py, including the ability to refresh linked tables in Access. - Adjusted polling intervals and batch sizes for performance optimization.
128 lines
4.5 KiB
Python
128 lines
4.5 KiB
Python
import os
|
||
import sys
|
||
import win32com.client
|
||
import tkinter as tk
|
||
from tkinter import messagebox
|
||
|
||
# 隐藏 tkinter 主窗口
|
||
root = tk.Tk()
|
||
root.withdraw()
|
||
|
||
def main():
|
||
# 检查是否通过拖拽传入文件
|
||
if len(sys.argv) != 2:
|
||
messagebox.showerror("错误", "请将一个 Access 数据库文件拖拽到此 EXE 上运行!")
|
||
return
|
||
|
||
access_file = sys.argv[1]
|
||
|
||
# 检查文件是否存在且是 Access 文件
|
||
if not os.path.exists(access_file):
|
||
messagebox.showerror("错误", f"文件不存在:\n{access_file}")
|
||
return
|
||
|
||
ext = os.path.splitext(access_file)[1].lower()
|
||
if ext not in ['.accdb', '.mdb']:
|
||
messagebox.showwarning("警告", "这不是一个 Access 数据库文件(.accdb 或 .mdb)\n将尝试继续,但可能失败。")
|
||
|
||
# 获取脚本所在目录(EXE 同目录)
|
||
if getattr(sys, 'frozen', False):
|
||
script_dir = os.path.dirname(sys.executable)
|
||
else:
|
||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||
|
||
vba_txt_file = os.path.join(script_dir, "vba.txt")
|
||
|
||
if not os.path.exists(vba_txt_file):
|
||
messagebox.showerror("错误", f"未找到 vba.txt 文件!\n请确保 vba.txt 与 EXE 在同一目录。\n路径: {vba_txt_file}")
|
||
return
|
||
|
||
# 读取新 VBA 代码
|
||
try:
|
||
with open(vba_txt_file, "r", encoding="utf-8") as f:
|
||
new_code = f.read()
|
||
except Exception as e:
|
||
messagebox.showerror("错误", f"读取 vba.txt 失败:\n{e}")
|
||
return
|
||
|
||
try:
|
||
# 启动 Access(使用 DispatchEx 强制创建新实例,避免与已打开的 Access 冲突)
|
||
access = win32com.client.DispatchEx("Access.Application")
|
||
access.Visible = False # 后台运行,不显示窗口
|
||
|
||
# 打开数据库
|
||
access.OpenCurrentDatabase(access_file)
|
||
|
||
all_forms = access.CurrentProject.AllForms
|
||
form_count = all_forms.Count
|
||
|
||
if form_count == 0:
|
||
messagebox.showinfo("完成", "数据库中没有窗体,无需替换。")
|
||
access.CloseCurrentDatabase()
|
||
access.Quit()
|
||
return
|
||
|
||
replaced = 0
|
||
for i in range(form_count):
|
||
form_name = all_forms.Item(i).Name
|
||
|
||
try:
|
||
access.DoCmd.OpenForm(form_name, 1) # acDesign = 1
|
||
form = access.Forms(form_name)
|
||
module = form.Module
|
||
|
||
line_count = module.CountOfLines
|
||
if line_count > 0:
|
||
module.DeleteLines(1, line_count)
|
||
|
||
if new_code.strip():
|
||
module.InsertLines(1, new_code)
|
||
|
||
access.DoCmd.Close(0, form_name, 1) # acForm=0, acSaveYes=1
|
||
replaced += 1
|
||
except Exception as e:
|
||
access.DoCmd.Close(0, form_name, 0) # 尝试关闭,避免卡住
|
||
print(f"处理窗体 {form_name} 时出错: {e}")
|
||
|
||
# 刷新所有链接表
|
||
refreshed_tables = 0
|
||
failed_tables = 0
|
||
try:
|
||
db = access.CurrentDb()
|
||
table_count = db.TableDefs.Count
|
||
|
||
for i in range(table_count):
|
||
table_def = db.TableDefs(i)
|
||
# 检查是否是链接表(Connect属性不为空)
|
||
if table_def.Connect:
|
||
try:
|
||
table_def.RefreshLink()
|
||
print(f"已刷新链接表: {table_def.Name}")
|
||
refreshed_tables += 1
|
||
except Exception as e:
|
||
print(f"刷新链接表 {table_def.Name} 失败: {e}")
|
||
failed_tables += 1
|
||
except Exception as e:
|
||
print(f"刷新链接表时出错: {e}")
|
||
|
||
access.CloseCurrentDatabase()
|
||
access.Quit()
|
||
|
||
# 构建结果消息
|
||
result_msg = f"操作完成!\n\n"
|
||
result_msg += f"已处理 {form_count} 个窗体,成功替换 {replaced} 个。\n"
|
||
if refreshed_tables > 0 or failed_tables > 0:
|
||
result_msg += f"已刷新 {refreshed_tables} 个链接表"
|
||
if failed_tables > 0:
|
||
result_msg += f",{failed_tables} 个失败"
|
||
result_msg += "。\n"
|
||
result_msg += f"\n文件已保存: {os.path.basename(access_file)}"
|
||
|
||
messagebox.showinfo("成功", result_msg)
|
||
|
||
except Exception as e:
|
||
messagebox.showerror("运行错误", f"操作失败:\n{e}\n\n请检查是否已启用 VBA 项目访问信任。")
|
||
|
||
if __name__ == "__main__":
|
||
main()
|
||
# pyinstaller --onefile --noconsole --name "VBA代码批量替换" vbareplace.py |