VBA处理空数组错误

时间:2010-11-04 13:15:18

标签: vba error-handling excel-vba excel-2003 excel

我正在编写一个脚本,它将遍历我的电子表格,并查找是否有所选单元格的重复项。如果有重复,那么该函数将返回一个行是重复的数组,并创建一个注释告诉我哪些行是重复的。我已经能够处理错误0但是现在当我使用UBound函数检查数组中是否存在元素时,我得到错误9。有没有人知道如何验证整数数组,如果它是空的或不是因为我的代码似乎没有完成这项工作。以下是我的代码

Function IsArrayEmpty(anArray As Variant) As Boolean
    Dim i As Integer

    On Error Resume Next
        i = UBound(anArray, 1)
    Select Case (Err.Number)
        Case 0
            IsArrayEmpty = True
        Case 9
            IsArrayEmpty = True
        Case Else
            IsArrayEmpty = False
    End Select
End Function

8 个答案:

答案 0 :(得分:7)

尝试此操作来检查空数组:

Dim arr() As String

If (Not arr) = -1 Then
   Debug.Print "empty"
Else
   Debug.Print "UBound is " & UBound(X)
End If  

HTH!

答案 1 :(得分:7)

您的函数失败,因为如果UBound()没有引发错误(即数组的大小),则Err.Number为0并且:

Case 0
  IsArrayEmpty = True
执行

返回错误的结果。

最简单的方法就是捕获错误:

Function IsArrayEmpty(anArray As Variant) As Boolean
On Error GoTo IS_EMPTY
If (UBound(anArray) >= 0) Then Exit Function
IS_EMPTY:
    IsArrayEmpty = True
End Function

答案 2 :(得分:4)

您的数组变量是空还是空()?

'Empty'是一个未初始化的变体:IsEmpty(myVar)将返回true ...你可能会被愚弄认为你有一个空数组(这是'空()',而不是'空' - 试着保持up,这节课后会有一个简短的测试)因为IsEmpty(myArray)也会返回True。

Dim myVar as Variant      ' this is currently Empty, and Ubound returns an error
Dim myArray() as variant ' this is currently Empty(), and Ubound returns an error

Redim myVar(0 to 0) ' this is no longer empty, and has a valid Ubound
Redim myArray(0 to 0) ' this is no longer empty, and has a valid Ubound

检查myVar的可靠方法是TypeName(myVar) - 如果是数组,则名称包含括号:

  
If Instr(Typename(myVar), "(") > 0 then  

    ' we now know it is an array  
    If Not IsEmpty(myVar) Then  

       ' We can now check its dimensions  
        If Ubound(myVar) > 0  
             ' insert error-free code here  
        Endif  

    Endif  

Endif  

完整答案是Excellerando上的“在Excel VBA中检测数组变体”。

答案 3 :(得分:1)

  

..我仍然收到错误#9脚本   超出范围

如果您收到错误#9 ....这是否意味着您正在提供所需的信息(数组为空)?

答案 4 :(得分:1)

Chip Pearson在answer年前就给出了,它仍然有效。这是我将近四年在图书馆中使用的功能。

Public Function IsArrayEmpty(arr As Variant) As Boolean
    Dim lb As Long
    Dim ub As Long

    Err.Clear
    On Error Resume Next

    If IsArray(arr) = False Then
        ' we weren't passed an array, return True
        IsArrayEmpty = True
    End If

    ' Attempt to get the UBound of the array. If the array is
    ' unallocated, an error will occur.
    ub = UBound(arr, 1)
    If (Err.Number <> 0) Then
        IsArrayEmpty = True
    Else
        ''''''''''''''''''''''''''''''''''''''''''
        ' On rare occasion, under circumstances I
        ' cannot reliably replicate, Err.Number
        ' will be 0 for an unallocated, empty array.
        ' On these occasions, LBound is 0 and
        ' UBound is -1.
        ' To accommodate the weird behavior, test to
        ' see if LB > UB. If so, the array is not
        ' allocated.
        ''''''''''''''''''''''''''''''''''''''''''
        Err.Clear
        lb = LBound(arr)
        If lb > ub Then
            IsArrayEmpty = True
        Else
            IsArrayEmpty = False
        End If
    End If

    Err.Clear
End Function

基本上,它将检查以确保您传递了数组,然后尝试查找上限(如果数组为空,则将引发错误),最后将下限与上限进行比较以确保数组确实不是空的。

答案 5 :(得分:0)

您可以使用JScript的VBArray()对象检索总元素数来检查数组是否为空(使用变体类型的数组,单维或多维):

Sub Test()

    Dim a() As Variant
    Dim b As Variant
    Dim c As Long

    ' Uninitialized array of variant
    ' MsgBox UBound(a) ' gives 'Subscript out of range' error
    MsgBox GetElementsCount(a) ' 0

    ' Variant containing an empty array
    b = Array()
    MsgBox GetElementsCount(b) ' 0

    ' Any other types, eg Long or not Variant type arrays
    MsgBox GetElementsCount(c) ' -1

End Sub

Function GetElementsCount(aSample) As Long

    Static oHtmlfile As Object ' instantiate once

    If oHtmlfile Is Nothing Then
        Set oHtmlfile = CreateObject("htmlfile")
        oHtmlfile.parentWindow.execScript ("function arrlength(arr) {try {return (new VBArray(arr)).toArray().length} catch(e) {return -1}}"), "jscript"
    End If
    GetElementsCount = oHtmlfile.parentWindow.arrlength(aSample)

End Function

对我而言,每个元素大约需要0.3 mksec + 15毫秒初始化,因此10M元素阵列大约需要3秒。可以通过ScriptControl ActiveX实现相同的功能(它在64位MS Office版本中不可用,因此您可以使用this之类的解决方法。

答案 6 :(得分:0)

UBound和LBound将返回给定数组的上边界和下边界。因此,如果Ubound(arr)等于LBound(arr),则它为空。

Dim arr() As String

If UBound(arr) = LBound(arr) Or UBound(arr) <= 0 Then
   Debug.Print "empty"
Else
   Debug.Print "not empty"
End If  

答案 7 :(得分:0)

您始终可以使用“ isArray()”函数

ServiceA