🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

VBA 2D Arrays dans Excel — Tableaux à deux dimensions, grilles et Range.Value

|

VBA 2D Arrays dans Excel — Tableaux à deux dimensions, grilles et Range.Value

TL;DR — Un tableau 2D VBA est un seul tableau à deux indices — une grille de lignes et de colonnes, g(row, column) — et non un tableau de tableaux. Dim g(1 To 3, 1 To 4), c'est trois lignes sur quatre colonnes. Le fait le plus utile pour le travail dans Excel : lire Range("A1:D3").Value vous remet un tableau Variant à deux dimensions basé sur 1 en une seule étape, et réécrire un tableau avec Range(...).Value = arr l'écrit en une seule étape — c'est pourquoi le traitement par tableau est radicalement plus rapide que de boucler cellule par cellule.

Sub SheetToArrayAndBack()
    Dim data As Variant
    data = Range("A1:D100").Value          ' un seul acces a la feuille -> tableau 2D base sur 1

    Dim r As Long
    For r = 1 To UBound(data, 1)           ' lignes
        data(r, 4) = data(r, 2) * data(r, 3)   ' col D = col B * col C, en memoire
    Next r

    Range("A1:D100").Value = data          ' un seul acces retour -> instantane
End Sub

Un tableau 2D, c'est le point de rencontre des tableaux et des feuilles de calcul : une feuille est une grille, et la façon la plus rapide de travailler sur un bloc de cellules est de le charger dans un tableau 2D, de calculer en mémoire, puis de le réécrire. Cela s'appuie directement sur le dimensionnement des tableaux avec ReDim et la lecture de leur forme avec UBound — une grille a simplement une borne par dimension. La seule chose qui piège les gens, c'est que les tableaux issus de Range.Value sont basés sur 1, et que ReDim Preserve ne peut pas ajouter de lignes.

Ce que vous allez apprendre

  • Le modèle mental — une grille à deux indices, g(row, column), et non des tableaux imbriqués
  • Déclarer et adresser un tableau 2D avec Dim g(1 To 3, 1 To 4) et g(r, c)
  • Le gros morceau : Range.Value vous donne un tableau Variant 2D basé sur 1 en une seule étape
  • Réécrire un tableau vers une plage en une seule fois — et pourquoi c'est tellement plus rapide
  • Deux cas limites : une cellule unique n'est pas un tableau, et une colonne unique est (n, 1)
  • Ajouter des lignes : pourquoi ReDim Preserve ne le peut pas, et quoi faire à la place
  • En quoi un « tableau de tableaux » irrégulier diffère d'un vrai tableau 2D

Le modèle mental : un tableau, deux indices

Un tableau à une dimension est une rangée numérotée de cases : a(i). Un tableau à deux dimensions est une grille — vous adressez chaque case avec deux nombres, une ligne et une colonne : g(r, c). Point crucial, c'est un seul tableau qui se trouve être adressé de deux façons, et non une liste dont les éléments sont eux-mêmes des listes :

Dim g(1 To 3, 1 To 4) As Long   ' 3 lignes, 4 colonnes = 12 elements
g(1, 1) = 10                     ' ligne 1, colonne 1
g(3, 4) = 99                     ' ligne 3, colonne 4

Le premier indice est par convention la ligne, le second la colonne — le même ordre que celui dans lequel vous lisez une référence de cellule. Gardez cet ordre cohérent et un tableau 2D se met proprement en correspondance avec un bloc rectangulaire de cellules.

Déclarer et parcourir une grille

Déclarez les deux bornes, puis bouclez avec un For imbriqué — l'extérieur sur les lignes, l'intérieur sur les colonnes — en utilisant UBound avec un numéro de dimension :

Dim g(1 To 3, 1 To 4) As Long
Dim r As Long, c As Long
For r = LBound(g, 1) To UBound(g, 1)       ' lignes
    For c = LBound(g, 2) To UBound(g, 2)   ' colonnes
        g(r, c) = r * 10 + c
    Next c
Next r

UBound(g, 1) est le nombre de lignes, UBound(g, 2) le nombre de colonnes. Boucler de LBound à UBound sur chaque dimension signifie que le même code fonctionne que le tableau soit 1 To n (comme Range.Value vous le donne) ou basé sur zéro.

Le gros morceau : Range.Value est un tableau 2D basé sur 1

C'est le fait qui rend les tableaux 2D dignes d'être appris. Lire le .Value d'une plage de plusieurs cellules vous donne, en une seule étape, un tableau Variant à deux dimensions dont les bornes commencent à 1 — peu importe où la plage se situe sur la feuille :

Dim data As Variant
data = Range("C5:E7").Value      ' un bloc de 3 lignes, 3 colonnes n'importe ou sur la feuille
' data vaut maintenant data(1 To 3, 1 To 3) - TOUJOURS base sur 1, ligne puis colonne
Debug.Print data(1, 1)          ' la valeur de C5
Debug.Print data(3, 3)          ' la valeur de E7

Notez deux choses. D'abord, le tableau est basé sur 1, pas sur 0 — donc data(1, 1) est la cellule en haut à gauche, et une boucle For i = 0 manquerait la première ligne et tomberait sur l'erreur 9. Ensuite, les indices sont relatifs au bloc, pas à la feuille : data(1, 1) est la cellule en haut à gauche de la plage, que la plage soit A1 ou C5. Déclarez la variable de réception comme Variant (pas As Long() etc.) — VBA vous remplit un nouveau Variant 2D.

Réécrivez-le en une seule fois

La même astuce fonctionne en sens inverse. Affectez un tableau 2D à la forme correcte au .Value d'une plage et Excel écrit tout le bloc d'un coup :

Range("C5:E7").Value = data     ' ecrit les 9 cellules en une seule operation

C'est pourquoi l'approche par tableau est rapide. Toucher les cellules une par une franchit la frontière entre VBA et Excel à chaque lecture et à chaque écriture — des milliers d'allers-retours pour une grande plage. Lire dans un tableau, calculer en mémoire, puis réécrire, cela ne fait que deux franchissements en tout. Au-delà de quelques centaines de cellules, c'est la différence entre une macro qui paraît instantanée et une que vous regardez ramer. La plage écrite doit correspondre à la forme du tableau (lignes × colonnes), alors dimensionnez la plage cible à UBound(arr, 1) lignes sur UBound(arr, 2) colonnes.

Deux cas limites qui piquent

Une cellule unique n'est pas un tableau. Range("A1").Value renvoie un simple scalaire, pas un tableau 1 To 1, 1 To 1 — si bien qu'un code qui suppose un tableau échouera sur une plage d'une seule cellule. Si la plage peut être une cellule unique, testez avec IsArray() avant de l'indexer.

Une seule ligne ou colonne reste 2D. Range("A1:A10").Value vaut data(1 To 10, 1 To 1) — dix lignes, une colonne — vous l'adressez donc toujours comme data(i, 1), pas data(i). Il en va de même pour une seule ligne : data(1, j). Il est facile d'oublier le second indice sur une tranche « unidimensionnelle » d'une feuille.

Ajouter des lignes : ReDim Preserve ne le peut pas

Parce que ReDim Preserve ne redimensionne que la dernière dimension, vous ne pouvez pas augmenter le nombre de lignes (la première dimension) d'un tableau 2D tout en conservant les données. Trois options pratiques :

  • Dimensionner une fois. Si vous connaissez le nombre de lignes d'emblée (une dernière ligne, un nombre d'enregistrements), faites un ReDim de la grille à sa taille finale avant la boucle et jamais de Preserve.
  • Agrandir plutôt les colonnes. Déclarez le tableau en colonnes × lignes pour que la dimension que vous étendez soit la dernière, puis transposez à la sortie avec Application.Transpose.
  • Reconstruire. Pour une croissance vraiment inconnue, collectez dans une Collection ou une structure irrégulière et construisez le tableau 2D une seule fois à la fin.

Pour le travail sur feuille, la première option s'applique presque toujours, car le nombre de lignes est une chose peu coûteuse à connaître avant de commencer.

Les tableaux irréguliers sont autre chose

Un vrai tableau 2D est rectangulaire — chaque ligne a le même nombre de colonnes. Un tableau irrégulier (jagged) est un tableau à une dimension dont les éléments sont eux-mêmes des tableaux, si bien que chaque « ligne » peut avoir une longueur différente. Vous l'adressez avec deux paires de crochets, pas deux indices :

Dim jagged(1 To 2) As Variant
jagged(1) = Array(1, 2, 3)      ' une ligne de 3 elements
jagged(2) = Array(9, 8)         ' une ligne de 2 elements
Debug.Print jagged(1)(3)        ' 3   <- deux paires de crochets, pas (1, 3)

Les tableaux irréguliers sont pratiques pour des données en dents de scie, mais ils n'interagissent pas avec Range.Value, qui est toujours rectangulaire. Quand les données forment un rectangle — ce qu'un bloc de feuille est toujours — optez pour un vrai tableau 2D.

Comment ExcelMaster vous aide

Travailler efficacement sur un bloc de cellules tient en un seul motif — lire Range.Value dans un tableau 2D basé sur 1, calculer en mémoire, le réécrire en une seule fois — et les pièges sont tous dans les détails : l'indice basé sur 1, le scalaire de la cellule unique, la ligne que vous ne pouvez pas agrandir avec Preserve.

ExcelMaster vous laisse décrire la tâche — « pour chaque ligne de la plage utilisée, mets la quantité fois le prix dans la colonne E » — et il lit le bloc dans un tableau 2D, boucle de 1 à UBound(arr, 1), réécrit le résultat en une seule affectation, et gère les cas de la cellule unique et de la colonne unique, si bien que la macro est à la fois correcte et rapide. Vous gardez le classeur et le code.

Questions fréquentes

Comment déclarer un tableau 2D en VBA ?

Donnez deux bornes séparées par une virgule : Dim g(1 To 3, 1 To 4) As Long crée une grille de trois lignes et quatre colonnes. Adressez un élément avec deux indices, g(row, column), par exemple g(2, 3). Pour un tableau 2D dynamique, déclarez-le ouvert avec Dim g() et dimensionnez-le plus tard avec ReDim g(1 To 3, 1 To 4).

Comment lire une plage dans un tableau 2D en VBA ?

Affectez le .Value de la plage à un Variant : Dim data As Variant: data = Range("A1:D100").Value. VBA remplit un tableau à deux dimensions basé sur 1, data(1 To rows, 1 To columns), en une seule étape. Adressez les cellules comme data(row, column), où les indices sont relatifs au coin supérieur gauche de la plage. C'est la façon la plus rapide de traiter de nombreuses cellules.

Pourquoi mon tableau Range.Value est-il basé sur 1 plutôt que sur 0 ?

Parce que c'est ainsi qu'Excel le renvoie — un tableau Range.Value commence toujours à l'indice 1 sur les deux dimensions, peu importe où se trouve la plage sur la feuille. Bouclez de LBound(data, 1) à UBound(data, 1) (ou simplement 1 To UBound) pour ne pas sauter la première ligne ni dépasser la fin avec une boucle basée sur 0.

Comment réécrire un tableau 2D vers une plage ?

Affectez-le au .Value de la plage : Range("A1:D100").Value = data. La plage doit avoir la même forme que le tableau — le même nombre de lignes et de colonnes — alors dimensionnez la cible avec UBound(data, 1) lignes et UBound(data, 2) colonnes. Cela écrit tout le bloc en une seule opération, bien plus vite que cellule par cellule.

Puis-je ajouter une ligne à un tableau 2D en VBA ?

Pas avec ReDim Preserve — il ne peut redimensionner que la dernière dimension (les colonnes), si bien qu'augmenter le nombre de lignes lève l'erreur 9. Soit dimensionnez le tableau à son nombre de lignes final avant la boucle, soit déclarez-le en colonnes × lignes et transposez, soit construisez-le à partir d'une Collection et créez le tableau 2D une seule fois à la fin.

Testé dans

Testé dans : Excel 365 (Windows 11), VBA 7.1 — vérifié le 24/09/2026.

Guides associés : VBA ReDim · VBA UBound · VBA Array · VBA For Loop · VBA Range