Как проверить наличие пустого массива в макросе vba - PullRequest
56 голосов
/ 16 октября 2008

Я хочу проверить наличие пустых массивов. 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 пусто. Есть ли способ избежать этого?

Ответы [ 23 ]

73 голосов
/ 16 октября 2008

Когда вы работаете с массивом строк, рассматривали ли вы Join?

If Len(Join(FileNamesList)) > 0 Then
61 голосов
/ 17 января 2013

С тройным отрицанием:

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. Вы можете Not это XOR это с -1, возвращая ноль, если вы предпочитаете.

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

Источник

28 голосов
/ 06 марта 2009

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

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
6 голосов
/ 27 июня 2015

Здесь я вижу похожие ответы ... но не мои ...

Вот как я, к сожалению, собираюсь разобраться с этим ... Мне нравится подход len (join (arr))> 0, но он не сработал бы, если бы массив представлял собой массив пустых строк ...

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
5 голосов
/ 01 апреля 2011

Когда я пишу 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
4 голосов
/ 30 сентября 2013

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

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

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
4 голосов
/ 16 октября 2008

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

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
2 голосов
/ 08 апреля 2014

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
2 голосов
/ 16 июля 2017

На основании ответа Ахута ;

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

2 голосов
/ 21 октября 2014

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

Dim exampleArray() As Variant 'Any Type

If ((Not Not exampleArray) = 0) Then
      'Array is Empty
Else
      'Array is Not Empty
End If
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...