Как проверить пустой массив в макросе 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 пуст. Любой способ избежать этого?

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

 If Len(Join(FileNamesList)) > 0 Then 

Идите с тройным отрицательным:

 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 по какой-либо причине Not myArray возвращает указатель SafeArray. Для неинициализированных массивов возвращается -1. Вы не можете это сделать с XOR с -1, таким образом, возвращая ноль, если хотите.

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

Источник

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

 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 

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

Вот как я, к сожалению, собираюсь разобраться с этим … Мне нравится подход len (join (arr))> 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 

При написании 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 

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

 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 

Я просто вставляю ниже кода великий Чип Пирсон. Это работает.
Вот его страница о функциях массива .

Надеюсь, это поможет.

 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 

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

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

Вот простое, полное решение:

 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 

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

 Dim exampleArray() As Variant 'Any Type If ((Not Not exampleArray) = 0) Then 'Array is Empty Else 'Array is Not Empty End If 

Основываясь на ответе 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

 Public Function IsEmptyArray(InputArray As Variant) As Boolean On Error GoTo ErrHandler: IsEmptyArray = Not (UBound(InputArray) >= 0) Exit Function ErrHandler: IsEmptyArray = True End Function 

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

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

 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 

Чтобы проверить, является ли массив байтов пустым, самым простым способом является использование функции 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 

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

Я обобщу проблему и вопрос, как предполагалось. Тестирование в массиве и улавливание возможной ошибки

 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 … это возможно? в странности, да.

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

 if UBound(ar) > LBound(ar) Then 

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

Вы можете использовать функцию ниже, чтобы проверить, пуст ли пул версий или строк в 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) <= UBound(Arr, 1) End Function 

Пример использования

 Public Function test() Dim Arr(1) As String Arr(0) = "d" Dim x As Boolean x = IsArrayAllocated(Arr) End Function 

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

 if Ubound(yourArray)>-1 then debug.print "The array is not empty" else debug.print "EMPTY" end if 
 Function IsVarArrayEmpty(anArray As Variant) as boolean On Error Resume Next IsVarArrayEmpty = true IsVarArrayEmpty = UBound(anArray) < LBound(anArray) End Function 

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

Вы можете проверить его количество.

Здесь cid – массив.

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

Надеюсь, это поможет. Хорошего дня!

Другое решение для проверки пустого массива

 if UBound(ar) < LBound(ar) then msgbox "Your array is empty!" 

Или, если вы уже знаете, что LBound - 0

 if -1 = UBound(ar) then msgbox "Your array is empty!" 

Это может быть быстрее, чем join (). (И я не проверял с отрицательными индексами)

Вот мой пример для фильтрации 2 строковых массивов, чтобы они не делили одни и те же строки.

 ' Filtering ar2 out of strings that exists in ar1 For i = 0 To UBound(ar1) ' filter out any ar2.string that exists in ar1 ar2 = Filter(ar2 , ar1(i), False) If UBound(ar2) < LBound(ar2) Then MsgBox "All strings are the same.", vbExclamation, "Operation ignored": Exit Sub End If Next ' At this point, we know that ar2 is not empty and it is filtered ' 
 Public Function arrayIsEmpty(arrayToCheck() As Variant) As Boolean On Error GoTo Err: Dim forCheck forCheck = arrayToCheck(0) arrayIsEmpty = False Exit Function Err: arrayIsEmpty = True End Function 
  • Получение заголовков из документа Word
  • Параметры VBA, ADO.Connection и query
  • Дождитесь завершения Application.Calculate
  • Как скопировать данные из закрытых книг (их закрытие) в основную книгу с помощью VBA
  • Могу ли я запустить этот макрос быстрее?
  • Excel: поиск списка строк в определенной строке с использованием формул массива?
  • Условное форматирование с использованием кода Excel VBA
  • VBA-подзаголовок вне допустимого диапазона - ошибка 9
  • Хэш-таблица / ассоциативный массив в VBA
  • VBA потянув данные из SAP для манекенов
  • VBA Excel 2007 помогает ускорить код, чтобы скрыть строки
  • Interesting Posts

    Django 1.8: создать начальные миграции для существующей схемы

    OneDriveSetup.exe вызывает высокую загрузку процессора

    Что такое функция обратного вызова?

    Параметры индексирования Windows 10 не могут быть доступны (и поиск в Windows не работает)

    Есть ли способ использовать три языка клавиатуры, причем два из них могут переключаться с нажатием клавиши, а третья – с помощью горячей клавиши?

    Компьютер включается после любого режима

    Как избежать пробелов в командной строке в Windows без использования кавычек?

    Как отобразить два столбца ListView в Android?

    Мой 3TB HD не может использовать 3TB? (Только 2)

    определять интервалы последовательных целых последовательностей

    Является ли это специфичным для bash методом вызова скрипта: VARIABLE = value bash somescript

    Как использовать устаревший HTTP-клиент Apache на Android Marshmallow?

    iOS получить профили конфигурации, которые установлены

    Установка Windows без графической карты

    Какие клиенты bittorrent могут сначала загрузить фрагмент предварительного просмотра?

    Давайте будем гением компьютера.