VBA Handle Empty Array Ошибка - PullRequest
       33

VBA Handle Empty Array Ошибка

7 голосов
/ 04 ноября 2010

Я пишу скрипт, который будет проходить через всю мою электронную таблицу и определять, есть ли дубликаты выбранных ячеек.если есть ошибки, то функция вернет массив, строки которого являются ошибками, и создаст комментарий, сообщающий мне, какие строки являются ошибками.Мне удалось обработать ошибку 0, но теперь я получаю ошибку 9, когда проверяю массив, есть ли в нем элементы с использованием функции UBound.Кто-нибудь знает, как проверить массив целых чисел, если он пустой или нет, потому что мой код, кажется, не выполняет свою работу.Ниже мой код

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

Ответы [ 7 ]

7 голосов
/ 05 ноября 2010

Ваша функция не выполняется, потому что если нет ошибки, вызванной 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
7 голосов
/ 04 ноября 2010

Попробуйте проверить пустой массив:

Dim arr() As String

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

НТН!

4 голосов
/ 02 декабря 2010

Является ли ваш вариант массива пустым или пустым ()?

«Пустой» - неинициализированный вариант: IsEmpty (myVar) вернет истину ... И вас могут обмануть, думая, что у вас есть пустой массив (это «Пусто ()», а не «Пусто» - попробуйте не отставать, после этого класса будет короткий тест), потому что 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  

Полный ответ: «Обнаружение варианта массива в Excel VBA» на Excellerando .

1 голос
/ 19 ноября 2018

Чип Пирсон дал ответ лет назад, и он все еще работает. Вот функция, которую я выполнял в своей библиотеке почти четыре года.

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

По сути, он проверяет, что вы передали массив, затем пытается найти верхнюю границу (которая выдаст ошибку, если массив пустой), и, наконец, сравнивает нижнюю границу с верхней, чтобы массив на самом деле не пустой.

1 голос
/ 01 декабря 2010

.. Я все еще получаю сценарий ошибки № 9 вне границ

если вы получаете ошибку # 9 .... не означает ли это, что вы получаете необходимую информацию (массив пуст)?

0 голосов
/ 18 мая 2018

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  
0 голосов
/ 13 декабря 2015

Вы можете проверить, является ли массив пустым, получая общее количество элементов, используя объект VBArray() JScript (работает с массивами вариантного типа, одиночного или многомерного):

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 мксек для каждого элемента + 15 мсек инициализации, поэтому массив из 10M элементов занимает около 3 сек. Та же функциональность может быть реализована через ScriptControl ActiveX (она недоступна в 64-битных версиях MS Office, поэтому вы можете использовать обходной путь, например this ).

...