Dim Result() As Variant
在我的手表窗口中,这显示为
Expression | Value | Type
Result | | Variant/Variant()
如何检查以下内容:
if Result is nothing then
或
if Result is Not Set then
这基本上就是我想要完成的目标,但是第一个不起作用,第二个也不存在。
为了避免错误处理,我使用了这个,很久以前在论坛上看到的,从那时起就成功使用了:
If (Not Not Result) <> 0 Then 'Means it is allocated
或者另一种选择
If (Not Not Result) = 0 Then 'Means it is not allocated
我主要用它来通过这种方式扩展未设置数组的数组大小
'Declare array
Dim arrIndex() As Variant
'Extend array
If (Not Not Result) = 0 Then
ReDim Preserve Result(0 To 0)
Else
ReDim Preserve Result(0 To UBound(Result) + 1)
End If
Chip Pearson 制作了一个名为 modArraySupport 的有用模块,其中包含一堆用于测试此类内容的函数。在您的情况下,您需要使用
IsArrayAllocated
。
Public Function IsArrayAllocated(Arr As Variant) As Boolean
该函数返回 TRUE 或 FALSE 指示指定的数组是否已分配(非空)。返回 TRUE array 是静态数组或已使用 Redim 语句分配的动态数组。如果数组是动态数组,则返回 FALSE 尚未使用 ReDim 调整大小或已使用 Erase 语句取消分配。这个函数基本上是相反的 数组为空。例如,
Dim V() As Variant
Dim R As Boolean
R = IsArrayAllocated(V) ' returns false
ReDim V(1 To 10)
R = IsArrayAllocated(V) ' returns true
所使用的技术基本上是测试数组边界(如@Tim Williams建议的),但有一个额外的陷阱。
要在您的即时窗口中进行测试:
?IsArrayAllocated(Result)
在Watch窗口中测试:有多种方法可以做到这一点;例如,在
R
上添加一个监视,然后在“监视类型”下选择“值更改时中断”。
您可以在立即窗口中使用以下内容:
?Result Is Nothing
?IsNull( Result )
?IsEmpty( Result )
?IsMissing( Result )
第一个只是为了完整性。由于 Result 不是对象,因此
Result Is Nothing
会抛出错误。 Empty
适用于尚未初始化的变体 (更新)在进行一些额外的检查时,我发现 IsEmpty 永远不会在已声明的数组(无论是否已 Redim)上返回 true,只有一个例外。我发现的唯一例外是当数组在模块级别声明而不是公共时,然后仅当您在立即窗口中检查它时。
Missing
如果用于传递给函数或子函数的可选值。虽然您无法声明 Optional Foo() As Variant
,但您可以拥有类似 ParamArray Foo() As Variant
的内容,在这种情况下,如果没有传递任何内容,IsMissing
将返回 true。
因此,确定数组是否已初始化的唯一方法是编写一个程序来检查:
Public Function IsDimensioned(vValue As Variant) As Boolean
On Error Resume Next
If Not IsArray(vValue) Then Exit Function
Dim i As Integer
i = UBound(Bar)
IsDimensioned = Err.Number = 0
End Function
顺便说一句,应该注意的是,如果数组已确定尺寸然后被删除,则此例程(或 Jean-François Corbett 发布的库)将返回 false。
我建议采用稍微不同的方法,因为我认为使用像
(Not Array) = -1
这样的语言工件来检查初始化很难阅读,并且会导致维护麻烦。
如果您需要检查数组分配,很可能是因为您正在尝试创建自己的“向量”类型:一个在运行时增长以容纳添加数据的数组。如果您利用类型系统,VBA 可以相当容易地实现向量类型。
Type Vector
VectorData() As Variant
VectorCount As Long
End Type
Dim MyData As Vector
Sub AddData(NewData As Variant)
With MyData
' If .VectorData hasn't been allocated yet, allocate it with an
' initial size of 16 elements.
If .VectorCount = 0 Then ReDim .VectorData(1 To 16)
.VectorCount = .VectorCount + 1
' If there is not enough storage for the new element, double the
' storage of the vector.
If .VectorCount > UBound(.VectorData) Then
ReDim Preserve .VectorData(1 To UBound(.VectorData) * 2)
End If
.VectorData(.VectorCount) = NewData
End With
End Sub
' Example of looping through the vector:
For I = 1 To MyData.VectorCount
' Process MyData.VectorData(I)
Next
请注意,在此代码中无需检查数组分配,因为我们只需检查
VectorCount
变量即可。如果它是 0,我们就知道向量中还没有添加任何内容,因此数组未分配。
这段代码不仅简单明了,向量还具有数组的所有性能优势,而且添加元素的摊余成本实际上是 O(1),非常高效。唯一的权衡是,由于每次向量用完空间时存储空间都会加倍,在最坏的情况下,向量的存储空间有 50% 被浪费。
检查阵列的
LBound
。如果出现错误,则表明它尚未初始化。
使用内联错误检查的示例:
Dim u As Long
Dim e As Long
On Error Resume Next
u = UBound(arr)
e = Err.Number
On Error GoTo 0
If e = 9 Then
'Error 9 = subscript out of bounds.
'The array is empty.
Stop
Else
'The array is not empty.
Stop
End If
所以我发现 RandomCoders 方法非常好。但请记住,它仅在将变体声明为数组时才有效:
Sub test()
Dim v() As Variant
Debug.Print (Not Not v) = 0 'returns true
v = [A1:B5].Value
Debug.Print (Not Not v) = 0 'returns false
End Sub
但是您也可以通过这种方式检查变体:
Sub test2()
Dim v As Variant
Debug.Print IsEmpty(v) 'returns true
v = [A1:B5].Value
Debug.Print IsEmpty(v) 'returns false
End Sub