Как проверить пустой массив в макросе vba

Я хочу проверить пустые массивы. Google дал мне различные решения, но ничего не помогло. Возможно, я применяю их неправильно.

Function GetBoiler(ByVal sFile As String) As String
'Email Signature
    Dim fso As Object
    Dim ts As Object
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set ts = fso.GetFile(sFile).OpenAsTextStream(1, -2)
    GetBoiler = ts.ReadAll
    ts.Close
End Function

Dim FileNamesList As Variant, i As Integer
' activate the desired startfolder for the filesearch
FileNamesList = CreateFileList("*.*", False) ' Returns File names
' performs the filesearch, includes any subfolders
' present the result
' If there are Signatures then populate SigString
Range("A:A").ClearContents
For i = 1 To UBound(FileNamesList)
    Cells(i + 1, 1).Formula = FileNamesList(i)
Next i

SigString = FileNamesList(3)

If Dir(SigString) <> "" Then
    Signature = GetBoiler(SigString)
Else
    Signature = ""
End If

Здесь, если массив FileNamesList пуст, GetBoiler(SigString) вообще не должен вызываться. Когда массив FileNamesList пуст, SigString также пуст, и это вызывает функцию GetBoiler() с пустой строкой. Я получаю ошибку в строке

Set ts = fso.GetFile(sFile).OpenAsTextStream(1, -2)

поскольку sFile пуст. Есть ли способ избежать этого?

Комментарии к вопросу (1)

Поскольку вы имеете дело со строковым массивом, рассматривали ли вы вариант Join?

If Len(Join(FileNamesList)) > 0 Then
Комментарии (8)

Ехать с тройным негативным:

If (Not Not FileNamesList)  0 Then
    ' Array has been initialized, so you're good to go.
Else
    ' Array has NOT been initialized
End If

Или просто:

If (Not FileNamesList) = -1 Then
    ' Array has NOT been initialized
Else
    ' Array has been initialized, so you're good to go.
End If

В VB, по каким-то причинам, не с myarray` возвращает указатель типа safearray. Для неинициализированных массивов, это возвращает -1. Вы можете " не " это XOR это с -1, таким образом, возвращается ноль, если вы предпочитаете.

               (Not myArray)   (Not Not myArray)
Uninitialized       -1                 0
Initialized    -someBigNumber   someOtherBigNumber

Source

Комментарии (3)

Если вы тест на функцию массив это'будете работать за всякие границы:

Function IsVarArrayEmpty(anArray As Variant)

Dim i As Integer

On Error Resume Next
    i = UBound(anArray,1)
If Err.number = 0 Then
    IsVarArrayEmpty = False
Else
    IsVarArrayEmpty = True
End If

End Function
Комментарии (3)

Я вижу подобные ответы здесь... но не мое...

Это как я к сожалению буду с этим бороться... Мне нравится лен(присоединиться(Арр)) и gt; 0, но это не'т работать, если массив был массив emptystrings...

Public Function arrayLength(arr As Variant) As Long
  On Error GoTo handler

  Dim lngLower As Long
  Dim lngUpper As Long

  lngLower = LBound(arr)
  lngUpper = UBound(arr)

  arrayLength = (lngUpper - lngLower) + 1
  Exit Function

handler:
  arrayLength = 0 'error occured.  must be zero length
End Function
Комментарии (0)

При написании на VBA есть эта фраза в моей голове: "не может быть так просто, но..."и

Вот что я приняла его:

Private Function IsArrayEmpty(arr As Variant)
  ' This function returns true if array is empty
  Dim l As Long

  On Error Resume Next
  l = Len(Join(arr))
  If l = 0 Then
    IsArrayEmpty = True
  Else
    IsArrayEmpty = False
  End If

  If Err.Number > 0 Then
      IsArrayEmpty = True
  End If

  On Error GoTo 0
End Function

Private Sub IsArrayEmptyTest()
  Dim a As Variant
  a = Array()
  Debug.Print "Array is Empty is " & IsArrayEmpty(a)
  If IsArrayEmpty(a) = False Then
    Debug.Print "  " & Join(a)
  End If
End Sub
Комментарии (2)

Этот код делает не то, что вы ожидаете:

If Dir(SigString)  "" Then
    Signature = GetBoiler(SigString) 
Else
    Signature = "" 
End If

Если вы передадите пустую строку (""") или vbNullString в Dir, он вернет имя первого файла в текущем пути к каталогу (путь, возвращаемый CurDir$). Таким образом, если SigString пуст, ваше условие If будет оценено как True, потому что Dir вернет непустую строку (имя первого файла в текущем каталоге), и будет вызван GetBoiler. Если же SigString будет пустым, вызов fso.GetFile завершится неудачей.

Вам следует либо изменить условие, чтобы проверить, что SigString не пуст, либо использовать метод FileSystemObject.FileExists вместо Dir для проверки существования файла. Метод Dir сложен в использовании именно потому, что он делает то, чего вы, возможно, не ожидаете от него. Лично я бы использовал Scripting.FileSystemObject вместо Dir, потому что здесь нет ничего смешного (FileExists возвращает True, если файл существует, и False, если не существует). Более того, FileExists выражает намерение вашего кода гораздо яснее, чем Dir.

Метод 1: Сначала проверьте, что SigString не является пустым.

If SigString  "" And Dir(SigString)  "" Then
    Signature = GetBoiler(SigString) 
Else
    Signature = "" 
End If

Метод 2: Используйте метод FileSystemObject.FileExists.

Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")

If fso.FileExists(SigString) Then
    Signature = GetBoiler(SigString) 
Else
    Signature = "" 
End If
Комментарии (0)

Я просто скопировав ниже код великого чипа Пирсона. Это работает Шарм. Здесь's его страницы на функции массив.

Я надеюсь, что это помогает.

Public Function IsArrayEmpty(Arr As Variant) As Boolean
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' IsArrayEmpty
' This function tests whether the array is empty (unallocated). Returns TRUE or FALSE.
'
' The VBA IsArray function indicates whether a variable is an array, but it does not
' distinguish between allocated and unallocated arrays. It will return TRUE for both
' allocated and unallocated arrays. This function tests whether the array has actually
' been allocated.
'
' This function is really the reverse of IsArrayAllocated.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

    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

End Function
Комментарии (1)

Двиг был ближе всех, но его ответ выдает ошибку несоответствия типов.

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

Здесь'простой, комплексное решение:

option explicit
Function foo() As Variant

    Dim bar() As String

    If (Not Not bar) Then
        ReDim Preserve bar(0 To UBound(bar) + 1)
    Else
        ReDim Preserve bar(0 To 0)
    End If

    bar(UBound(bar)) = "it works!"

    foo = bar

End Function
Комментарии (0)

Упрощенная проверка на пустой массив:

Dim exampleArray() As Variant 'Any Type

If ((Not Not exampleArray) = 0) Then
      'Array is Empty
Else
      'Array is Not Empty
End If
Комментарии (1)

На основе ahuth'ы ответ;

Function AryLen(ary() As Variant, Optional idx_dim As Long = 1) As Long
    If (Not ary) = -1 Then
        AryLen = 0
    Else
        AryLen = UBound(ary, idx_dim) - LBound(ary, idx_dim) + 1
    End If
End Function

Проверка на пустой массив; is_empty = AryLen(some_array)=0

Комментарии (0)
Public Function IsEmptyArray(InputArray As Variant) As Boolean

   On Error GoTo ErrHandler:
   IsEmptyArray = Not (UBound(InputArray) >= 0)
   Exit Function

   ErrHandler:
   IsEmptyArray = True

End Function
Комментарии (2)

Вы можете использовать следующие функции, чтобы проверить, если вариант или строку пустой массив в VBA


Function IsArrayAllocated(Arr As Variant) As Boolean
        On Error Resume Next
        IsArrayAllocated = IsArray(Arr) And _
                           Not IsError(LBound(Arr, 1)) And _
                           LBound(Arr, 1) 
Комментарии (0)

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

Комментарии (0)

Вот еще один способ сделать это. Я использовал его в некоторых случаях и это's работает.

Function IsArrayEmpty(arr As Variant) As Boolean

Dim index As Integer

index = -1
    On Error Resume Next
        index = UBound(arr)
    On Error GoTo 0

If (index = -1) Then IsArrayEmpty = True Else IsArrayEmpty = False

End Function
Комментарии (0)
Function IsVarArrayEmpty(anArray As Variant) as boolean
    On Error Resume Next
    IsVarArrayEmpty = true
    IsVarArrayEmpty = UBound(anArray) < LBound(anArray)
End Function

Может быть, метод ubound падает и он остается в true, а если `метод ubound < lbound, это'ы пуст

Комментарии (0)

Чтобы проверить, является ли байтовый массив пуст, то самый простой способ-использовать функцию VBA в <код>StrPtr()</код>.

Если массив пуст, но <код>В StrPtr()</код> возвращает <код>0</код>; в противном случае она возвращает ненулевое значение (впрочем, это'ы <б>нет</б> адрес первого элемента).

Dim ar() As Byte
Debug.Assert StrPtr(ar) = 0

ReDim ar(0 to 3) As Byte
Debug.Assert StrPtr(ar)  0

Однако, он работает только с массивом байтов.

Комментарии (0)

Вы можете проверить свой счет.

Вот дур - это массив.

if (jsonObject("result")("cid").Count) = 0 them
MsgBox "Empty Array"

Я надеюсь, что это помогает. Иметь хороший день!

Комментарии (0)

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

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

Комментарии (1)

Лично я думаю, что одним из ответов может быть изменен, чтобы проверить, если массив имеет содержание:

if UBound(ar) > LBound(ar) Then

Это обрабатывает отрицательные числа ссылок и занимает меньше времени, чем некоторые из других вариантов.

Комментарии (1)

Я'обобщу проблему и вопрос по назначению. Протестируйте ассистирование на массиве и поймайте возможную ошибку

Function IsVarArrayEmpty(anArray as Variant)
Dim aVar as Variant

IsVarArrayEmpty=False
On error resume next
aVar=anArray(1)
If Err.number then '...still, it might not start at this index
    aVar=anArray(0)
    If Err.number then IsVarArrayEmpty=True ' neither 0 or 1 yields good assignment
EndIF
End Function

Конечно, он пропускает массивы со всеми отрицательными индексами или со всеми > 1... вероятно ли это? в странной стране, да.

Комментарии (1)