我正在开发一个与 COM 服务器交换对象的 Excel VBA 插件,如下所示:
'get an array of objects
Dim Ents() As ISomething
ComObject.GetEntities Ents
'send an array with 10 objects
ReDim Ents(9)
Set Ents(0) = ...
...
ComObject.SetEntities Ents
Run Code Online (Sandbox Code Playgroud)
获取数组效果很好:如果数组包含对象,它会按预期工作,如果数组为空,那么UBound(Ents) = -1一切都会按预期工作。
发送数组仅适用于非空数组,因为我不能Redim Ents(-1),并且EraseVBA 和 COM 服务器崩溃:Debug.Print UBound(Ents)在 VBA 中崩溃,谁知道是什么导致服务器崩溃。
看起来该Erase语句使数组未定义/损坏而不是空。
编辑(对下面评论的澄清):
执行此代码会崩溃,因为它无法计算UBound:
Sub Test()
Dim Ents() As ISmartId
Debug.Print UBound(Ents)
End Sub
Run Code Online (Sandbox Code Playgroud)
但是,如果添加Ents到监视窗口,然后在该行设置断点Debug.Print并执行,调试器会ISmartId(0 to -1)在“类型”列中显示 。此后,执行继续而不会崩溃,并且“调试”窗口显示预期的-1.
看起来调试器能够按照我需要的方式正确初始化空数组,以显示其值。
对于对象,您只需将未定义的数组复制到变体中并返回即可做到这一点:
Dim o() As Worksheet
Dim v As Variant
v = o
o = v
Run Code Online (Sandbox Code Playgroud)
对于非对象,在变体中创建一个空数组,然后更改其类型代码:
Private Declare Sub GetMem2 Lib "msvbvm60" (src As Any, dest As Any)
Dim i() as Long
Dim v as Variant
v = Array()
Dim NewTypeCode As Integer
NewTypeCode = vbArray Or vbLong
GetMem2 NewTypeCode, v
i = v
Run Code Online (Sandbox Code Playgroud)