Обработка ошибки 9 при наличии пустого массива

Я пишу сценарий, который просматривает электронную таблицу Excel и обнаруживает, есть ли дубликаты выбранных ячеек. Если есть дубликаты, функция вернет массив, в котором строки являются дубликатами, и создаст комментарий, чтобы сообщить мне строки.

Мне удалось обработать ошибку 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

person Talguy    schedule 04.11.2010    source источник


Ответы (8)


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

Dim arr() As String

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

HTH!

person Dr. belisarius    schedule 04.11.2010
comment
Я не претендую на особые знания, но, очевидно, этот метод проверки пустого массива использует ошибку в VBA и не должен использоваться: stackoverflow.com/questions/183353/ - person jtolle; 04.11.2010
comment
@jtolle - ваша ссылка, безусловно, является окончательным обсуждением этого вопроса. возможно, этот Q следует пометить как дубликат. или, по крайней мере, ваша ссылка должна быть ответом на вопрос Талгуя. - person hawbsl; 04.11.2010
comment
@jtolle Может быть. Я использовал эту вещь раньше, но, поскольку я ее не создавал, я не претендую на какие-либо достоинства. - person Dr. belisarius; 04.11.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
person Alex K.    schedule 05.11.2010
comment
это сработало лучше, но я все еще получаю сообщение об ошибке № 9, сценарий выходит за допустимые пределы - person Talguy; 05.11.2010
comment
Dim a(): Debug.Print IsArrayEmpty(a) у меня работает нормально ... Убедитесь, что у вас нет Инструменты ›Параметры› Общие ›Прервать все ошибки. - person Alex K.; 05.11.2010

Ваш вариант массива Empty или Empty ()?

'Empty' - это неинициализированный вариант: IsEmpty (myVar) вернет true ... И вас могут обмануть, если вы подумаете, что у вас пустой массив (который является 'Empty ()', а не 'Empty' - постарайтесь не отставать, там будет коротким тестом после этого класса), потому что 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 до 0) "это больше не пусто и имеет действующий Ubound
Redim myArray (от 0 до 0)" это больше не пусто и имеет действительный 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.

person Nigel Heffernan    schedule 02.12.2010

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

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

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

person phrebh    schedule 19.11.2018
comment
Случай странного поведения с комментариями можно увидеть при оценке массива результатов после Split() пустой строки: UBound(Split("","splitter")) = -1, LBound(Split("","splitter")) = 0. Возможно, это просто (неудобный) способ указать на ошибку в основных строковых функциях, подобно тому, как некоторые строковые функции традиционно возвращают -1 на разных языках и платформах. - person miroxlav; 03.09.2019

.. Я все еще получаю сообщение об ошибке №9. Сценарий выходит за пределы допустимого диапазона.

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

person CaBieberach    schedule 01.12.2010
comment
это информация, которую я хочу, но программа не переходит к обработчику ошибок, вместо этого я получаю всплывающее сообщение об ошибке 9 - person Talguy; 02.12.2010
comment
Привет, Талгай, ты пробовал предложение Алекса К.? По этой ссылке ‹pcreview.co.uk/forums/thread-3387988.php ›если поменять в одной офисной программе, то можно будет перенести в другую. - person CaBieberach; 02.12.2010
comment
Проверьте также эту ссылку ‹cpearson.com/Excel/ErrorHandling.htm ›. Раздел Блоки обработки ошибок и при ошибке Перейти. (Множественный оператор при ошибке в той же процедуре не улавливает правильно.) - person CaBieberach; 02.12.2010

Вы всегда можете использовать функцию isArray ()

Dim yourArray as variant
if not isArray(your_array) then
   msgbox("empty")
else
   msgbox("with data")
end if
person Kepa    schedule 27.11.2019

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

person omegastripes    schedule 12.12.2015

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  
person Joaquinglezsantos    schedule 18.05.2018