TL;DR —
For Each item In collectionparcourt chaque membre d'une collection et vous les remet un à un — sans compteur, sans.Count, sans décalage d'une unité. Utilisez-le quand vous avez une collection (unRange, lesWorksheets, un tableau) et que vous voulez toucher chaque élément. Ne revenez àFor i = 1 To Nque lorsque vous avez besoin de l'indice lui-même : pour parcourir à l'envers, pour sauter avecStep, ou pour supprimer des éléments au fil de l'eau. Trois règles l'empêchent de vous trahir : la variable de boucle doit être un objet ou unVariant, parcourir un tableau est en lecture seule, et vous ne devez jamais retirer d'éléments de la collection que vous parcourez.
Dim cell As Range
Dim total As Double
For Each cell In Sheets("Data").Range("B2:B11")
total = total + cell.Value ' VBA vous remet chaque cellule à son tour
Next cell
Debug.Print total ' pas de i, pas de .Count, aucune borne à rater
La plupart des boucles des vraies macros disent au fond la même chose : « pour
chaque cellule de cette plage… », « pour chaque feuille de ce classeur… », « pour
chaque nom de cette liste… ». For Each, c'est VBA qui vous laisse écrire cette
phrase presque littéralement. Le For i = 1 To N à compteur peut exprimer la même
idée, mais il vous laisse gérer vous-même l'indice — valeur de départ, valeur de
fin, le .Count, le décalage d'une unité. For Each vous décharge de cette
comptabilité. Le revers, c'est qu'il vous retire l'indice entièrement, et
quelques opérations en ont réellement besoin.
Ce que vous allez apprendre
- Le modèle mental —
For Eachparcourt l'appartenance, pas les positions - Pourquoi la variable de boucle doit être un
Range, unWorksheetou unVariant— jamais unLong - Le piège de la lecture seule : affecter la variable de boucle d'un tableau ne fait rien
- Pourquoi supprimer à l'intérieur d'un
For Eachcorrompt silencieusement le parcours — et que faire à la place - Une règle claire pour choisir
For Eachou revenir àFor…Next
Le modèle mental : For Each parcourt l'appartenance, pas les positions
Une boucle à compteur pense en positions : « va à la case 1, puis à la case 2,
puis à la case 3 ». For Each pense en appartenance : « donne-moi chaque chose
qui appartient à ce groupe, dans l'ordre où le groupe les conserve ». Vous ne
dites jamais où se trouve un élément ; vous le recevez, tout simplement.
Ce basculement explique pourquoi For Each est plus court et, sur de grandes
plages, légèrement plus rapide. Avec Cells(i, 1), VBA doit calculer l'adresse et
résoudre la cellule à chaque itération. Avec For Each cell In rng, l'énumérateur
intégré de la collection vous remet à chaque fois un objet Range déjà résolu —
aucun calcul. Vous échangez le numéro d'indice contre un parcours plus propre et
plus rapide. Tout ce qui suit découle de l'absence de cet indice.
La règle qui décide du type de la variable de boucle : objet ou Variant, jamais Long
C'est la première chose qui fait trébucher, car c'est l'inverse d'une boucle à
compteur. Dans For i = 1 To 10, i est un Long. Dans un For Each, la
variable de boucle reçoit un élément entier de la collection : elle doit donc
pouvoir le contenir :
' Plage de cellules -> l'élément est un Range
Dim cell As Range
For Each cell In Range("A1:A10")
cell.Value = cell.Value * 2
Next cell
' Worksheets -> l'élément est un Worksheet
Dim ws As Worksheet
For Each ws In ThisWorkbook.Worksheets
Debug.Print ws.Name
Next ws
Déclarez Dim cell As Long pour parcourir une plage et VBA lève « Objet
requis » (erreur 424) à l'instant où il tente de fourrer un Range dans un
nombre. La règle : le type de la variable de boucle doit correspondre au genre
de chose que contient la collection — Range pour des cellules, Worksheet
pour des feuilles, Workbook pour des classeurs ouverts.
Il existe une exception, et c'est celle qu'on oublie : les tableaux. Un
tableau VBA peut tout contenir, si bien que le compilateur ne peut pas connaître
le type d'élément à l'avance. Parcourir un tableau avec For Each exige un
Variant :
Dim names As Variant
names = Array("Alice", "Bob", "Carol")
Dim n As Variant ' OBLIGATOIREMENT un Variant pour parcourir un tableau
For Each n In names
Debug.Print n
Next n
Utilisez Dim n As String ici et vous obtiendrez une erreur d'incompatibilité de
type. Dans le doute sur un tableau, la variable de boucle est un Variant.
La règle qui piège tout le monde une fois : parcourir un tableau est en lecture seule
Voici un bug qui semble devoir fonctionner et n'en fait rien :
Dim nums As Variant
nums = Array(1, 2, 3)
Dim x As Variant
For Each x In nums
x = x * 10 ' on croit multiplier chaque élément...
Next x
Debug.Print nums(0), nums(1), nums(2) ' -> 1 2 3 (INCHANGÉ)
Vous avez multiplié x, pas le tableau. Quand For Each parcourt un tableau,
la variable de boucle est une copie de l'élément, pas une prise en direct sur
lui. Affecter x modifie la copie et la jette à l'itération suivante. Le tableau
ne bouge jamais.
C'est la chose la plus importante à savoir sur For Each, car elle échoue en
silence — aucune erreur, juste des données périmées. La solution est de revenir à
une boucle à compteur, qui atteint le véritable élément par son indice :
Dim i As Long
For i = LBound(nums) To UBound(nums)
nums(i) = nums(i) * 10 ' CECI modifie réellement le tableau
Next i
Notez l'asymétrie : parcourir un Range avec For Each est modifiable
(cell.Value = … traverse l'objet Range jusqu'à la vraie cellule), car cell
est une référence d'objet, pas une copie. Ce sont spécifiquement les tableaux —
et les éléments de type valeur — qui sont en lecture seule sous For Each. Si
votre boucle doit réécrire le contenu d'un tableau, utilisez
For i = LBound To UBound.
La règle qu'on apprend à ses dépens : ne jamais supprimer de la collection que vous parcourez
For Each s'appuie sur l'énumérateur de la collection, et cet énumérateur suppose
que la collection ne change pas de forme sous ses pieds. Retirez un élément en
plein parcours et l'énumérateur perd sa place — il saute des éléments, ou lève une
erreur, et il ne vous dit jamais lesquels.
' CASSÉ — supprimer décale la collection sous l'énumérateur
Dim sh As Worksheet
For Each sh In ThisWorkbook.Worksheets
If sh.Name Like "Temp*" Then sh.Delete ' saute des feuilles, imprévisible
Next sh
Le même piège vous attend quand vous supprimez des lignes de feuille, retirez des
éléments d'une Collection ou enlevez des clés d'un Dictionary à l'intérieur
d'un For Each. La règle est absolue : si la boucle modifie l'appartenance de
la collection, n'utilisez pas For Each. Parcourez-la plutôt avec un compteur
à l'envers, de sorte que retirer un élément ne perturbe jamais les indices que
vous n'avez pas encore visités :
' CORRECT — décompter pour que les suppressions ne décalent pas le reste
Dim i As Long
For i = ThisWorkbook.Worksheets.Count To 1 Step -1
With ThisWorkbook.Worksheets(i)
If .Name Like "Temp*" Then .Delete
End With
Next i
C'est la même discipline de parcours inversé que vous employez pour supprimer des
lignes de tableur sans risque — voyez le motif Step -1 dans
VBA For Loop. L'idée directrice : For Each sert à lire
et modifier des éléments en place ; une boucle à compteur décroissante sert à en
ajouter ou en retirer.
Quand choisir For Each plutôt que For…Next
Aucune des deux boucles n'est « meilleure » — elles répondent à des questions différentes. Choisissez selon ce que la tâche exige de l'indice :
- Utilisez
For Eachquand vous avez une collection et voulez toucher chaque membre dans son ordre naturel : sommer une plage, mettre en forme chaque cellule, afficher le nom de chaque feuille, traiter chaque élément une fois. Plus lisible, aucune borne à rater, et plus rapide sur de grandes plages. - Utilisez
For i = 1 To Nquand vous avez besoin de l'indice comme valeur — pour écrire dans la lignei, pour parcourir à l'envers (Step -1), pour sauter (Step 2), pour comparer l'élémentiavec l'élémenti+1, ou pour supprimer au fil de l'eau. C'est aussi le seul moyen modifiable de réécrire les éléments d'un tableau.
Un indice révélateur : si vous vous surprenez à appeler .Count et à fabriquer
votre propre i juste pour atteindre collection(i), c'est probablement
For Each que vous vouliez. Si vous cherchez l'élément avant ou après
l'élément courant, ou si vous retirez des éléments, il vous faut le compteur.
Comment ExcelMaster aide
Choisir la boucle, typer correctement la variable de boucle, se rappeler que les tableaux sont en lecture seule et que les suppressions doivent se faire à l'envers — c'est exactement le genre de jugement mécanique qui se dresse entre « je sais ce que je veux » et « la macro le fait correctement ».
ExcelMaster
vous laisse énoncer l'objectif à la place. Dites « dans la feuille Commandes,
surligne chaque ligne dont le statut est En retard » ou « supprime chaque feuille
dont le nom commence par Temp », et il écrit et exécute la logique — en
choisissant For Each là où un simple parcours convient et un compteur
décroissant là où des éléments sont retirés, pour que le bug d'ordre de
suppression ne se produise jamais. Quand vous écrivez vraiment à la main une
macro planifiée, c'est encore vous qui choisirez la boucle. Pour la tâche
quotidienne « fais juste ça sur les données d'aujourd'hui », décrire le résultat
vaut mieux que réussir à la main chaque règle d'énumérateur.
Questions fréquentes
Quelle est la différence entre For Each et For…Next en VBA ?
For Each parcourt une collection par appartenance — il vous remet chaque
élément dans l'ordre naturel de la collection et vous ne gérez jamais d'indice.
For i = 1 To N est à compteur — vous contrôlez l'indice, donc vous pouvez
parcourir à l'envers avec Step -1, sauter avec Step 2, ou atteindre l'élément
i+1. Utilisez For Each pour un simple parcours d'un Range, des Worksheets
ou d'un tableau ; utilisez For…Next quand il vous faut l'indice, que vous voulez
supprimer des éléments, ou que vous devez réécrire les éléments d'un tableau.
Pourquoi ai-je « Objet requis » (erreur 424) dans une boucle For Each ?
Presque toujours parce que la variable de boucle est déclarée avec le mauvais type
— souvent un Long ou un String alors que la collection contient des objets.
For Each cell In Range(...) réclame Dim cell As Range, et
For Each ws In Worksheets réclame Dim ws As Worksheet. Si vous parcourez un
tableau VBA, la variable de boucle doit être un Variant.
Puis-je modifier les valeurs d'un tableau dans une boucle For Each ?
Non. Quand For Each parcourt un tableau, la variable de boucle est une copie
de chaque élément, si bien que l'affecter modifie la copie, pas le tableau — sans
aucune erreur. Pour modifier le tableau, utilisez une boucle à compteur :
For i = LBound(arr) To UBound(arr) et affectez arr(i). Parcourir un Range
avec For Each est modifiable, car la variable de boucle est une référence
d'objet en direct vers la cellule.
Comment parcourir chaque cellule d'une plage avec For Each ?
Déclarez la variable de boucle en Range et parcourez directement la plage :
For Each cell In Range("A1:B10"). VBA parcourt les cellules ligne par ligne.
Pour un grand bloc, c'est plus rapide que des boucles Cells(i, j) imbriquées,
mais l'approche la plus rapide de toutes est de lire la plage dans un tableau en
une seule fois (arr = Range("A1:B10").Value) et de parcourir le tableau — voyez
VBA Array.
Pourquoi supprimer des lignes ou des feuilles dans un For Each en saute-t-il certaines ?
Parce que For Each s'appuie sur un énumérateur qui suppose que l'appartenance de
la collection ne change pas pendant le parcours. Supprimer un élément décale tout
ce qui le suit, et l'énumérateur perd sa place — sautant des éléments en silence.
Ne supprimez jamais à l'intérieur d'un For Each. Utilisez une boucle à compteur
qui décompte vers le bas (For i = .Count To 1 Step -1) pour que les retraits
ne perturbent pas les éléments que vous n'avez pas encore atteints.
Testé dans
Testé avec : Excel 365 (Windows 11), VBA 7.1 — dernière vérification le 01/08/2026.
Guides associés : VBA For Loop · VBA Collection · VBA With · VBA Array · VBA Dictionary
