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

时间:2011-03-30 00:43:52

标签: vba variant

   Dim Result() As Variant

在我的观察窗口中,显示为

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

如何查看以下内容:

   if Result is nothing then

   if Result is Not Set then

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

6 个答案:

答案 0 :(得分:15)

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

If (Not Not Result) <> 0 Then 'Means it is allocated

或者

If (Not Not Result) = 0 Then 'Means it is not allocated

我主要用这种方法从unset数组扩展数组大小

'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

答案 1 :(得分:10)

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

?Result Is Nothing
?IsNull( Result )
?IsEmpty( Result )
?IsMissing( Result )

首先是完整性。由于Result不是对象,Result Is Nothing将抛出错误。 Empty适用于尚未初始化的变种,包括尚未标注尺寸的数组。

(更新)在做一些额外的检查时,我发现只有一个例外,IsEmpty永远不会在声明的数组(无论是否Redim)上返回true。我发现的唯一例外是当数组在模块级别而不是Public时声明,然后只有在立即窗口中检查它时。

Missing if if for optional values是否传递给函数或sub。虽然您无法声明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çoisCorbett发布的库)将返回false。

答案 2 :(得分:8)

Chip Pearson制作了一个名为modArraySupport的有用模块,它包含一系列功能来测试这样的事情。在您的情况下,您可能希望使用IsArrayAllocated

Public Function IsArrayAllocated(Arr As Variant) As Boolean
  

此函数返回TRUE或FALSE,指示是否已分配指定的数组(非空)。返回的TRUE   array是静态数组或已使用Redim语句分配的动态数组。如果数组是动态数组,则返回FALSE   尚未使用ReDim调整大小或已使用Erase语句取消分配。这个功能基本上是相反的   ArrayIsEmpty。例如,

Dim Result() As Variant
Dim R As Boolean
R = IsArrayAllocated(Result)  ' returns false
ReDim V(1 To 10)
R = IsArrayAllocated(Result)  ' returns true

使用的技术基本上是测试数组边界(由@Tim Williams建议)但是有额外的问题。

要在即时窗口中进行测试:

?IsArrayAllocated(Result)

在Watch窗口中进行测试:有很多方法可以做到这一点;例如,在R上添加一个监视,在“监视类型”下选择“值改变时休息”。

答案 3 :(得分:0)

检查阵列的LBound。如果你收到错误,那么它就是未初始化的。

答案 4 :(得分:0)

我建议采用稍微不同的方法,因为我认为使用像(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%的向量存储空间被浪费了。

答案 5 :(得分:0)

我认为已接受答案的第4行应该说:

ReDim Result(1 To 10)

代替:

ReDim V(1 To 10)

我相信第5行:

R = IsArrayAllocated(Result)  ' returns true

将像第3行一样返回FALSE。

R = IsArrayAllocated(Result)  ' returns false

因为结果不是第4行中重新定义的内容。

在第4行中,尝试重新命名称为V的数组,但甚至没有声明它。