En bref — Supprimer une ligne est une modification structurelle : elle ne vide pas la ligne, elle la retire et fait remonter d'un cran toutes les lignes du dessous. Ce simple fait est à l'origine du bug VBA le plus courant qui soit — une boucle vers le bas qui supprime des lignes saute chaque ligne qui suivait une ligne supprimée, parce que les numéros de ligne se décalent sous la boucle. Le correctif tient en un mot : bouclez à rebours (
For i = last To first Step -1). Supprimez la ligne entière avec.EntireRow.Delete, et pour de nombreuses lignes éparpillées, réunissez-les dans un seulUnionet supprimez une seule fois — c'est plus rapide et cela contourne complètement le problème de décalage.
' Supprimer chaque ligne dont la colonne A est vide - boucler de BAS en HAUT.
Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets("Data")
Dim lastRow As Long, i As Long
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
For i = lastRow To 2 Step -1 ' <-- à rebours, sinon vous sautez des lignes
If Trim(ws.Cells(i, "A").Value) = "" Then ws.Rows(i).EntireRow.Delete
Next i
« Supprimez ces lignes » ressemble à la tâche la plus simple de l'automatisation Excel, et c'est
celle qui piège presque tout le monde du premier coup. La raison n'est pas la méthode Delete —
c'est que supprimer modifie précisément ce sur quoi vous bouclez. Prenez le bon sens de parcours
et la suppression par condition devient triviale ; prenez le mauvais et votre macro laisse
silencieusement la moitié des lignes concernées en place. Ce guide est bâti autour de cette seule
idée, puis des schémas pratiques qui en découlent.
Ce que vous allez apprendre
- Le modèle mental — supprimer retire une ligne et fait remonter tout ce qui est en dessous
- La règle la plus importante — bouclez à rebours, sinon une boucle vers le bas saute des lignes
- Pourquoi
.EntireRow.Deleteest la cible sûre, et ce que fait.Deletesur une cellule à la place - Le schéma plus rapide pour les lignes éparpillées — construire un
Union, supprimer une seule fois - Retirer les lignes vides et supprimer par condition sans casser les formules de référence
Le modèle mental : une suppression déplace la grille, elle ne vide pas une ligne
Deux opérations totalement différentes portent le même nom de « suppression ». Appuyer sur
Suppr efface une cellule — la ligne reste, la valeur disparaît. Un clic droit ▸
Supprimer, ou Rows(i).Delete dans le code, retire la ligne — la ligne cesse d'exister et
chaque ligne située en dessous remonte d'un cran pour combler le trou. La ligne qui était la 11
devient la 10.
Ce comblement du trou, c'est toute l'histoire. Quand vous supprimez la ligne 10, les données de la ligne 11 se retrouvent dans la ligne 10. Tout code qui supposait que « la ligne 11 contient toujours ce qu'elle contenait il y a un instant » est désormais faux. C'est pourquoi supprimer des lignes n'a rien à voir avec les autres boucles que vous écrivez : l'adresse des données que vous n'avez pas encore traitées change à l'instant même où vous supprimez. Vous modifiez le système de coordonnées pendant que vous le parcourez.
Gardez cette image en tête — sous la ligne supprimée, tout remonte — et chaque règle qui suit n'en est qu'une conséquence.
La règle la plus importante : bouclez à rebours, sinon vous sautez des lignes
Voici le bug, écrit comme presque tout le monde l'écrit la première fois :
' FAUX - une boucle vers le bas sur des lignes que vous supprimez.
For i = 2 To lastRow
If ws.Cells(i, "A").Value = "DELETE" Then ws.Rows(i).EntireRow.Delete
Next i
Supposons que les lignes 5 et 6 contiennent toutes deux "DELETE". La boucle atteint i = 5,
supprime la ligne 5, et la ligne 6 remonte pour devenir la nouvelle ligne 5. Mais la boucle passe
alors à i = 6 — soit la ligne qui était la ligne 7. L'ancienne ligne 6 n'a jamais été
vérifiée. Deux correspondances voisines, et la seconde survit. Sur un bloc de correspondances,
vous en laissez à peu près une sur deux, et le symptôme (« certaines lignes n'ont pas été
supprimées ») paraît aléatoire.
Le correctif ne coûte rien. Parcourez de bas en haut :
' CORRECT - supprimer de la dernière ligne jusqu'à la première.
For i = lastRow To 2 Step -1
If ws.Cells(i, "A").Value = "DELETE" Then ws.Rows(i).EntireRow.Delete
Next i
En sens inverse, supprimer la ligne 6 fait remonter les lignes situées sous la 6 — mais vous
les avez déjà traitées. Les lignes que vous n'avez pas encore examinées sont toutes au-dessus
de celle que vous venez de supprimer, et leurs numéros n'ont pas bougé. Le décalage a toujours
lieu ; simplement, il se produit derrière vous, là où il ne peut faire aucun dégât. Dès qu'une
boucle supprime des lignes, elle utilise Step -1. Retenez cela et la moitié des bugs de
suppression disparaît.
La règle qui garde les données alignées : supprimez la ligne, pas une cellule
Delete s'applique à n'importe quelle plage, et plus la plage est petite, plus elle est
dangereuse. Si vous écrivez ws.Cells(i, "A").Delete, vous supprimez une seule cellule, et
Excel fait remonter les cellules situées en dessous, dans la seule colonne A — en laissant les
colonnes B, C et D exactement où elles étaient. À partir de là, chaque ligne est désalignée : la
colonne A affiche un enregistrement tandis que B et C affichent celui du dessous. Aucune erreur ne
se déclenche ; vos données sont simplement mélangées en silence.
Supprimer la ligne entière garde chaque colonne alignée :
ws.Rows(i).EntireRow.Delete ' toute la ligne 11 disparaît ; 12, 13... remontent ensemble
ws.Cells(i, "A").EntireRow.Delete ' identique - .EntireRow promeut une cellule en sa ligne entière
.EntireRow est la promotion de « cette cellule » vers « la ligne entière dans laquelle elle se
trouve », et c'est presque toujours ce que vous voulez. Réservez le Range.Delete nu avec
Shift:=xlUp/xlToLeft au cas rare où vous voulez réellement déplacer un bloc de cellules, et
non retirer un enregistrement.
Le schéma plus rapide et plus sûr : réunir un Union et supprimer une seule fois
Boucler et supprimer ligne par ligne fonctionne dès lors que vous bouclez à rebours, mais sur de
grandes feuilles c'est lent — chaque .Delete force Excel à décaler la grille et à recalculer. Il
existe un schéma à la fois plus rapide et insensible au piège du décalage, parce qu'il effectue
toute la suppression en une seule étape : constituez avec Union une Range regroupant chaque
ligne à retirer, puis supprimez le tout à la fin.
Dim victims As Range, i As Long
For i = 2 To lastRow ' le sens n'importe pas - on supprime plus tard
If ws.Cells(i, "A").Value = "DELETE" Then
If victims Is Nothing Then
Set victims = ws.Rows(i)
Else
Set victims = Union(victims, ws.Rows(i))
End If
End If
Next i
If Not victims Is Nothing Then victims.EntireRow.Delete ' une seule suppression, toutes les lignes d'un coup
Comme aucune ligne n'est retirée avant la fin de la boucle, les numéros de ligne ne bougent jamais
pendant le parcours — une boucle vers le bas est donc parfaitement sûre ici. Et une unique
.Delete sur une plage à zones multiples est spectaculairement plus rapide que des centaines de
suppressions individuelles. Ma règle empirique : quelques lignes, bouclez à rebours ; des
centaines ou des milliers, réunissez un Union (ou filtrez — voir plus bas) et supprimez une
seule fois. Enveloppez l'une ou l'autre dans Application.ScreenUpdating = False /
Calculation = xlManual et les grosses suppressions passent de quelques secondes à instantanées.
Lignes vides, conditions et le piège des références
Supprimer les lignes vides dispose d'un raccourci d'une ligne qui bat n'importe quelle boucle — laissez Excel trouver les vides :
On Error Resume Next ' SpecialCells lève l'erreur 1004 s'il n'y a aucun vide
ws.Range("A2:A" & lastRow).SpecialCells(xlCellTypeBlanks).EntireRow.Delete
On Error GoTo 0
SpecialCells(xlCellTypeBlanks) renvoie chaque cellule vide de la colonne A sous forme d'une plage
à zones multiples, et .EntireRow.Delete en supprime toutes les lignes d'un seul coup. Deux
réserves : elle se fonde sur une seule colonne (une ligne dont A est vide mais B rempli disparaît
quand même), et elle lève une erreur en l'absence de vide — d'où le garde-fou On Error.
Pour supprimer par condition sur de gros volumes, le geste de pro est l'AutoFilter : filtrez les lignes dont vous ne voulez pas, supprimez celles qui restent visibles, retirez le filtre. C'est l'approche la plus rapide de toutes, car c'est Excel qui fait la correspondance :
With ws.Range("A1").CurrentRegion
.AutoFilter Field:=1, Criteria1:="DELETE"
.Offset(1).SpecialCells(xlCellTypeVisible).EntireRow.Delete ' ignorer la ligne d'en-tête
End With
ws.AutoFilterMode = False
Un piège leur survit à tous : supprimer des lignes décale les références. Si une formule
ailleurs pointe vers =A20 et que vous supprimez la ligne 5, Excel la réécrit en =A19 — en
général ce que vous voulez. Mais si vous supprimez la ligne dont dépend une formule, celle-ci se
transforme en #REF!. Supprimer des lignes sous des formules actives est la cause classique d'une
feuille pleine d'erreurs #REF! : avant une suppression en masse, sachez si quoi que ce soit en
aval référence les lignes que vous retirez. Trouver où s'arrêtent vos données est une compétence
connexe — voir VBA Last Row.
Comment ExcelMaster aide
Le code de suppression de lignes a plusieurs façons discrètes de mal tourner : la boucle vers le
bas qui saute des lignes, la suppression d'une seule cellule qui désaligne les colonnes, l'appel à
SpecialCells qui plante en l'absence de vide, la suppression en masse qui laisse des #REF!
derrière elle. Aucune ne déclenche d'erreur visible — elles produisent simplement des données
légèrement fausses.
ExcelMaster vous laisse
plutôt décrire le résultat. Dites « supprime chaque ligne dont la colonne A est vide » ou « retire
les lignes dont le statut est Annulé », et il écrit la boucle dans le bon sens (ou un
Union/filtre pour de gros volumes), cible .EntireRow, protège les cas limites et sauvegarde
d'abord la feuille. Vous gardez le classeur et le code ; vous vous épargnez le moment où un
Step -1 oublié corrompt silencieusement un rapport.
Questions fréquentes
Pourquoi ma boucle VBA saute-t-elle des lignes lors d'une suppression ?
Parce que supprimer une ligne fait remonter d'un cran chaque ligne du dessous, alors qu'une boucle
vers le bas continue de s'incrémenter. Après la suppression de la ligne 5, l'ancienne ligne 6
devient la ligne 5 — et la boucle passe à la ligne 6, qu'elle saute. Bouclez plutôt à rebours :
For i = lastRow To 2 Step -1. Les lignes non encore vérifiées sont alors toujours au-dessus de la
suppression, si bien que leurs numéros ne bougent jamais.
Comment supprimer une ligne entière en VBA ?
Utilisez .EntireRow.Delete — par exemple ws.Rows(11).EntireRow.Delete ou
ws.Cells(11, "A").EntireRow.Delete. Les deux retirent la ligne entière, de sorte que chaque
colonne reste alignée. Évitez Cells(11, "A").Delete, qui supprime une seule cellule et ne décale
que cette colonne, mélangeant tout le reste.
Quelle est la façon la plus rapide de supprimer de nombreuses lignes en VBA ?
Pour des centaines ou des milliers de lignes, ne supprimez pas une par une. Soit vous appliquez un
AutoFilter aux lignes à éliminer et supprimez les cellules visibles en une étape, soit vous
constituez un Union de toutes les lignes ciblées pendant la boucle et appelez .EntireRow.Delete
une seule fois à la fin. Une unique suppression multi-lignes est bien plus rapide que de nombreuses
suppressions individuelles, surtout avec ScreenUpdating et Calculation désactivés.
Comment supprimer toutes les lignes vides en VBA ?
ws.Range("A2:A" & lastRow).SpecialCells(xlCellTypeBlanks).EntireRow.Delete retire en une seule
opération chaque ligne dont la colonne A est vide. Enveloppez-la dans On Error Resume Next /
On Error GoTo 0, car SpecialCells lève une erreur lorsqu'il n'y a aucune cellule vide à trouver.
Pourquoi ai-je des erreurs #REF! après avoir supprimé des lignes ?
Supprimer des lignes décale les références de cellule. Les formules qui pointent au-delà des
lignes supprimées sont renumérotées automatiquement, mais toute formule qui référençait une cellule
à l'intérieur d'une ligne supprimée ne peut plus se résoudre et devient #REF!. Avant une
suppression en masse, vérifiez si d'autres cellules dépendent des lignes que vous vous apprêtez à
retirer.
Testé dans
Testé dans : Excel 365 (Windows 11), VBA 7.1 — dernière vérification le 07/08/2026.
Guides associés : VBA Insert Rows and Columns · VBA Hide Columns and Rows · VBA Last Row · VBA For Loop · VBA Range
