如何检查变量数组是否未分配?

问题描述 投票:0回答:6
   Dim Result() As Variant

在我的手表窗口中,这显示为

Expression | Value | Type
Result     |       | Variant/Variant()

如何检查以下内容:

   if Result is nothing then

   if Result is Not Set then

这基本上就是我想要完成的目标,但是第一个不起作用,第二个也不存在。

vba variant
6个回答
47
投票

为了避免错误处理,我使用了这个,很久以前在论坛上看到的,从那时起就成功使用了:

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

9
投票

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
上添加一个监视,然后在“监视类型”下选择“值更改时中断”。


9
投票

您可以在立即窗口中使用以下内容:

?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。


1
投票

我建议采用稍微不同的方法,因为我认为使用像

(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% 被浪费。


1
投票

检查阵列的

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

0
投票

所以我发现 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
© www.soinside.com 2019 - 2024. All rights reserved.