如何通过Python强制生成EA图元InstanceGUID以启用自定义绘图样式?
问题
我正在使用Python调用Sparx Enterprise Architect (EA) API,希望为图中的部分图元设置“启用自定义绘图样式”。该配置信息(是否勾选“启用自定义绘图样式”)存储在图的StyleEx属性中,格式为"OPTIONS_(8位DUID)=CDS=1:;",其中DUID对应图元的InstanceGUID。
当能获取到图元的InstanceGUID时,将其写入图的StyleEx即可实现设置,但部分场景下图元的InstanceGUID为空,且图的StyleEx也为空。执行以下代码尝试刷新保存后,仍无法获取到InstanceGUID和StyleEx:
diag = EARepo.GetDiagramByGUID("{diagram_GUID}") for diagObj in diag.DiagramObjects: print(diagObj.InstanceGUID) >>> only empty strings print(diag.StyleEx) >>> also empty string EARepo.SaveDiagram(diag.DiagramID) diag.Update() for diagObj in diag.DiagramObjects: diagObj.Update() diag.DiagramObjects.Refresh() diag.Update() EARepo.SaveDiagram(diag.DiagramID)
同时通过SQLQuery查询也无法获取InstanceGUID或DUID,仅能得到InstanceID但无法用于此配置。手动在EA中修改并保存图时,系统会自动生成InstanceGUID,但脚本操作无法实现。
请问是否有办法通过脚本强制EA为图元生成InstanceGUID?或是有其他方式设置“启用自定义绘图样式”?
解决方案
方法1:微调图元位置触发InstanceGUID生成
EA的InstanceGUID通常在图元被修改并保存后自动生成,你可以通过对空InstanceGUID的图元做微小位置调整,触发EA的修改标记,保存后即可生成GUID:
diag = EARepo.GetDiagramByGUID("{diagram_GUID}") # 遍历图元,微调位置触发修改 for diagObj in diag.DiagramObjects: if not diagObj.InstanceGUID: # 微小调整X坐标,再改回原位置 diagObj.Left = diagObj.Left + 1 diagObj.Left = diagObj.Left - 1 diagObj.Update() # 保存并刷新图 EARepo.SaveDiagram(diag.DiagramID) diag.Refresh() # 重新获取图,此时可读取InstanceGUID diag = EARepo.GetDiagramByGUID("{diagram_GUID}") for diagObj in diag.DiagramObjects: print(diagObj.InstanceGUID)
生成GUID后,就可以正常拼接StyleEx内容来启用自定义绘图样式。
方法2:手动生成GUID并关联数据库(谨慎使用)
如果方法1无效,可自行生成符合EA格式的GUID,手动写入图元对象并更新数据库:
注意:直接操作数据库有数据损坏风险,建议先备份模型,仅在测试环境验证后使用。
import uuid diag = EARepo.GetDiagramByGUID("{diagram_GUID}") diagram_id = diag.DiagramID # 遍历图元,生成并设置InstanceGUID for diagObj in diag.DiagramObjects: if not diagObj.InstanceGUID: # 生成符合EA格式的GUID(大写带大括号) new_guid = "{" + str(uuid.uuid4()).upper() + "}" diagObj.InstanceGUID = new_guid diagObj.Update() # 通过SQL更新数据库表 sql = f"""UPDATE t_diagramobjects SET InstanceGUID = '{new_guid}' WHERE Diagram_ID = {diagram_id} AND InstanceID = {diagObj.InstanceID}""" EARepo.SQLQuery(sql) # 保存图并设置StyleEx EARepo.SaveDiagram(diagram_id) diag.Refresh() style_ex_parts = [] for diagObj in diag.DiagramObjects: if diagObj.InstanceGUID: duid = diagObj.InstanceGUID[1:9] # 提取GUID前8位作为DUID style_ex_parts.append(f"OPTIONS_{duid}=CDS=1:;") diag.StyleEx = "".join(style_ex_parts) diag.Update() EARepo.SaveDiagram(diagram_id)
方法3:间接调用EA内部命令(通过VBScript)
Python无法直接调用EA的内部编辑命令,但可以生成临时VBS脚本执行,触发图元GUID生成:
import os # 生成VBS脚本内容 vbs_content = f""" Set repo = CreateObject("EA.Repository") repo.OpenFile("你的EA模型完整路径.eapx") Set diag = repo.GetDiagramByGUID("{diagram_GUID}") For Each dobj In diag.DiagramObjects If dobj.InstanceGUID = "" Then ' 微调位置触发修改 dobj.Left = dobj.Left + 1 dobj.Left = dobj.Left - 1 dobj.Update() End If Next repo.SaveDiagram(diag.DiagramID) repo.CloseFile() """ # 保存并执行VBS脚本 with open("generate_guid.vbs", "w") as f: f.write(vbs_content) os.system("cscript generate_guid.vbs") os.remove("generate_guid.vbs") # 回到Python继续处理StyleEx设置 diag = EARepo.GetDiagramByGUID("{diagram_GUID}") # 后续操作同方法1
内容的提问来源于stack exchange,提问作者janowm

