Utiliser les variables tableaux en VBA Excel
Date de publication : 14/08/2007
Par
SilkyRoad (silkyroad.developpez.com)
Cet article propose une initiation aux variables tableaux, en VBA Excel.
I. Introduction
II. Description
II-A. Les tableaux de taille fixe
II-B. Les tableaux dynamiques
II-C. Les tableaux multidimensionnels
III. L'instruction ReDim
III-A. ReDim
III-B. Le mot clé Preserve
IV. Option Base
V. Les fonctions LBound et UBound
V-A. LBound
V-B. UBound
VI. La fonction Array
VII. La fonction IsArray
VIII. L'instruction Erase
IX. Les tableaux de type définis par l'utilisateur
X. Les tableaux de paramètres ParamArray
XI. La fonction Filter
XII. La fonction Join
XIII. Passer un tableau à une sous-procédure: utilisation de ByRef
XIV. Quelques exemples
XIV-A. Vérifier si un tableau est vide
XIV-B. Compter le nombre de doublons dans une plage
XIV-C. Alimenter une ListBox multicolonnes à partir d'un tableau
XIV-D. Trier les données d'un tableau
XIV-E. Compter le nombre de dimensions d'un tableau
XIV-F. Transférer le contenu d'un tableau dans une feuille de calcul
XIV-G. Créer un graphique à partir de variables tableaux
XV. Liens
XVI. Téléchargement
I. Introduction
Les variables tableaux servent à stocker et manipuler des groupes de données du même type.
Les éléments du tableau sont indexés séquentiellement. Chaque élément est identifiable par un
numéro d'indice. Les modifications apportées à une donnée du tableau n'affectent pas les
autres éléments.
Créer un tableau de taille X revient en quelque sort à déclarer X variables différentes, en une
fois.
Un tableau est constitué d'une ou plusieurs dimensions. Le nombre d'éléments pour chaque
dimension est défini par des limites inférieures et supérieures.
La taille et les dimensions peuvent être fixes (statiques) ou libres (dynamiques).
Seuls les tableaux dynamiques peuvent modifier leur taille et leur dimension en cours
de procédure.
Passer par un tableau n'est pas une obligation. Toutefois, cette méthode
permet des gains de temps significatifs, notamment pour la manipulation des grands groupes de
données. Sur les grandes collections, il convient d'éviter l'énumération qui est très lente.
Comparez la rapidité d'exécution du code entre:
| Vba |
Dim ObjCell As Range
For Each ObjCell In Range("A1:J65535").Cells
ObjCell.Value = ObjCell.Value * 2 + 3
Next
|
et
| Vba |
Dim Montab As Variant, cmpt1 As Long, cmpt2 As Long
Montab = Range("A1:J65535").Value
For cmpt1 = LBound(Montab, 1) To UBound(Montab, 1)
For cmpt2 = LBound(Montab, 2) To UBound(Montab, 2)
Montab(cmpt1, cmpt2) = Montab(cmpt1, cmpt2) * 2 + 3
Next cmpt2
Next cmpt1
Range("A1:J65535").Value = Montab
|
Le deuxième code s'exécute environ 20 fois plus vite.
II. Description
II-A. Les tableaux de taille fixe
Un tableau est dit de taille fixe lorsque ses dimensions sont prédéfinies au moment de
la déclaration de la variable.
La ligne de code suivante montre comment déclarer un tableau fixe.
Dim NomTableau(2) As String
L'indice
2 spécifie la taille du tableau.
L'indice inférieur d'un tableau peut commencer à 0 ou à 1 en fonction de la définition
de l'instruction
Option Base.
Pour obtenir plus de détails sur la gestion des indices, consultez les chapitres:
* Option Base
* LBound et UBound
As String définit le type de données.
Les tableaux se déclarent de la même façon que les autres variables.
Tous
les types de variables
peuvent être utilisés afin de déclarer un tableau.
Déclarez explicitement vos tableaux, avec un type de données adapté, afin d'optimiser
l'utilisation de l'espace mémoire.
Dans le premier exemple ci-dessous, 0 est le plus petit index du tableau, et 2 l'index
le plus élevé. Cela signifie que le tableau pourra contenir 3 éléments.
Cette procédure simplifiée montre comment alimenter les éléments du tableau et comment
boucler sur ces mêmes éléments afin d'en lire le contenu.
| Vba |
Option Explicit
Option Base 0
Sub MonPremierTableau()
Dim NomTableau(2) As String
Dim i As Integer
NomTableau(0) = "a"
NomTableau(1) = "b"
NomTableau(2) = "c"
For i = 0 To 2
MsgBox NomTableau(i)
Next i
End Sub
|
II-B. Les tableaux dynamiques
Si vous ne spécifiez pas la dimension au moment de la déclaration de la
variable, le tableau est appelé dynamique.
Ce type de tableau est utilisé lorsque l'on ne connait pas à l'avance la taille et/ou les
dimensions à attribuer.
Celles ci seront précisées en cours de procédure, grâce à l'instruction ReDIm.
Vous pouvez ainsi changer aussi souvent que vous le souhaitez:
* Le nombre de dimensions (Voir le chapitre 'Les tableaux
multidimensionnels').
* Le nombre d'éléments (Voir les chapitres 'ReDim', 'Option Base').
* Les limites supérieures et inférieures de chaque
dimension (Voir les chapitres 'Option Base', 'LBound et UBound').
Pour rendre un tableau dynamique, n'indiquez aucune valeur entre les parenthèses
(contrairement aux tableaux fixes) lorsque vous déclarez la variable.
Dim NomTableau() As String
Cet exemple montre comment définir la taille du tableau à partir de la variable "i".
Vous remarquerez qu'Option Base n'est pas précisé: 0 est donc le plus petit indice
(index) du tableau.
| Vba |
Option Explicit
Sub MonDeuxiemeTableau()
Dim NomTableau() As String
Dim i As Integer, j As Integer
i = 2
ReDim NomTableau(i)
For j = 0 To UBound(NomTableau)
NomTableau(j) = Chr(65 + j)
Next j
For j = 0 To UBound(NomTableau)
MsgBox NomTableau(j)
Next j
End Sub
|
C'est ReDim qui attribue de l'espace mémoire aux tableaux dynamiques.
Consultez le chapitre réservé à cette instruction pour plus de détails.
II-C. Les tableaux multidimensionnels
Tous les exemples vus jusqu'à présent étaient à dimension unique:
Dim NomTableau(2) As String 'déclare un tableau fixe
ReDim LeTableau(i) 'Redimensionne un tableau dynamique
De la même manière, il est possible de créer des tableaux multidimensionnels
statiques et dynamiques.
Vous pouvez déclarer jusqu'à 60 dimensions dans une variable tableau.
Il suffit d'insérer des virgules pour séparer chaque dimension, quand vous déclarez
le tableau.
Cet exemple déclare un tableau de 3 dimensions:
Dim NomTableau(5, 10, 20) As Integer
Le nombre total d'éléments disponible est donc le produit des tailles de toutes les
dimensions.
 |
Lorsque vous souhaitez agrandir un tableau dynamique tout en conservant les
données existantes, seule la dernière dimension peut être
redimensionnée
(Voir le chapitre ReDim Preserve pour plus de détails).
|
Utilisez des boucles imbriquées pour manipuler les tableaux à plusieurs dimensions.
| Vba |
Option Explicit
Sub ExempleTableau_MultiDimensionnel()
Dim i As Integer, j As Integer
Dim VarTab(1 To 3, 1 To 6) As String
For i = 1 To UBound(VarTab, 1)
For j = 1 To UBound(VarTab, 2)
VarTab(i, j) = i & j
Debug.Print VarTab(i, j)
Next j
Next i
End Sub
|
Le code suivant alimente chaque élément du tableau avec des lettres
aléatoires, entre A et Z.
Ensuite la macro trie par ordre croissant une des colonnes (au choix de l'utilisateur),
dans la 1ere dimension du tableau.
| Vba |
Option Explicit
Sub TriCroissantMulticolonnes()
Dim Tableau(1 To 4, 1 To 50) As String
Dim i As Integer, j As Integer, y As Integer
Dim indexColTri As Byte
Dim t As Variant
Dim Resultat As String
For i = 1 To UBound(Tableau, 2)
For j = 1 To UBound(Tableau, 1)
Randomize
Tableau(j, i) = Chr(Int((26 * Rnd) + 1) + 64)
Next j
Next i
indexColTri = 1
If indexColTri > UBound(Tableau, 1) Then Exit Sub
For i = 1 To UBound(Tableau, 2)
For j = 1 To UBound(Tableau, 2) - 1
If Tableau(indexColTri, j) > Tableau(indexColTri, j + 1) Then
For y = 1 To UBound(Tableau, 1)
t = Tableau(y, j)
Tableau(y, j) = Tableau(y, j + 1)
Tableau(y, j + 1) = t
Next y
End If
Next j
Next i
For i = 1 To UBound(Tableau, 2)
Resultat = ""
For j = 1 To UBound(Tableau, 1)
Resultat = Resultat & Tableau(j, i) & vbTab
Next j
Debug.Print Resultat
Next i
End Sub
|
III. L'instruction ReDim
III-A. ReDim
L'instruction ReDim est utilisée pour définir (ou redéfinir), en cours de
procédure, l'espace mémoire alloué à un tableau dynamique.
ReDim sert pour:
* Redéfinir le nombre d'éléments.
* Changer le nombre de dimensions.
* Etablir les limites supérieures et inférieures de chaque
dimension.
Exemple:
| Vba |
Option Explicit
Option Base 0
Sub Test()
Dim NomTableau() As Single
Dim i As Integer
ReDim NomTableau(2)
For i = 0 To UBound(NomTableau)
NomTableau(i) = (3 + i) / 2
Next i
End Sub
|
Vous pouvez appliquer l'instruction ReDim plusieurs fois dans une même procédure.
 |
A chaque fois que vous modifiez la taille d'un tableau, le contenu des anciens éléments
est effacé.
|
| Vba |
Option Explicit
Option Base 0
Sub Test()
Dim NomTableau() As String
Dim i As Integer
ReDim NomTableau(5)
For i = 0 To UBound(NomTableau)
NomTableau(i) = Chr(65 + i)
Next i
MsgBox "Premier élément du tableau: " & NomTableau(0)
ReDim NomTableau(3)
MsgBox "Premier élément du tableau: " & NomTableau(0)
End Sub
|
Attention à la saisie du nom de la variable tableau lorsque vous utilisez ReDim.
L'instruction a une action déclarative si la variable spécifiée n'existe pas formellement.
Même si Option Explicit est ajouté en tête de module, une erreur de saisie dans le
nom ne renverra pas de message d'erreur et un nouveau tableau sera créé.
| Vba |
Option Explicit
Sub Test()
Dim NomTableau() As Long
ReDim NomTablau(5)
End Sub
|
Lorsque vous appliquez ReDim sur des tableaux formalisés, vous pouvez modifier
le nombre d'éléments mais pas directement le type de données. Si vous souhaitez aussi
changer les types de données en cours de procédure, utilisez une variable Variant et
la syntaxe suivante:
| Vba |
Sub Test()
Dim NomVariable As Variant
Dim i As Integer
ReDim NomVariable(1 To 3) As String
For i = 1 To UBound(NomVariable)
NomVariable(i) = Chr(64 + 1)
Next i
ReDim NomVariable(1 To 2) As Integer
For i = 1 To UBound(NomVariable)
NomVariable(i) = i
Next i
End Sub
|
III-B. Le mot clé Preserve
Nous avons vu que l'instruction ReDim modifie la taille des tableaux, mais efface
les anciens éléments.
Ajoutez le mot clé Preserve pour agrandir un tableau dynamique tout en conservant
les valeurs existantes. Vous pourrez ainsi modifier la taille de la dernière dimension
d'un tableau sans perdre les données déjà stockées dans les éléments d'origine.
Cet exemple montre comment lister dans un tableau à deux dimensions, le nom des fichiers
d'un répertoire et leur date de création ou de dernière modification.
Comme le nombre de fichiers n'est pas connu à l'avance, la taille du tableau augmente d'une
unité à chaque tour de boucle, sans effacer les enregistrements qu'il contient déjà.
Vous remarquerez que c'est la dernière dimension du tableau (variable x) qui est modifiée.
| Vba |
Option Explicit
Sub ListeFichiersRepertoire()
Dim Repertoire As String, Fichier As String
Dim Tableau() As Variant
Dim x As Integer, i As Integer
Dim VerifTab As Variant
Repertoire = "C:\Documents and Settings\dossier"
Fichier = Dir(Repertoire & "\*.*")
Do While Fichier <> ""
x = x + 1
ReDim Preserve Tableau(1 To 2, 1 To x)
Tableau(1, x) = Fichier
Tableau(2, x) = FileDateTime(Repertoire & "\" & Fichier)
Fichier = Dir
Loop
On Error Resume Next
VerifTab = UBound(Tableau)
On Error GoTo 0
If IsEmpty(VerifTab) Then Exit Sub
For i = 1 To UBound(Tableau, 2)
Debug.Print Tableau(1, i) & " --> " & Tableau(2, i)
Next i
End Sub
|
Le mot clé Preserve:
* Permet uniquement de modifier la limite supérieure de la
dernière dimension du tableau.
* Ne permet pas de modifier le nombre de dimensions.
IV. Option Base
La limite inférieure des tableaux est définie
par l'instruction Option Base. La valeur peut être 0 ou 1.
La base par défaut est 0 si l'instruction n'est pas spécifiée dans le module.
Option Base doit être placée tout en haut du module, avant toute procédure ou
déclaration.
Celle ci est valable uniquement pour le module où elle est située.
Vous pouvez vérifier l'action d'Option Base en testant les deux codes suivants.
Le premier (base 0) renvoie des limites 0 et 5. Le tableau peut donc contenir 6 éléments.
| Vba |
Option Explicit
Option Base 0
Sub Test_Base()
Dim NomTableau(5) As String
MsgBox "Index inférieur: " & LBound(NomTableau) & vbCrLf & _
"Index supérieur: " & UBound(NomTableau)
End Sub
|
Le deuxième (base 1) renvoie des limites 1 et 5. Le tableau peut donc contenir 5 éléments.
| Vba |
Option Explicit
Option Base 1
Sub Test_Base()
Dim NomTableau(5) As String
MsgBox "Index inférieur: " & LBound(NomTableau) & vbCrLf & _
"Index supérieur: " & UBound(NomTableau)
End Sub
|
Pour vous affranchir des particularités d'Option Base, vous pouvez aussi utiliser
la clause To, afin de contrôler la plage des indices d'un tableau.
La syntaxe est: NomTableau(LimiteInférieure To LimiteSupérieure).
Dim NomTableau(1 To 5) As String
Pour définir un tableau multi dimensionnel:
Dim NomTableau(1 To 5, 1 To 20) As String
Cet exemple renvoie des limites 1 et 5:
| Vba |
Option Explicit
Sub Test_Base()
Dim NomTableau(1 To 5) As String
MsgBox "Index inférieur: " & LBound(NomTableau) & vbCrLf & _
"Index supérieur: " & UBound(NomTableau)
End Sub
|
V. Les fonctions LBound et UBound
Les fonctions LBound et UBound permettent de déterminer la taille d'une
dimension dans un tableau.
Leur principe d'utilisation est identique.
V-A. LBound
LBound Renvoie le plus petit indice disponible pour la dimension indiquée.
MsgBox LBound(NomTableau, 2)
Ici, la procédure affiche la limite inférieure de la 2eme dimension.
Utilisez LBound(NomTableau, 3) pour la 3eme dimension ...etc...
1 sera la valeur par défaut si l'argument dimension n'est pas spécifié.
Pour tester la première dimension (ou un tableau à dimension unique) vous pouvez donc écrire:
| Vba |
Option Explicit
Option Base 0
Sub Test_LBound()
Dim NomTableau() As Single
ReDim NomTableau(8)
MsgBox LBound(NomTableau, 1)
MsgBox LBound(NomTableau)
End Sub
|
La limite inférieure d'une dimension peut être:
* 0 ou 1, en fonction de la valeur de l'instruction Option Base
(Consultez le chapitre Option Base pour plus de détails).
* N'importe quelle valeur pour les dimensions définies à l'aide
de la clause To.
LBound provoque une erreur si les dimensions des tableaux n'ont pas été initialisées.
| Vba |
Option Explicit
Option Base 0
Sub Test_LBound()
Dim Tab_x() As Long
Dim Tab_y(1 To 20, 5 To 30) As Integer
Dim Tab_z(10) As String
ReDim Tab_x(5)
Debug.Print LBound(Tab_x)
Debug.Print LBound(Tab_y)
Debug.Print LBound(Tab_y, 2)
Debug.Print LBound(Tab_z)
ReDim Tab_x(4 To 8, 1 To 10, 1 To 20)
Debug.Print LBound(Tab_x)
Debug.Print LBound(Tab_x, 3)
End Sub
|
V-B. UBound
UBound Renvoie l'indice le plus élevé disponible pour la dimension indiquée.
MsgBox UBound(NomTableau, 2)
Ici, la procédure affiche la limite supérieure de la 2eme dimension.
Utilisez UBound(NomTableau, 3) pour la 3eme dimension ...etc...
1 sera la valeur par défaut si l'argument dimension n'est pas spécifié.
Pour tester la première dimension (ou un tableau à dimension unique) vous pouvez donc écrire:
| Vba |
Option Explicit
Option Base 0
Sub Test_UBound()
Dim NomTableau() As Single
ReDim NomTableau(8)
MsgBox UBound(NomTableau, 1)
MsgBox UBound(NomTableau)
End Sub
|
UBound provoque une erreur si les dimensions des tableaux n'ont pas été initialisées.
D'autres tests pour la fonction UBound:
| Vba |
Option Explicit
Option Base 0
Sub Test_UBound()
Dim Tab_x() As Long
Dim Tab_y(1 To 20, 5 To 30) As Integer
Dim Tab_z(10) As String
ReDim Tab_x(5)
Debug.Print UBound(Tab_x)
Debug.Print UBound(Tab_y)
Debug.Print UBound(Tab_y, 2)
Debug.Print UBound(Tab_z)
ReDim Tab_x(4 To 8, 1 To 10, 1 To 20)
Debug.Print UBound(Tab_x)
Debug.Print UBound(Tab_x, 3)
End Sub
|
VI. La fonction Array
La fonction Array permet de créer une liste d'éléments, séparés par des virgules.
L'utilisation est très diversifiée comme le montre ces quelques exemples:
| Vba |
ActiveWorkbook.SendMail Recipients:=Array("mimi@provider.com", "loulou@provider.fr"), _
Subject:="Rapport de visite " & ActiveWorkbook.Name, ReturnReceipt:=True
|
| Vba |
Worksheets(Array("Feuil2", "Feuil3")).Copy
|
| Vba |
Dim Ws As Worksheet
For Each Ws In ThisWorkbook.Worksheets(Array("Feuil5", "Feuil7", "Feuil8"))
Ws.Range("A1").Value = 1
Next Ws
|
| Vba |
Private Sub CommandButton1_Click()
Dim Ctrl As Variant
Dim j As Byte
For Each Ctrl In Array(TextBox1, TextBox3, TextBox5)
j = j + 1
Ctrl.Object.Value = "Champ" & j
Next
End Sub
|
Lorsque vous attribuez le tableau Array à une variable, celle ci doit impérativement être de
type Variant.
| Vba |
Option Explicit
Option Base 0
Sub ExempleArray_V01()
Dim NomTableau As Variant
NomTableau = Array("a", "b", "c")
MsgBox NomTableau(0)
MsgBox NomTableau(2)
End Sub
|
L'exemple suivant montre comment boucler sur le tableau:
| Vba |
Sub Exemple_BoucleArray()
Dim NomTableau As Variant
Dim i As Integer
NomTableau = Array("a", "b", "c")
For i = LBound(NomTableau) To UBound(NomTableau)
MsgBox NomTableau(i)
Next i
End Sub
|
Pour que l'instruction Option Base n'ait pas d'influence sur la fonction
Array, utilisez la syntaxe VBA.Array:
| Vba |
Option Explicit
Option Base 1
Sub ExempleArray_V01()
Dim NomTableau As Variant
NomTableau = VBA.Array("a", "b", "c")
MsgBox NomTableau(0)
MsgBox NomTableau(2)
End Sub
|
VII. La fonction IsArray
La fonction IsArray vérifie si une variable est un tableau. La valeur True est
renvoyée quand c'est le cas.
| Vba |
Sub VerifieExistenceTableau()
Dim Tableau(2) As String
Dim NomTableau As Variant
MsgBox IsArray(Tableau())
MsgBox IsArray(NomTableau)
NomTableau = Range("A1")
MsgBox IsArray(NomTableau)
NomTableau = Range("A1:B5")
MsgBox IsArray(NomTableau)
End Sub
|
Cette fonction est très pratique pour contrôler les variables