V6 CAA 开放接口供 VBA 调用开发指南
作者:CATIA开发者指南
发布时间:2026年5月27日 12:01
原文链接:https://mp.weixin.qq.com/s?__biz=MzkxNTQ0MTY0NQ==&mid=2247486486&idx=1&sn=139020898266c4bf9c194f00b8c48bf9&chksm=c15e5e94f629d782fbeaf84536ee45886c5578ee5065e3da2f93746148e8a2e9be78a7fb063e&cur_album_id=2800898825187262468&scene=189#wechat_redirect
本文面向说明如何把 CAA 能力封装成 VBA 可调用的 Automation 接口。
VBA 不能直接调用任意 CAA C++ 接口。VBA 能调用的是 COM Automation / TypeLib 中声明过、运行时能够从 V6 对象上取得的脚本接口。因此开发主线不是“把一个 C++ 头文件给 VBA 引用”,而是:
- 先用 CAA C++ 实现业务能力。
- 再用 IDL 定义 VBA 可见的 Automation 接口。
- 通过 TypeLib 交付给 VBA 做早绑定或晚绑定。
- 在 V6 对象模型中提供获取入口,例如对象的
GetItem("接口名")、工厂接口、应用服务或命令入口。 - 在 3DEXPERIENCE 会话、PLM 上下文和权限边界内调用。
安装库里可以看到这条链路的典型证据:
- CAADoc/CAASystem.edu/PublicInterfaces/CAAIASysSprocket.idl 使用
#pragma DUAL和#pragma ALIAS定义 VBA 可见对象。 - CAADoc/CAASystem.edu/CAASysAutomationImpl.m/src/CAASysSprocketImpl.cpp 用
TIE_CAAIASysSprocket把 C++ 实现绑定到 Automation 接口。 - CAADoc/CAASystem.edu/PrivateInterfaces/CAASysTypeLib.h 把多个 IDL include 到一个 TypeLib 中。
- CAADoc/CAASystem.edu/CAASysTypeLib.m/Imakefile.mk 声明
BUILT_OBJECT_TYPE = TYPELIB。 - win_b64/startup/DELMIAResourcesScriptSamples/SampleRscMotionControllerVBA.txt、win_b64/startup/DELMIAResourcesScriptSamples/SampleRscSimulationVBA.txt 等脚本展示了 V6 VBA 中常见的
ActiveEditor、VPMOccurrence、GetItem("CAARsc...")调用模式。
1. 推荐总体架构
建议把系统分成三层,不要让 VBA 直接承受 CAA 模型复杂度。
VBA / CATScript
|
| COM Automation TypeLib, dual interface, BSTR, VARIANT, SAFEARRAY
v
Automation Adapter CAA 模块
|
| 参数校验、类型转换、错误码整理、事务/Update/Session 控制
v
核心 CAA 业务服务
|
| FeatureModeler、Drafting、Part、Product、PLM、Update、Delete 等 CAA API
v
V6 PLM Session / Editor / Representation / Feature / Occurrence
这样做有几个好处:
- VBA 只看到简单对象、字符串、数值、数组和脚本对象。
- CAA 侧可以继续使用
CATBaseUnknown、CATUnicodeString、CATLISTV、CATFmFeatureFacade、CATIPLMUpdateEngine等原生类型。 - 出错时由 CAA 侧返回稳定的
HRESULT和可读错误信息,不把内部崩溃边界暴露给 VBA。 - 以后如果把入口从 VBA 换成 EKL、命令、批处理或 Web 服务,核心业务服务仍可复用。
2. 第一步:确定哪些 CAA 能力适合开放给 VBA
先不要急着写 IDL。建议先整理一个接口清单,把能力分为三类。
第一类是适合开放给 VBA 的能力:
- 查询对象名称、属性、状态、数量、路径、业务编号。
- 创建或修改有限范围内的业务对象。
- 对当前选择对象执行一个封装好的业务动作。
- 返回报表数据、检查结果、失败原因。
第二类要谨慎开放:
- 触发全局 update、保存、删除、替换、加载 3D 数据。
- 需要 PLM 权限、锁定、生命周期状态或协同上下文的操作。
- 可能造成模型待更新、报红或交互命令状态变化的读取接口。
第三类不建议直接开放:
- 原始 CAA 指针、内部 container、StartUp、feature 私有属性。
- 任意
QueryInterface能力。 - 要求调用方管理
AddRef/Release的对象。 - 对多线程、跨文档、跨 session 敏感的底层 API。
在 V6 里,尤其要先定义清楚对象上下文:接口是作用在当前 ActiveEditor.ActiveObject,还是当前选择集,还是一个 PLM representation,还是一个 VPMOccurrence。这个决定后续 VBA 的入口设计。
3. 第二步:设计 VBA 友好的对象模型
VBA 适合的接口风格和 C++ 不一样。建议遵守这些规则。
3.1 类型选择
VBA 可见接口优先使用:
BSTR / CATBSTR:字符串。long、int、double、boolean:基础值。VARIANT / CATVariant:可变索引、可选参数、返回 mixed 类型。SAFEARRAY(VARIANT)/ CATSafeArrayVariant:数组。- 继承自
CATIABase或CATIACollection的 Automation 对象。
避免把下面这些类型放进 IDL:
CATUnicodeString。CATLISTV(...) / CATLISTP(...)。CATBaseUnknown* 之类的裸 CAA 指针。- 非 Automation 的业务接口。
- 需要 C++ 模板或 CAA 容器才能理解的类型。
3.2 方法粒度
VBA 接口不要设计成底层 API 的一对一镜像。更好的方式是把一组 CAA 调用封装成一个业务动作。
例如不要暴露:
GetContainer
GetStartUp
InstantiateFeature
SetAttributeA
SetAttributeB
RunUpdate
更建议暴露:
CreateCheckSet(name, ruleId) As CheckSet
RunDrawingCheck() As CheckReport
ExportCheckItems() As Variant
这样 VBA 侧少犯错,CAA 侧也能统一处理事务、update、权限和错误恢复。
4. 第三步:编写 Automation IDL
V6/CAA 的 Automation 接口通常用 IDL 定义。以 CAADoc 中的 CAAIASysSprocket.idl 为参考,一个最小接口可以这样设计。
#ifndef MyCompanyIAFeatureInspector_idl
#define MyCompanyIAFeatureInspector_idl
#include "CATIABase.idl"
#include "CATVariant.idl"
#include "CATSafeArray.idl"
/**
* VBA-visible feature inspection service.
*/
interface MyCompanyIAFeatureInspector : CATIABase
{
HRESULT GetName(out /*IDLRETVAL*/ CATBSTR oName);
HRESULT GetStatus(out /*IDLRETVAL*/ CATBSTR oStatus);
HRESULT ExportProperties(out /*IDLRETVAL*/ CATSafeArrayVariant oProperties);
};
#pragma ID MyCompanyIAFeatureInspector "DCE:PUT-YOUR-INTERFACE-GUID-HERE"
#pragma DUAL MyCompanyIAFeatureInspector
// Object name visible from VBA Object Browser.
#pragma ID MyCompanyFeatureInspector "DCE:PUT-YOUR-VB-ALIAS-GUID-HERE"
#pragma ALIAS MyCompanyIAFeatureInspector MyCompanyFeatureInspector
#endif
关键点如下:
CATIABase.idl 是常见 Automation 基类入口。#pragma DUAL 表示生成 dual interface,VBA 可以早绑定,也可以通过 IDispatch 晚绑定。#pragma ALIAS 定义 VBA 里看到的对象名。- 每个接口和对象 alias 都要有稳定 GUID。发布后不要随意改 GUID,否则旧 VBA 引用会断。
- 返回值统一用
HRESULT,真正的 VBA 返回值通过out /*IDLRETVAL*/给出。
如果要做集合对象,建议继承 CATIACollection,并实现 Count、Item、_NewEnum 和 ToArray。CAADoc 中 CAAIASysSprockets.idl 就是很好的参考。
5. 第四步:实现 C++ Automation Adapter
IDL 只定义 VBA 能看到什么,真正工作要由 C++ 类实现。典型结构如下:
#include"MyCompanyFeatureInspectorImpl.h"
CATImplementClass(MyCompanyFeatureInspectorImpl,
Implementation,
CATBaseUnknown,
CATnull);
#include"TIE_MyCompanyIAFeatureInspector.h"
TIE_MyCompanyIAFeatureInspector(MyCompanyFeatureInspectorImpl);
实现类建议继承 CATBaseObject 或项目中已有的 Automation 基类,然后实现 IDL 中声明的方法。
HRESULT MyCompanyFeatureInspectorImpl::GetName(CATBSTR& oName)
{
oName = NULL;
CATUnicodeString name;
HRESULT hr = _service->GetBusinessName(_spTarget, name);
if (FAILED(hr))
{
return hr;
}
name.ConvertToBSTR(&oName);
return S_OK;
}
这里有几个工程规则很重要:
- 进入方法先校验对象上下文,例如 editor、selection、representation、feature 是否仍有效。
- CAA 业务异常不要直接穿透给 VBA,转换成
HRESULT和可读错误信息。 - 所有返回给 VBA 的字符串用 BSTR,数组用 SAFEARRAY。
- 返回 Automation 对象时遵守 COM 引用计数,返回前确保对象已经
AddRef或通过QueryInterface取得。 - 不要把内部对象指针缓存到跨 session、跨文档或跨 editor 的长生命周期对象中。
CAADoc 中的 CAASysSprocketImpl.cpp 使用了一个典型模式:创建实现对象,然后 QueryInterface(IID_CAAIASysSprocket, ...),最后释放实现对象自身引用,让返回接口持有正确引用计数。
6. 第五步:处理集合、数组和枚举
VBA 用户非常依赖数组和 For Each。如果接口要返回多对象,建议提供两种形式。
一种是集合对象:
Dim items As MyCompanyCheckItems
Set items = inspector.CheckItems
Dim item As MyCompanyCheckItem
ForEach item In items
Debug.Print item.Name
Next
另一种是数组:
Dim values As Variant
values = inspector.ExportProperties()
C++ 侧可以参考 CAASysSprocketsImpl.cpp 的做法:
get_Count 返回集合数量。Item(CATVariant index, ...) 支持数字索引、名称或对象本身。get__NewEnum 用 CATCreateIEnumVARIANT 创建枚举器。ToArray / 返回数组时使用 CATSafeArrayVariant 和转换工具。
集合索引要特别注意:CATIA Automation 传统上常用 1-based index,而 VBA 数组通常根据声明可能是 0-based 或 1-based。建议在文档和错误信息里写清楚。
7. 第六步:提供 VBA 获取入口
接口实现好了,还必须让 VBA 能拿到对象。V6 中常见有三种入口。
7.1 挂在业务对象上的 GetItem 入口
当前安装库中的 DELMIA 资源脚本大量使用这种方式:
Dim mainResource As Variant
Set mainResource = CATIA.ActiveEditor.ActiveObject
Dim motion As RscMotionController
Set motion = mainResource.GetItem("CAARscMotionController")
这说明目标对象本身支持按名称取得某个 Automation 接口或服务对象。你的自定义能力如果是“某类对象上的扩展能力”,也可以采用类似模式:
Dim inspector As MyCompanyFeatureInspector
Set inspector = selectedObject.GetItem("MyCompanyFeatureInspector")
适用场景:
- 能力天然依附在某个 VPM occurrence、feature、resource 或 representation 上。
- VBA 用户从当前选择或 active object 出发。
- 接口生命周期不应超过宿主对象。
7.2 工厂或管理器入口
如果能力不是某个对象的固定扩展,而是一个全局服务,可以提供工厂对象。
Dim service As MyCompanyAutomationService
Set service = CATIA.GetItem("MyCompanyAutomationService")
Dim report As MyCompanyCheckReport
Set report = service.CheckActiveEditor()
实际能否直接挂到 CATIA、ActiveEditor 或某个 manager 上,要看你所在应用框架是否提供对应扩展点。没有官方扩展点时,不要硬模拟内部对象结构,宁可通过命令或选中对象入口暴露。
7.3 命令入口加对象入口
交互式场景可以提供一个 CAA 命令用于准备上下文,然后由 VBA 调用 Automation 对象处理结果。例如命令负责让用户选择、加载数据、打开 editor,Automation 接口只做稳定的数据读写。
注意:CATIA.StartCommand 只适合已验证的前台交互命令,不适合作为无人值守批处理主链路。V6 的命令常涉及 editor、选择集、确认框和 PLM 上下文,VBA 直接启动命令很难保证可重复性。
8. 第七步:创建 TypeLib 模块
VBA 早绑定需要 TypeLib。CAA 示例里有一个专门的 TypeLib 模块。
TypeLib 聚合头文件示例:
#ifndef MyCompanyTypeLib_tplib
#define MyCompanyTypeLib_tplib
#pragma REPID MyCompanyTypeLib "DCE:PUT-YOUR-TYPELIB-GUID-HERE"
#pragma REPBEGIN MyCompanyTypeLib
// 如果依赖已有 Automation 类型库,可在这里声明依赖。
//#pragma REPREQ InfTypeLib
#include"MyCompanyIAFeatureInspector.idl"
#include"MyCompanyIACheckReport.idl"
#include"MyCompanyIACheckItems.idl"
#pragma REPEND MyCompanyTypeLib
#endif
对应 Imakefile.mk:
BUILT_OBJECT_TYPE = TYPELIB
LINK_WITH = InfTypeLib
构建后应生成类似 MyCompanyTypeLib.tlb 的文件。部署时要保证:
.tlb位于运行环境可找到的位置,通常随 runtime view 或交付包进入code/bin一类目录。- 依赖的 Dassault Systemes TypeLib 已存在,例如当前安装库中已有 win_b64/code/bin/CATIAAppTypeLib.tlb、win_b64/code/bin/InfTypeLib.tlb、win_b64/code/bin/PartTypeLib.tlb、win_b64/code/bin/ProductStructureClientIDLTypeLib.tlb 等。
- Windows 上需要时注册 TypeLib,或让 V6 自动化前置条件流程处理注册。AutomationInterfaces/PublicInterfaces/CATScriptUtilities.h 中可以看到
LoadTypeLibs、RegisterTypeLibs、UnregisterTypeLibs这类基础能力。
9. 第八步:构建、部署与运行时路径
一个最小交付通常包含两个模块:
MyCompanyAutomationItf.m # IDL / generated headers / interface package
MyCompanyAutomationImpl.m # C++ implementation shared library
MyCompanyTypeLib.m # TypeLib module
实际项目中还可能有:
MyCompanyFeatureModel.m # 核心 CAA 业务服务
MyCompanyCommands.m # CAA 交互命令
resources/msgcatalog # NLS
resources/graphic # CATfct, icons, UI resources
部署检查项:
- C++ 实现库已经进入 runtime view 的
code/bin。 - TypeLib 已生成并可被 VBA 引用。
- 所有依赖 framework 在运行环境中可加载。
- 如果接口依赖自定义 feature,CATfct、NLS、client id、credentials 配置都已经生效。
- 如果入口来自
GetItem("..."),宿主对象在目标 app/editor 中确实支持该接口获取。 - 在目标 3DEXPERIENCE 会话中验证,不只在编译环境中验证。
10. 第九步:VBA 侧调用方式
10.1 早绑定
早绑定适合正式交付。VBA 工程中添加 TypeLib 引用后,可以写出明确类型。
Sub CATMain()
Dim activeObject As Variant
Set activeObject = CATIA.ActiveEditor.ActiveObject
Dim inspector As MyCompanyFeatureInspector
Set inspector = activeObject.GetItem("MyCompanyFeatureInspector")
If inspector IsNothingThen
MsgBox "Failed to retrieve MyCompanyFeatureInspector"
ExitSub
EndIf
Dim name AsString
name = inspector.GetName()
Dim status AsString
status = inspector.GetStatus()
MsgBox "Name=" & name & vbCrLf & "Status=" & status
EndSub
早绑定优点是对象浏览器可见、自动补全较好、枚举常量可读。缺点是 TypeLib GUID 或版本变动会影响已有 VBA 工程。
10.2 晚绑定
晚绑定适合调试或跨版本兼容。
Sub CATMain()
Dim activeObject As Variant
Set activeObject = CATIA.ActiveEditor.ActiveObject
Dim inspector AsObject
Set inspector = activeObject.GetItem("MyCompanyFeatureInspector")
If inspector IsNothingThen
MsgBox "Inspector is not available in current context"
ExitSub
EndIf
MsgBox inspector.GetStatus()
EndSub
晚绑定不依赖 VBA 工程预先引用 TypeLib,但运行时错误会更晚暴露,枚举常量也需要写成数字或自己定义常量。
11. 第十步:错误处理和诊断
VBA 调 CAA 时,错误处理要比普通宏更严格。
VBA 侧建议写法:
Sub CATMain()
OnErrorGoTo ErrorHandler
Dim activeObject As Variant
Set activeObject = CATIA.ActiveEditor.ActiveObject
Dim inspector AsObject
Set inspector = activeObject.GetItem("MyCompanyFeatureInspector")
If inspector IsNothingThen
Err.Raise vbObjectError + 1000, , "Current object does not support MyCompanyFeatureInspector"
EndIf
MsgBox inspector.GetStatus()
ExitSub
ErrorHandler:
MsgBox "Automation call failed:" & vbCrLf & Err.Description
EndSub
CAA 侧建议做到:
- 对
NULL输入返回E_POINTER或E_INVALIDARG。 - 对当前上下文不支持返回明确错误,不要返回空对象后继续执行。
- 对权限、锁定、生命周期、PLM 加载失败做专门日志。
- 对可能修改模型的接口记录 before/after update 状态。
- 对底层 CAA 崩溃风险较高的能力,做进程隔离或只允许在受控命令中调用。
如果接口可能触发模型更新,建议 CAA 侧封装成完整流程:检查状态、执行动作、运行 update、返回报告。不要让 VBA 分散调用多个底层步骤。
12. V6 与 V5 的重点差异
这一部分最重要,很多 V5 经验在 V6 中只能部分复用。
12.1 应用入口不同
V5 常见入口是:
Set partDoc = CATIA.ActiveDocument
Set part = partDoc.Part
V6 更常见的是从 editor 和 PLM 对象出发:
Set activeObject = CATIA.ActiveEditor.ActiveObject
Set selection = CATIA.ActiveEditor.Selection
V6 的 active object 往往是 PLM / VPM / representation 上下文对象,不一定是 V5 风格的 PartDocument 或 ProductDocument。
12.2 数据模型不同
V5 以文件和 document 为中心,宏经常直接操作 CATPart、CATProduct、DrawingDocument。
V6 以 PLM session、representation、reference/instance、occurrence 和 editor 为中心。很多对象必须在正确 editor、正确 session、正确 representation 加载状态下才有效。
因此 V6 Automation 接口里要少传“文件路径”,多传“当前上下文对象”或从 ActiveEditor 获取上下文。
12.3 TypeLib 不是全部 CAA 能力
V5 用户容易把“Automation API”理解成 CATIA 已经开放的全部宏接口。
V6 里 CAA C++ API、Automation TypeLib、EKL、Web Services、batch API 是不同层次。某个 CAA 头文件存在,不代表 VBA 可以直接调用。只有写进 IDL、生成 TypeLib、实现 TIE、并提供运行时获取入口的能力,才算真正开放给 VBA。
12.4 对象获取方式更依赖 GetItem 和业务接口名
V5 里常见:
Set shapeFactory = part.ShapeFactory
V6 示例中更常见:
Set motion = mainResource.GetItem("CAARscMotionController")
Set simulation = mainResource.GetItem("CAARscSimulation")
也就是说,VBA 往往先拿到一个 PLM/VPM 对象,再按接口名获取具体业务能力。你的自定义接口最好也顺着这个模式设计。
12.5 Update、保存和权限更敏感
V5 宏里常见 Part.Update、Document.Save。
V6 中 update、保存、锁定、权限、成熟度、协同上下文更加复杂。CAA 侧应使用 V6 对应的 update/session/PLM API 做统一控制。VBA 不应直接拼接多个底层动作去赌当前 session 状态。
12.6 交互命令自动化更不稳定
V5 宏里有时会用 CATIA.StartCommand 辅助调用内置命令。V6 中命令通常与 app、editor、selection、dialog、server state 绑定更紧,不建议把 StartCommand 当成核心自动化 API。正式方案应开放业务 Automation 接口,而不是让 VBA 模拟 UI 操作。
12.7 64 位与注册问题更突出
当前安装库是 win_b64,VBA host、TypeLib、COM 注册、CAA runtime 都要保持位数和版本一致。V5 老项目中遗留的 32 位 COM 组件、旧 VB6 ActiveX、旧注册脚本,在 V6 64 位环境下通常需要重新处理。
12.8 自定义特征建议走 OSM + CATfct + Facade
如果开放给 VBA 的能力背后要创建或扩展 V6 自定义 feature,不建议沿用旧式直接构造目录或内部对象的做法。应先用 OSM 定义 StartUp,用 CATfctEditorAssistant 维护 CATfct,再在 CAA 侧用 CATFmCredentials、CATFmStartUpFacade、CATFmFeatureFacade 封装创建和读写,最后给 VBA 一个简洁入口。
13. 开发流程清单
下面是一条推荐落地路径。
- 明确 VBA 使用场景:当前选择、当前 editor、批处理、报表还是建模动作。
- 识别核心 CAA API,并先用 C++ 命令或单元测试验证业务链路。
- 设计 VBA 对象模型,确定接口名、对象名、方法、属性、集合和错误语义。
- 编写 IDL,继承
CATIABase或CATIACollection,使用#pragma DUAL和#pragma ALIAS。 - 为所有接口、alias、typelib 分配稳定 GUID。
- 编写 C++ 实现类,使用
CATImplementClass和TIE_...绑定接口。 - 在实现类中调用核心 CAA 业务服务,完成类型转换、上下文校验、日志和错误处理。
- 对集合实现
Count、Item、_NewEnum、ToArray。 - 提供运行时入口,例如
GetItem("MyCompanyFeatureInspector")、工厂服务或命令准备上下文。 - 创建 TypeLib 聚合头文件和
BUILT_OBJECT_TYPE = TYPELIB模块。 - 构建 interface、implementation、typelib 三类模块。
- 部署 shared library、TypeLib、CATfct、NLS 和依赖资源到 runtime view。
- 在目标 V6 客户端启动后,从 VBA 添加引用并运行最小宏。
- 测试无对象、错误对象、未加载对象、无权限对象、正常对象、大批量对象。
- 固化接口版本,不随意改 GUID 和方法签名。新增能力优先新增方法或新增接口。
14. 最小端到端示例
14.1 IDL
#include "CATIABase.idl"
interface MyCompanyIAHelloService : CATIABase
{
HRESULT SayHello(in CATBSTR iName, out /*IDLRETVAL*/ CATBSTR oMessage);
};
#pragma ID MyCompanyIAHelloService "DCE:11111111-2222-3333-4444-555555555555"
#pragma DUAL MyCompanyIAHelloService
#pragma ID MyCompanyHelloService "DCE:66666666-7777-8888-9999-AAAAAAAAAAAA"
#pragma ALIAS MyCompanyIAHelloService MyCompanyHelloService
14.2 C++ 实现骨架
CATImplementClass(MyCompanyHelloServiceImpl,
Implementation,
CATBaseUnknown,
CATnull);
#include"TIE_MyCompanyIAHelloService.h"
TIE_MyCompanyIAHelloService(MyCompanyHelloServiceImpl);
HRESULT MyCompanyHelloServiceImpl::SayHello(CATBSTR iName, CATBSTR& oMessage)
{
oMessage = NULL;
CATUnicodeString name;
if (iName != NULL)
{
name.BuildFromBSTR(iName);
}
CATUnicodeString message("Hello ");
message += name;
message.ConvertToBSTR(&oMessage);
return S_OK;
}
14.3 TypeLib 聚合
#pragma REPID MyCompanyTypeLib "DCE:BBBBBBBB-CCCC-DDDD-EEEE-FFFFFFFFFFFF"
#pragma REPBEGIN MyCompanyTypeLib
#include"MyCompanyIAHelloService.idl"
#pragma REPEND MyCompanyTypeLib
14.4 VBA 调用
Sub CATMain()
Dim activeObject As Variant
Set activeObject = CATIA.ActiveEditor.ActiveObject
Dim hello AsObject
Set hello = activeObject.GetItem("MyCompanyHelloService")
If hello IsNothingThen
MsgBox "MyCompanyHelloService is not available"
ExitSub
EndIf
MsgBox hello.SayHello("VBA")
EndSub
这个示例只说明调用链。真实项目还需要实现 GetItem("MyCompanyHelloService") 入口,或改成项目中已有的 manager/factory 入口。
15. 测试矩阵
建议至少覆盖这些测试。
| 测试项 | 目标 |
|---|---|
| VBA 早绑定引用 TypeLib | 确认对象浏览器可见、类型名和枚举可见 |
| VBA 晚绑定调用 | 确认无引用时也能通过 IDispatch 调用 |
| 当前 editor 为空 | 返回明确错误,不崩溃 |
| 当前对象不支持接口 | GetItem 返回 Nothing 或明确错误 |
| 对象已关闭或 session 已切换 | 不复用旧 CAA 指针 |
| PLM 数据未加载 | 返回加载失败或由 CAA 侧受控加载 |
| 无权限/锁定状态 | 返回权限错误,不做半修改 |
| 批量循环调用 | 检查引用计数、内存、update 状态 |
| 中文名称和特殊字符 | 验证 BSTR / Unicode 转换 |
| 不同机器部署 | 验证 TypeLib、shared library、依赖路径和注册 |
16. 常见问题
VBA 能不能直接 include CAA 头文件?
不能。VBA 只能通过 COM Automation / TypeLib 看到接口。CAA 头文件是 C++ 编译期接口。
已经有 CAA 接口,为什么 VBA 看不到?
通常是因为没有对应 IDL、没有生成 TypeLib、没有实现 Automation TIE、没有注册/部署 TypeLib,或没有从运行时对象提供获取入口。
GetItem(“…”) 里的字符串应该写什么?
写你开放给脚本层的对象/接口名称。对已有 Dassault 接口,可参考对应 VBA 示例或 TypeLib 对象浏览器。对自定义接口,应在 IDL 的 #pragma ALIAS 和运行时 GetItem 实现中保持一致。
该用早绑定还是晚绑定?
开发调试可先晚绑定,交付给业务用户建议早绑定。早绑定可读性和可维护性更好,但要稳定 TypeLib 版本和 GUID。
是否可以用 VBA 做批处理?
可以,但不要让 VBA 直接拼接大量底层模型操作。VBA 应调用一个 CAA 封装好的批处理方法,由 CAA 侧负责 session、update、保存、失败隔离和日志。
17. 推荐实践
- Automation 接口要业务化,不要把 CAA 底层对象原样暴露给 VBA。
- 接口命名、alias、GUID 发布后保持稳定。
- 所有跨边界数据都用 BSTR、VARIANT、SAFEARRAY 或 Automation 对象。
- CAA 侧统一管理 update、保存、删除、加载和权限。
- VBA 侧每次从当前 editor 或当前选择重新获取对象,不缓存跨文档对象。
- 对可能影响模型状态的读取接口,记录调用前后的 update 状态。
- 对批处理和高风险操作,优先设计“一次调用完成一个业务事务”的粗粒度方法。
- 把 V6 与 V5 的差异写进接口说明,特别是 editor/PLM 上下文、TypeLib、GetItem、权限和 64 位部署。
评论