web-dev-qa-db-fra.com

Comment vérifier le tableau vide dans la macro vba

Je veux vérifier les tableaux vides. Google m'a donné des solutions variées mais rien n'a fonctionné. Peut-être que je ne les applique pas correctement.

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

Ici, si FileNamesList tableau est vide, GetBoiler(SigString) ne devrait pas être appelé du tout. Lorsque FileNamesList tableau est vide, SigString est également vide et appelle la fonction GetBoiler() avec une chaîne vide. Je reçois une erreur à la ligne

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

puisque sFile est vide. Un moyen d'éviter cela?

56
Vicky

Comme vous avez affaire à un tableau de chaînes, avez-vous envisagé de rejoindre?

If Len(Join(FileNamesList)) > 0 Then
73
Fionnuala

Aller avec un triple négatif:

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

Ou juste:

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

En VB, pour une raison quelconque, Not myArray renvoie le pointeur SafeArray. Pour les tableaux non initialisés, cela renvoie -1. Vous pouvez Not this à XOR le avec -1, renvoyant ainsi zéro, si vous préférez.

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

Source

62
ahuth

Si vous testez une fonction de tableau, cela fonctionnera pour toutes les limites:

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
28
Lance Roberts

Je vois des réponses similaires ici ... mais pas les miennes ...

C’est ainsi que je vais malheureusement y faire face ... j’aime l’approche len (join (arr))> 0, mais cela ne fonctionnerait pas si le tableau était un tableau de chaînes vide ...

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
6
Perposterer

Lors de l'écriture de VBA, il y a cette phrase dans ma tête: "Cela pourrait être si facile, mais ..."

Voici ce que je l'ai adopté pour:

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
5
BBQ Chef

Ce code ne fait pas ce que vous attendez:

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

Si vous passez une chaîne vide ("") ou vbNullString à Dir, il renverra le nom du premier fichier du chemin du répertoire actuel (le chemin renvoyé par CurDir$). Donc, si SigString est vide, votre condition If sera évaluée à True car Dir retournera une chaîne non vide (le nom du premier fichier dans le répertoire en cours), et GetBoiler sera appelé. Et si SigString est vide, l’appel à fso.GetFile va échouer.

Vous devriez soit changer votre condition pour vérifier que SigString n'est pas vide, soit utiliser le FileSystemObject.FileExists méthode au lieu de Dir pour vérifier si le fichier existe. Dir est difficile à utiliser avec précision, car il fait des choses que vous ne pensiez pas forcément faire. Personnellement, j'utiliserais Scripting.FileSystemObject over Dir car il n’ya pas d’affaires amusantes (FileExists renvoie True si le fichier existe et, bien, False s’il n’existe pas). De plus, FileExists exprime clairement l'intention de votre code bien que Dir.

Méthode 1: Vérifiez que SigString est d'abord non vide

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

Méthode 2: utilisez le FileSystemObject.FileExists méthode

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

If fso.FileExists(SigString) Then
    Signature = GetBoiler(SigString) 
Else
    Signature = "" 
End If
4
Mike Spross

Je suis simplement en train de coller ci-dessous le code du grand Chip Pearson. Cela fonctionne un charme.
Voici son page sur les fonctions du tablea .

J'espère que ça aide.

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
sancho.s

Auth était le plus proche, mais sa réponse soulève une erreur d’écart type.

En ce qui concerne les autres réponses, vous devriez éviter d'utiliser une erreur pour tester une condition, si vous le pouvez, car au moins, cela complique le débogage (que se passe-t-il si quelque chose d'autre provoque cette erreur)?.

Voici une solution simple et complète:

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
Mike Bethany

Vérification simplifiée pour tableau vide:

Dim exampleArray() As Variant 'Any Type

If ((Not Not exampleArray) = 0) Then
      'Array is Empty
Else
      'Array is Not Empty
End If
2
Robert S.

Basé sur ahuth's réponse ;

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

Recherchez un tableau vide. is_empty = AryLen(some_array)=0

2
user425678

Pour vérifier si un tableau d'octets est vide, le moyen le plus simple consiste à utiliser la fonction VBA StrPtr().

Si le tableau d'octets est vide, StrPtr() renvoie 0; sinon, il renvoie une valeur non nulle (cependant, il est ne pas l'adresse au premier élément).

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

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

Cependant, cela ne fonctionne qu'avec le tableau Byte.

1
Fuzzier

Une autre méthode serait de le faire plus tôt. Vous pouvez créer une variable booléenne et la définir sur true une fois que vous avez chargé des données dans le tableau. vous n'avez donc besoin que d'une simple instruction if indiquant le moment où vous chargez des données dans le tableau.

1
Tim Boutchia
Public Function IsEmptyArray(InputArray As Variant) As Boolean

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

   ErrHandler:
   IsEmptyArray = True

End Function
1
Zhenya

Voici une autre façon de le faire. Je l'ai utilisé dans certains cas et ça marche.

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
1
Surya
Function IsVarArrayEmpty(anArray As Variant) as boolean
    On Error Resume Next
    IsVarArrayEmpty = true
    IsVarArrayEmpty = UBound(anArray) < LBound(anArray)
End Function

Peut-être que ubound se bloque et reste à vrai, et si ubound < lbound, c'est vide

1
Pierre

Vous pouvez vérifier son compte.

Ici cid est un tableau.

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

J'espère que ça aide. Bonne journée!

0
Mantej Singh

Vous pouvez vérifier si le tableau est vide en récupérant le nombre total d'éléments à l'aide de l'objet VBArray() de JScript (fonctionne avec les tableaux de type variant, simples ou multidimensionnels):

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

Pour moi, il faut environ 0,3 mksec pour chaque élément + 15 ms d’initialisation, donc le tableau de 10 M d’éléments prend environ 3 secondes. La même fonctionnalité pourrait être implémentée via ScriptControl ActiveX (elle n'est pas disponible dans les versions MS Office 64 bits, vous pouvez donc utiliser une solution de contournement comme this ).

0
omegastripes
if Ubound(yourArray)>-1 then
 debug.print "The array is not empty"
else
 debug.print "EMPTY"
end if
0
Dave Poole

Je vais généraliser le problème et la question comme prévu. Testez l'évaluation sur le tableau et détectez l'erreur éventuelle

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

Bien sûr, il manque des tableaux avec tous les index négatifs ou tous les> 1 ... est-ce probable? au pays étrange, oui.

0
jpinto3912

Personnellement, je pense qu'une des réponses ci-dessus peut être modifiée pour vérifier si le tableau a un contenu:

if UBound(ar) > LBound(ar) Then

Cela gère les références numériques négatives et prend moins de temps que certaines des autres options.

0
Jim Snyder

Vous pouvez utiliser la fonction ci-dessous pour vérifier si le variant ou le tableau de chaînes est vide dans 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

Utilisation de l'échantillon

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