数组

时间:2019-06-11 12:59:19

标签: arrays excel vba

我想测试我的数组是否为空。

我尝试使用函数IsEmpty(),但是该函数始终返回False。并且不要输入if条件。

我的下面的代码:

Sub Freeze()

    Dim tab_freeze() as variant

    If IsEmpty(tab_freeze) Then
        ReDim tab_freeze(0)
    Else
        ReDim Preserve tab_freeze(UBound(tab_freeze) + 1)
        tab_freeze(UBound(tab_freeze)) = "As you want here"
     End If

End Sub

我想让函数知道我的数组tab_freeze是否为空。 或者了解为什么IsEmpty(tab_freeze)第一次返回False

5 个答案:

答案 0 :(得分:3)

IsEmpty是一个标准库函数,当类型为True的变量具有Variant子类型(Empty)时返回Variant/EmptyRange.Value的情况是单元格中没有内容。

在您的情况下,您不是在处理Variant,而是在处理Variants dynamic 数组。 动态意味着您首先必须使用命令ReDim为特定数量的元素分配空间。您可以使用IsEmpty(tab_freeze(1))检查第一个元素是否已初始化-但这可能不是您想要的。

不幸的是,VBA上没有内置函数可以检查是否已分配了动态数组。有很多建议如何检查,例如参见How to check for empty array in vba macro。我个人使用以下例程。它检查变量是否声明为Array及其范围。如果未分配数组,则LBoundUBound返回运行时错误(因此该函数将不会获得True)。但它也处理split("")的返回值-这将使LBound的值为0,而UBound的值为-1

Function IsArrayAllocated(arr As Variant) As Boolean
    On Error Resume Next
    IsArrayAllocated = isArray(arr) _
                   And Not IsError(LBound(arr, 1)) _
                   And LBound(arr, 1) <= UBound(arr, 1)
End Function

答案 1 :(得分:2)

根据您对“空数组”的理解,可能会有不同的答案。如果您将Dim tab_freeze() as variant视为一个空数组,只要其中没有维,则可以这样做:

Public Function IsArrayEmpty(myArray As Variant) As Boolean

    On Error GoTo IsArrayEmpty_Error

    Dim tempVar As Variant
    tempVar = myArray(0)

    IsArrayEmpty = False

    On Error GoTo 0
    Exit Function

IsArrayEmpty_Error:

    IsArrayEmpty = True

End Function

如果有人在使用Option Base 1,则第一个元素不是0,而是1,这会出现问题。通常,这被认为是无量纲的数组,但是您可以根据需要调用它(如果单独编程,则可能在VBA中是这样)。

如果您将Dim testArray(10) as Variant视为“空”数组,则可以这样做:

Public Function IsArrayWithValuesAtAll(myArray As Variant) As Boolean
    IsArrayWithValuesAtAll = IsError(Application.Match("*", (myArray), 0))
End Function

答案 2 :(得分:0)

为了测试数组是否为空,我通常Join()没有定界符并测试其长度。

Sub Freeze()

    Dim tab_freeze() As Variant

    Dim jArr As String

    jArr = Join(tab_freeze, "")

    If Len(jArr) = 0 Then
        ReDim tab_freeze(0)
    Else
        ReDim Preserve tab_freeze(UBound(tab_freeze) + 1)
        tab_freeze(UBound(tab_freeze)) = "As you want here"
    End If

End Sub

尽管,值得注意的是,对于Empty数组,此数组将返回无量纲的数组。

答案 3 :(得分:0)

感谢所有答案。

但是我找到了解决方案。 Vba认为,对于Dim tab_freeze() As Varianttab_freeze不是空的,但是UBound(tab_freeze)调用了错误。

所以我刚刚删除了Dim中的括号:

Sub Freeze()

    Dim tab_freeze as variant

    If IsEmpty(tab_freeze) Then
        ReDim tab_freeze(0)
    Else
        ReDim Preserve tab_freeze(UBound(tab_freeze) + 1)
        tab_freeze(UBound(tab_freeze)) = "As you want here"
     End If

End Sub

答案 4 :(得分:0)

为什么不使用用户Merri在此vbforums thread中谈论的VB魔术,而不是使用Variant来替换类型为Variant的数组。

  

处理数组时的常见问题之一是知道何时初始化数组以及何时未初始化数组。幸运的是,有一个简单的本地VB代码解决方案:

     

Not Not ArrayName

     

这是要在数组变量中获取32位指针值,镜像这些位,然后再次对其进行镜像。现在,您有效地知道了指向安全数组结构的指针。另外,您还知道是否可以使用LBound和UBound访问数组。

Private Sub ArrayTest()
    Dim testArr() as Variant
    ' Prints False
    Debug.Print Not Not testArr

    ReDim testArr(0)
    ' This prints True
    Debug.Print Not Not testArr
End Sub

Merri还谈到了可能发生的问题,但我还没有发现,我们必须记住,该文章是关于Visual Basic而非Visual Basic for Applications的。 (介意,我在解释)
显然,在某些情况下,使用此方法会引发错误,可以通过在VB IDE中运行一次简单的Dim IDEbug() As Long: Debug.Assert Not IDEbug Or App.hInstance来避免该错误。
再次报价:

  

这里发生的是,首先我们打电话来推高可能的错误情况。然后我们调用App.hInstance:我们几乎可以对任何VB方法进行调用,但是由于hInstance返回Long数,因此我们使用它。无论出于何种原因,这都会使以下所有“ Not ArrayName”调用均正常工作。在IDE中执行该行之后,您甚至可以注释该行,其效果仍然保留。仅关闭VB并再次打开它会重置条件,以便您需要再次拨打电话。

我想强调一点,我没有提出这个解决方案,但是它极大地帮助了我。我还要指出,我从未执行过Debug.Assert Not someArray Or Application.Hinstance,并且还没有遇到任何问题。显然,这可能与VBA与VB稍有不同有关,但我不能肯定地说。