TL;DR —
Range("A1").Valuelit ou écrit une cellule. Ce qui compte, c'est ce qui se passe avec plusieurs cellules :arr = Range("A1:C1000").Valuelit tout le bloc dans un tableau Variant 2D en base 1 en un seul appel, etRange("A1:C1000").Value = arrle réécrit en un seul appel. Toucher les cellules une à une —Cells(i, j).Valuedans une boucle — franchit la frontière de VBA vers Excel à chaque lecture, et c'est ce franchissement, pas l'arithmétique, qui rend les grandes boucles lentes.
Dim v As Variant
v = Range("A1").Value ' lire une cellule dans une variable
Range("B1").Value = v * 1.08 ' ecrire une cellule
Dim arr As Variant
arr = Range("A1:A10000").Value ' lire 10 000 cellules en UN appel -> tableau 2D
' ... traiter arr en memoire ...
Range("C1:C10000").Value = arr ' tout reecrire en UN appel
Lire et écrire des valeurs est la première chose que fait quiconque en VBA, et pour une seule cellule
c'est exactement aussi simple que ça en a l'air. L'idée sur laquelle repose ce guide apparaît dès que
vous avez plus d'une cellule : .Value sur une plage n'est pas une valeur, c'est un bloc — un tableau
à deux dimensions — et déplacer ce bloc en un seul appel plutôt qu'une cellule à la fois, c'est la
différence entre une macro qui semble instantanée et une qui se fige. Tenez cela, et les règles de
vitesse comme les petits pièges de type se mettent en place.
Ce que vous allez apprendre
- Le modèle mental —
.Valueest un bloc, et une plage donne un tableau Variant 2D - La règle la plus importante — lire et écrire tout le bloc en un aller-retour, pas cellule par cellule
- Pourquoi le tableau est en base 1 et en 2D, même pour une seule colonne
- Le cas particulier de la cellule unique — une cellule est un scalaire, pas un tableau
.Valueest la propriété par défaut — le raccourci, et pourquoi ne pas s'y fier- Affecter une valeur remplace ce qui était dans la cellule, formule comprise
Le modèle mental : .Value est un bloc
Pour une seule cellule, .Value est une valeur unique que vous lisez ou affectez :
Dim name As String
name = Range("A1").Value ' scalaire en entree
Range("A2").Value = "Total" ' scalaire en sortie
Pour une plage de plusieurs cellules, .Value est toute la grille d'un coup. Lisez-la dans un
Variant et vous obtenez un tableau à deux dimensions ; affectez-lui un tableau à deux dimensions et
vous remplissez chaque cellule en un seul geste :
Dim block As Variant
block = Range("A1:C100").Value ' block est maintenant un tableau Variant 100 x 3
Le mot important est une fois. Chaque fois que votre code lit ou écrit .Value, il franchit la
frontière entre le moteur VBA et l'application Excel — un saut relativement coûteux. Une cellule, c'est
un saut ; tout un bloc lu dans un tableau, c'est aussi un saut. Ce seul fait — une plage est un bloc
que vous pouvez déplacer en un unique franchissement — gouverne la règle de performance ci-dessous et
c'est la chose la plus précieuse à savoir sur .Value.
La règle la plus importante : l'aller-retour par tableau, pas la boucle sur les cellules
Voici le même travail fait de deux façons. Additionner une colonne, en majorant chaque valeur de 8 % et en l'écrivant juste à côté.
La façon lente touche Excel à chaque itération :
Dim i As Long
For i = 1 To 10000
Cells(i, 3).Value = Cells(i, 1).Value * 1.08 ' 2 franchissements par ligne = 20 000 sauts
Next i
La façon rapide franchit la frontière deux fois en tout et fait le travail en mémoire :
Dim src As Variant, out() As Variant, i As Long
src = Range("A1:A10000").Value ' 1 saut a l'entree
ReDim out(1 To UBound(src, 1), 1 To 1)
For i = 1 To UBound(src, 1)
out(i, 1) = src(i, 1) * 1.08 ' pur VBA - aucun Excel implique
Next i
Range("C1:C10000").Value = out ' 1 saut a la sortie
L'arithmétique est identique ; la boucle a exactement la même longueur. La seule différence, c'est que la seconde version lit 10 000 cellules en un appel et en écrit 10 000 en un appel, tandis que la première effectue 20 000 trajets séparés à travers la frontière VBA-Excel. Sur des données réelles, la version par tableau est couramment des dizaines de fois plus rapide — souvent la différence entre « instantané » et « regardez tourner le sablier ». Pour un gain encore plus grand, associez-la à la désactivation du recalcul et du rafraîchissement de l'écran pendant l'écriture ; voir VBA Calculation et VBA ScreenUpdating. Le franchissement de la frontière est le coût, et l'aller-retour par tableau est la façon d'arrêter de le payer par cellule.
Pourquoi le tableau est en base 1 et en 2D
Le tableau Variant que vous rend une plage surprend deux fois. D'abord, il est toujours en base 1,
quel que soit le réglage Option Base — arr(1, 1) est la cellule en haut à gauche. Ensuite, il est
toujours à deux dimensions, même quand la plage est une seule colonne ou une seule ligne :
Dim col As Variant
col = Range("A1:A5").Value ' une seule colonne
Debug.Print col(3, 1) ' PAS col(3) - c'est (ligne, colonne)
Une plage d'une colonne est un tableau de 5 sur 1, que vous indexez donc col(ligne, 1) ; une plage
d'une ligne est de 1 sur 5, indexée ligne(1, colonne). Écrire col(3) au lieu de col(3, 1)
déclenche « Subscript out of range » et c'est l'erreur la plus fréquente quand on passe pour la
première fois aux tableaux. Si vous voulez réellement un tableau à une dimension à partir d'une seule
colonne, enveloppez la lecture dans Application.Transpose — mais sachez que Transpose a ses propres
limites (il plafonne autour de 65 536 éléments et convertit les types), si bien que pour de grandes
données ou des données mixtes, le tableau 2D simple est plus sûr. Voir
VBA Array pour exploiter le résultat.
Le cas particulier de la cellule unique
Il existe un cas limite qui casse le code à base de tableaux : si la plage est une cellule unique,
.Value renvoie un simple scalaire, pas un tableau de 1 sur 1.
Dim v As Variant
v = Range("A1").Value ' A1 seul -> un scalaire, pas v(1, 1)
' v(1, 1) ici declenche une erreur
Ainsi, un code qui lit rng.Value dans un tableau puis indexe arr(1, 1) fonctionne pour un rng de
plusieurs cellules mais explose quand rng se trouve être une seule cellule. Si la taille d'une plage
peut descendre jusqu'à une cellule, forcez une taille minimale, ou vérifiez rng.Cells.Count > 1 avant
de traiter le résultat comme un tableau. C'est une petite incohérence du modèle objet d'Excel, mais elle
provoque de vrais bugs du type « marche sur la grande feuille, échoue sur la petite ».
.Value est la propriété par défaut — le raccourci et son risque
.Value est la propriété par défaut d'un Range, ce qui veut dire qu'Excel vous laisse l'omettre :
x = Range("A1") ' fonctionne - implicitement .Value
Range("A1") = 42 ' fonctionne - implicitement .Value
Ça se lit proprement, et beaucoup de code le fait. Le risque, c'est que le raccourci masque quelle
opération vous voulez dire. Set rng2 = Range("A1") affecte l'objet Range ; x = Range("A1")
affecte sa valeur — la présence ou l'absence de Set change silencieusement le sens. Et
If Range("A1") = Range("B1") compare des valeurs, ce qui n'est pas forcément ce qu'un lecteur attend
quand le code ne dit rien des valeurs. L'habitude à garder : écrire .Value explicitement quand
vous voulez la valeur. Ça coûte six caractères et supprime toute une catégorie d'ambiguïté du genre
« voulaient-ils la cellule ou son contenu » — surtout autour de Set, traité dans
VBA Range.
Affecter une valeur remplace la formule
Un dernier point qui piège ceux qui mêlent valeurs et formules : écrire .Value dans une cellule
écrase ce qui s'y trouvait, formule comprise.
Range("D2").Formula = "=B2*C2" ' D2 contient maintenant une formule vivante
Range("D2").Value = 100 ' D2 est maintenant le nombre statique 100 - la formule a disparu
C'est en général ce que vous voulez — c'est exactement ainsi qu'on « convertit une formule en son
résultat » dans une seule cellule (réaffecter la valeur par-dessus elle-même). Mais cela signifie que
vous ne pouvez pas ajuster une valeur sans détruire la formule qui l'a produite. Quand il vous faut une
formule vivante dans la cellule, affectez .Formula, pas .Value — les deux sont des faces
différentes de la même cellule, traitées dans VBA Formula. Et quand le nombre
précis que vous relisez compte — argent, dates, longues décimales — le choix entre .Value et
.Value2 commence à peser, ce qui fait l'objet de
VBA Value vs Value2 vs Text.
Comment ExcelMaster aide
Les erreurs de .Value qui coûtent vraiment du temps ne sont pas des fautes de frappe — c'est la
boucle lente cellule par cellule sur une grande feuille, le arr(3) qui aurait dû être arr(3, 1), le
code à base de tableaux qui casse sur une plage d'une seule cellule, et le .Value implicite qui a
comparé la mauvaise chose sans bruit. Chacune s'exécute ; elle s'exécute juste mal ou lentement.
ExcelMaster écrit d'emblée la
version rapide et correcte. Demandez-lui de « majorer la colonne A de 8 % vers la colonne C », et il
lit le bloc dans un tableau Variant, le traite en mémoire, et le réécrit en une seule affectation — avec
le recalcul et le rafraîchissement de l'écran gérés autour de l'écriture. Il indexe correctement le
tableau 2D, protège le cas de la cellule unique, et écrit .Value explicitement pour que le code dise
ce qu'il veut dire. Vous décrivez la transformation ; il écrit l'aller-retour qui s'exécute en un clin
d'œil au lieu d'une boucle qui traîne.
Questions fréquentes
Comment obtenir la valeur d'une cellule en VBA Excel ?
Lisez la propriété Value d'un Range : x = Range("A1").Value ou x = Cells(1, 1).Value. Pour
plusieurs cellules d'un coup, lisez toute la plage dans un Variant — arr = Range("A1:C100").Value —
ce qui donne un tableau à deux dimensions en base 1 (arr(ligne, colonne)). Lire un bloc dans un
tableau est bien plus rapide que lire chaque cellule dans une boucle, car chaque accès individuel à
.Value franchit la frontière de VBA vers Excel.
Comment écrire une valeur dans une cellule en VBA ?
Affectez à Value : Range("A1").Value = 42 ou Cells(1, 1).Value = "Total". Pour écrire plusieurs
cellules d'un coup, construisez un tableau Variant 2D et affectez-le à une plage de même forme :
Range("A1:A100").Value = arr. Cela écrit les 100 cellules en une seule opération au lieu de boucler,
ce qui est radicalement plus rapide sur les grandes plages.
Pourquoi la valeur de ma plage VBA est-elle un tableau 2D ?
Parce qu'une plage de plusieurs cellules est une grille : son .Value est donc un tableau à deux
dimensions indexé arr(ligne, colonne) et toujours en base 1 — même une seule colonne est un tableau
de N sur 1, que vous indexez donc arr(3, 1), pas arr(3). Indexer avec un seul indice déclenche
« Subscript out of range ». La cellule unique est l'exception : Range("A1").Value renvoie un simple
scalaire, pas un tableau de 1 sur 1.
Pourquoi la lecture des cellules dans une boucle VBA est-elle si lente ?
Chaque accès Cells(i, j).Value franchit la frontière entre le moteur VBA et l'application Excel, et
c'est ce saut qui coûte cher — pas l'arithmétique. Une boucle sur 10 000 lignes qui lit et écrit chaque
cellule effectue 20 000 franchissements. Lire la plage dans un tableau, la traiter en mémoire, puis
réécrire le tableau ne fait que deux franchissements, et c'est pourquoi c'est souvent des dizaines de
fois plus rapide.
Quelle est la différence entre .Value et un simple Range("A1") en VBA ?
.Value est la propriété par défaut d'un Range, donc x = Range("A1") est traité comme
x = Range("A1").Value. Les deux se lisent pareil pour les valeurs, mais omettre .Value masque votre
intention : Set rng = Range("A1") affecte l'objet Range, tandis que x = Range("A1") affecte sa
valeur, et la seule différence est le mot-clé Set. Écrire .Value explicitement rend le code sans
ambiguïté.
Testé dans
Testé dans : Excel 365 (Windows 11), VBA 7.1 — vérifié le 31/08/2026.
Guides connexes : VBA Range · VBA Cells · VBA Formula · VBA Value vs Value2 vs Text · VBA Array
