← 返回首页

V6 CAA 开放接口供 VBA 调用开发指南

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 引用”,而是:

  1. 先用 CAA C++ 实现业务能力。
  2. 再用 IDL 定义 VBA 可见的 Automation 接口。
  3. 通过 TypeLib 交付给 VBA 做早绑定或晚绑定。
  4. 在 V6 对象模型中提供获取入口,例如对象的 GetItem("接口名")、工厂接口、应用服务或命令入口。
  5. 在 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 中常见的 ActiveEditorVPMOccurrenceGetItem("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 侧可以继续使用 CATBaseUnknownCATUnicodeStringCATLISTVCATFmFeatureFacadeCATIPLMUpdateEngine 等原生类型。
  • 出错时由 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:数组。
  • 继承自 CATIABaseCATIACollection 的 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,并实现 CountItem_NewEnumToArray。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()

实际能否直接挂到 CATIAActiveEditor 或某个 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 中可以看到 LoadTypeLibsRegisterTypeLibsUnregisterTypeLibs 这类基础能力。

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

部署检查项:

  1. C++ 实现库已经进入 runtime view 的 code/bin
  2. TypeLib 已生成并可被 VBA 引用。
  3. 所有依赖 framework 在运行环境中可加载。
  4. 如果接口依赖自定义 feature,CATfct、NLS、client id、credentials 配置都已经生效。
  5. 如果入口来自 GetItem("..."),宿主对象在目标 app/editor 中确实支持该接口获取。
  6. 在目标 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_POINTERE_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 风格的 PartDocumentProductDocument

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.UpdateDocument.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 侧用 CATFmCredentialsCATFmStartUpFacadeCATFmFeatureFacade 封装创建和读写,最后给 VBA 一个简洁入口。

13. 开发流程清单

下面是一条推荐落地路径。

  1. 明确 VBA 使用场景:当前选择、当前 editor、批处理、报表还是建模动作。
  2. 识别核心 CAA API,并先用 C++ 命令或单元测试验证业务链路。
  3. 设计 VBA 对象模型,确定接口名、对象名、方法、属性、集合和错误语义。
  4. 编写 IDL,继承 CATIABaseCATIACollection,使用 #pragma DUAL#pragma ALIAS
  5. 为所有接口、alias、typelib 分配稳定 GUID。
  6. 编写 C++ 实现类,使用 CATImplementClassTIE_... 绑定接口。
  7. 在实现类中调用核心 CAA 业务服务,完成类型转换、上下文校验、日志和错误处理。
  8. 对集合实现 CountItem_NewEnumToArray
  9. 提供运行时入口,例如 GetItem("MyCompanyFeatureInspector")、工厂服务或命令准备上下文。
  10. 创建 TypeLib 聚合头文件和 BUILT_OBJECT_TYPE = TYPELIB 模块。
  11. 构建 interface、implementation、typelib 三类模块。
  12. 部署 shared library、TypeLib、CATfct、NLS 和依赖资源到 runtime view。
  13. 在目标 V6 客户端启动后,从 VBA 添加引用并运行最小宏。
  14. 测试无对象、错误对象、未加载对象、无权限对象、正常对象、大批量对象。
  15. 固化接口版本,不随意改 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 位部署。

评论