54 votes

Le remplissage de VBA tableaux dynamiques

Le code suivant me donne l'erreur 9 "indice hors de portée". Je voulais dire pour déclarer un tableau dynamique, de sorte que la dimension des changements comme je l'ai ajouter des éléments. Dois-je créer un "spot" sur le tableau avant que je stocker quelque chose en elle comme en JS?

Sub test_array()
    Dim test() As Integer
    Dim i As Integer
    For i = 0 To 3
        test(i) = 3 + i
    Next i
End Sub

73voto

Fluffi1974 Points 374

dans votre boucle pour utiliser un Redim sur le tableau comme ici:

For i = 0 to 3
  ReDim Preserve test(i)
  test(i) = 3 + i
Next i

26voto

a505999 Points 91

Affiche la première fois, longtemps le lecteur. Comme Cody et Brett mentionné, vous pourriez réduire le VBA ralentissement avec une utilisation raisonnable de l' Redim Preserve. Brett a suggéré Mod pour ce faire.

Vous pouvez également utiliser un définis par l'utilisateur Type et Sub pour ce faire. Envisager de mon code ci-dessous:

Public Type dsIntArrayType
   eElems() As Integer
   eSize As Integer
End Type

Public Sub PushBackIntArray( _
    ByRef dsIntArray As dsIntArrayType, _
    ByVal intValue As Integer)

    With dsIntArray
    If UBound(.eElems) < (.eSize + 1) Then
        ReDim Preserve .eElems(.eSize * 2 + 1)
    End If
    .eSize = .eSize + 1
    .eElems(.eSize) = intValue
    End With

End Sub

Cela exige ReDim Preserve seulement lorsque la taille a doublé. Le membre de la variable eSize permet de suivre les données réelles de la taille de l' eElems. Cette approche m'a permis d'améliorer les performances lors de la finale de la longueur du tableau n'est pas connue jusqu'à l'exécution.

Espérons que cela aide les autres aussi.

25voto

Cody Gray Points 102261

Oui, vous êtes à la recherche pour l' ReDim déclaration, qui alloue dynamiquement la quantité d'espace requise dans le tableau.

La déclaration suivante

Dim MyArray()

déclare un tableau sans dimensions, de sorte que le compilateur ne sait pas comment elle est grande et ne peut pas stocker quoi que ce soit à l'intérieur d'elle.

Mais vous pouvez utiliser l' ReDim déclaration pour redimensionner le tableau:

ReDim MyArray(0 To 3)

Et si vous avez besoin de redimensionner le tableau, tout en préservant son contenu, vous pouvez utiliser l' Preserve mot-clé le long de avec l' ReDim déclaration:

ReDim Preserve MyArray(0 To 3)

Mais notez que les deux ReDim et particulièrement ReDim Preserve ont un lourd coût de performance. Essayez d'éviter de faire ce cours et plus dans une boucle si possible; à vos utilisateurs de vous remercier.


Cependant, dans l'exemple illustré à votre question (si ce n'est pas simplement un jetable exemple), vous n'avez pas besoin d' ReDim à tous. Il suffit de déclarer le tableau explicite dimensions:

Dim MyArray(0 To 3)

14voto

brettdj Points 26353

En plus de Cody utiles commentaires, il est intéressant de noter que parfois vous ne connaissez pas la taille de votre tableau doit être. Les deux options sont dans cette situation sont

  1. La création d'un tableau suffisamment grand pour traiter tout ce que vous pensez être jetées
  2. Sensible de l'utilisation de Redim Preserve

Le code ci-dessous fournit un exemple d'une routine dimension myArray , en ligne avec l' lngSize variable, puis ajouter des éléments supplémentaires (égale à la première taille de la matrice) par l'utilisation d'un Mod test à chaque fois que la limite supérieure est sur le point d'être dépassé

Option Base 1

Sub ArraySample()
    Dim myArray() As String
    Dim lngCnt As Long
    Dim lngSize As Long

    lngSize = 10
    ReDim myArray(1 To lngSize)

    For lngCnt = 1 To lngSize*5
        If lngCnt Mod lngSize = 0 Then ReDim Preserve myArray(1 To UBound(myArray) + lngSize)
        myArray(lngCnt) = "I am record number " & lngCnt
    Next
End Sub

13voto

Petr Pivonka Points 1

Je vois beaucoup de (tous) les postes ci-dessus en s'appuyant sur LBound/UBound appelle encore potentiellement non initialisée VBA tableau dynamique, quelles sont les causes de l'application de la mort inévitable ...

Erratique code:

Dim x As Long Dim arr1() As SomeType ... x = UBound(arr1) 'crashes

Bon code:

Dim x As Long Dim arr1() As SomeType ... ReDim Preserve arr1(0 To 0) ... x = UBound(arr1)

... c'est à dire un code où l' Dim arr1() est suivie immédiatement par LBound(arr1)/UBound(arr1) des appels sans ReDim arr1(...) entre les deux, se bloque. Le rond-point est d'employer un On Error Resume Next et de vérifier l' Err.Number juste après l' LBound(arr1)/UBound(arr1) appelez -, il devrait être 0 si le tableau est initialisé, sinon non nulle. Comme il y a quelques VBA intégré de mauvaise conduite, le contrôle de la matrice de limites est nécessaire. Explication détaillée tout le monde peut lire à Puce de Pearson de site web (qui devrait être célébré comme un Trésor De l'Humanité VBA Sagesse ...)

Heh, c'est mon premier post, croire qu'il est lisible.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X