Handle Error 9 when there is an Empty Array

后端 未结 8 1586
无人共我
无人共我 2021-01-02 17:43

I am writing a script that will loop through an Excel spreadsheet and find if there are duplicates of selected cells. If there are duplicates then the function will return

相关标签:
8条回答
  • 2021-01-02 18:20

    Try this to check an empty array:

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

    HTH!

    0 讨论(0)
  • 2021-01-02 18:23

    The UBound and LBound will return the upper and lower boundries of a given array. So, if Ubound(arr) is equal than LBound(arr) then it is empty.

    Dim arr() As String
    
    If UBound(arr) = LBound(arr) Or UBound(arr) <= 0 Then
       Debug.Print "empty"
    Else
       Debug.Print "not empty"
    End If  
    
    0 讨论(0)
  • 2021-01-02 18:24

    Your function is failing because if there is no error raised by UBound() (i.e. the array is dimensioned) then Err.Number is 0 and:

    Case 0
      IsArrayEmpty = True
    

    is executed returning an incorrect result.

    The simplest way is to just trap the error:

    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
    
    0 讨论(0)
  • 2021-01-02 18:24

    Is your array variant Empty or Empty()?

    'Empty' is an uninitialised variant: IsEmpty(myVar) will return true... And you could be fooled into thinking you have an empty array (which is 'Empty()', not 'Empty' - try to keep up, there will be a short test after this class) because IsEmpty(myArray) returns True, too.

    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

    A reliable way to check myVar is TypeName(myVar) - if it's an array, the name contains brackets:

      
    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  
    
    

    The full answer is 'Detecting an array variant in Excel VBA' on Excellerando.

    0 讨论(0)
  • 2021-01-02 18:28

    You can check if the array is empty by retrieving total elements count using JScript's VBArray() object (works with arrays of variant type, single or multidimensional):

    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
    

    For me it takes about 0.3 mksec for each element + 15 msec initialization, so the array of 10M elements takes about 3 sec. The same functionality could be implemented via ScriptControl ActiveX (it is not available in 64-bit MS Office versions, so you can use workaround like this).

    0 讨论(0)
  • 2021-01-02 18:32

    Chip Pearson gave the answer years ago and it still works. Here's the function I've had in my library for almost four years.

    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
    

    Basically, it checks to make sure you passed an array, then it attempts to find the upper bound (which will throw an error if the array is empty), and finally it compares the lower bound to the upper bound to make sure the array really isn't empty.

    0 讨论(0)
提交回复
热议问题