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

VBA Worksheet_Change dans Excel — exécuter du code quand une cellule est modifiée (et la boucle infinie à éviter)

|

VBA Worksheet_Change dans Excel — exécuter du code quand une cellule est modifiée (et la boucle infinie à éviter)

TL;DRWorksheet_Change est un événement qu'Excel déclenche chaque fois qu'un utilisateur (ou votre code) modifie une cellule de cette feuille. Excel vous remet la cellule modifiée sous forme de Target, pour que vous puissiez réagir — horodater la ligne, valider la saisie, journaliser la modification. La seule chose à savoir : si votre gestionnaire écrit dans une cellule, cette écriture redéclenche Worksheet_Change — encore et encore — jusqu'à ce qu'Excel se fige. Le correctif tient en une seule paire de lignes, Application.EnableEvents = False … = True, autour de chaque écriture. Acquérez ce réflexe et tout le reste n'est que détail.

' Réside dans l'objet propre à la feuille (p. ex. Sheet1), PAS un Module ni ThisWorkbook.
Private Sub Worksheet_Change(ByVal Target As Range)
    If Intersect(Target, Range("B:B")) Is Nothing Then Exit Sub   ' ne réagir qu'à la colonne B
    On Error GoTo Done
    Application.EnableEvents = False          ' empêcher notre propre écriture de redéclencher cet événement
    Target.Offset(0, 1).Value = Now          ' inscrire l'heure à côté de la modification
Done:
    Application.EnableEvents = True           ' TOUJOURS réactiver les événements
End Sub

Réagir aux modifications, c'est le moment où VBA cesse d'être « des boutons qui lancent des macros » pour commencer à sembler vivant : une cellule change et la feuille répond d'elle-même. Worksheet_Change est l'événement qui alimente les pistes d'audit, les horodatages automatiques, la validation en direct et les listes déroulantes dépendantes. C'est aussi l'événement qui provoque les instants les plus paniqués du genre « Excel s'est figé et j'ai perdu mon travail » — car le code évident n'est qu'à un petit pas d'une boucle infinie.

Ce que vous allez apprendre

  • Le modèle mental — un capteur de modification qui vous remet la cellule modifiée sous forme de Target
  • Le piège de la boucle infinie — et le correctif Application.EnableEvents qui définit le VBA événementiel
  • Pourquoi un plantage peut désactiver tous vos événements jusqu'au redémarrage d'Excel
  • Comment cibler le gestionnaire avec Intersect pour qu'il ne s'exécute pas à chaque modification
  • Pourquoi il ignore les recalculs de formules — et quand vous avez plutôt besoin de Worksheet_Calculate

Le modèle mental : un capteur de modification, pas un bouton

Worksheet_Change est un capteur relié à la feuille. Vous ne l'appelez pas ; à l'instant où le contenu d'une cellule change, c'est Excel qui vous appelle, en passant la ou les cellules modifiées sous forme d'un Range nommé Target. Votre travail consiste à lire Target et à décider quoi en faire.

Ce cadrage règle deux points. D'abord, Target est votre unique entrée — c'est là où la modification a eu lieu, et cela peut être une cellule ou plusieurs (un collage, un remplissage, une suppression sur toute une sélection arrivent tous sous forme d'un Target multi-cellules). Ensuite, le gestionnaire réside dans l'objet de code de la feuille concernéeSheet1 dans l'Explorateur de projets, pas ThisWorkbook ni un Module. La signature est figée : Private Sub Worksheet_Change(ByVal Target As Range). (La version à l'échelle du classeur, pour toutes les feuilles à la fois, est Workbook_SheetChange dans ThisWorkbook.)

Le piège qui fige Excel : votre écriture redéclenche l'événement

Voici le bug que tout développeur VBA écrit exactement une fois. Vous voulez réagir à une modification en réécrivant quelque chose dans la feuille :

Private Sub Worksheet_Change(ByVal Target As Range)
    Target.Offset(0, 1).Value = Now   ' écrire à côté de la modification... ce qui est LUI-MÊME une modification
End Sub

Écrire dans Target.Offset(0, 1) modifie une cellule — ce qui redéclenche Worksheet_Change — dont l'écriture le redéclenche encore — à l'infini. Excel s'appelle récursivement jusqu'à épuiser la pile et lever une erreur, ou simplement paraître figé. L'événement de modification n'a aucune protection intégrée contre le fait de réagir à sa propre réaction.

Le correctif est l'idiome le plus important du VBA événementiel : désactivez les événements autour de toute écriture, puis réactivez-les.

Private Sub Worksheet_Change(ByVal Target As Range)
    Application.EnableEvents = False
    Target.Offset(0, 1).Value = Now
    Application.EnableEvents = True
End Sub

Avec EnableEvents = False, votre écriture ne déclenche pas un nouveau Worksheet_Change, donc pas de récursion. Ensuite vous le rétablissez. Gravez la règle : dans tout événement qui écrit dans des cellules, encadrez l'écriture par Application.EnableEvents = False … = True.

La règle qui cache la seconde moitié du piège : un plantage laisse les événements désactivés

Application.EnableEvents est un interrupteur unique, global à l'application, et Excel ne le rétablit pas automatiquement. Cela crée un vilain second mode de défaillance : si votre gestionnaire échoue après l'avoir mis à False mais avant de l'avoir remis, les événements restent désactivés — pour toute la session Excel, sur chaque feuille et chaque classeur.

Le symptôme déroute : « mes macros ont soudain cessé de fonctionner ». Votre Worksheet_Change n'est pas cassé — les événements sont globalement supprimés parce qu'une exécution antérieure est morte en plein gestionnaire. C'est pourquoi le motif sûr réactive toujours les événements dans un gestionnaire d'erreurs :

Private Sub Worksheet_Change(ByVal Target As Range)
    On Error GoTo CleanExit
    Application.EnableEvents = False
    Target.Offset(0, 1).Value = Now
    ' ... d'autres traitements susceptibles d'échouer ...
CleanExit:
    Application.EnableEvents = True     ' s'exécute que l'on ait réussi ou échoué
End Sub

C'est exactement la discipline de « la sortie unique qui nettoie toujours » de VBA On Error, et elle est non négociable ici. (Si les événements sont déjà bloqués à l'arrêt, exécutez une ligne dans la fenêtre Exécution — Application.EnableEvents = True — ou redémarrez simplement Excel.)

La règle qui le maintient ciblé : cibler avec Intersect

Un Worksheet_Change nu se déclenche pour n'importe quelle cellule de la feuille. Si seules vous intéressent les modifications dans une colonne ou un tableau, vous devez le dire — sinon le gestionnaire s'exécute (et écrit peut-être) à chaque modification sans rapport. L'outil, c'est Intersect, qui renvoie le chevauchement entre Target et la plage qui vous intéresse, ou Nothing s'il n'y en a pas :

Private Sub Worksheet_Change(ByVal Target As Range)
    ' Ignorer les modifications hors de B2:B1000
    If Intersect(Target, Range("B2:B1000")) Is Nothing Then Exit Sub
    ' ... ne réagir qu'à la partie qui compte ...
End Sub

Deux mises en garde connexes. Target peut compter plusieurs cellules — un collage ou un remplissage de colonne vous remet une plage multi-cellules, si bien qu'un code supposant que Target.Value est une valeur unique lèvera une erreur ou se comportera mal ; parcourez Target en boucle, ou restreignez avec If Target.Count > 1 Then Exit Sub quand vous voulez vraiment des modifications unitaires. Et réagissez à l'intersection, pas à tout Target, lorsqu'un collage déborde de votre plage surveillée sur des cellules extérieures.

La distinction qui piège tout le monde : il ignore les recalculs de formules

Worksheet_Change se déclenche sur un changement du contenu d'une cellule — une valeur tapée, une valeur collée, une suppression, une écriture VBA. Il ne se déclenche pas quand une cellule affiche simplement un nouveau nombre parce qu'une formule a été recalculée. Si C1 vaut =A1+B1 et que A1 change, l'événement se déclenche pour A1 (la cellule modifiée), pas pour C1 (celle qui a été recalculée).

Quand vous devez réagir au changement d'un résultat, c'est un autre événement — Worksheet_Calculate — qui se déclenche au recalcul mais ne vous donne aucun Target (vous devez inspecter les cellules vous-même). Choisir le mauvais est une défaillance silencieuse : votre gestionnaire ne s'exécute tout simplement jamais. La règle : Change = quelqu'un a modifié la cellule ; Calculate = la sortie d'une formule a bougé.

Worksheet_Change est une moitié du duo « réagir à l'utilisateur ». Son jumeau, Worksheet_SelectionChange, se déclenche quand le curseur se déplace plutôt que quand une valeur change — et tous deux appartiennent à la même famille d'événements que Workbook_Open, l'événement qui s'exécute à la première ouverture du fichier.

Comment ExcelMaster aide

Une macro de réaction aux modifications est d'une minutie trompeuse : le bon objet, Intersect pour la cibler, EnableEvents pour éviter la boucle, un gestionnaire d'erreurs pour qu'un plantage ne tue pas tous les événements d'Excel. Oubliez la paire EnableEvents et vous figez le fichier ; oubliez le gestionnaire d'erreurs et vous cassez les événements en silence.

ExcelMaster vous laisse énoncer le comportement à la place. Dites « quand quelqu'un modifie la colonne B, mets l'heure actuelle dans la colonne C juste à côté », et il écrit un Worksheet_Change dans le bon objet de feuille — ciblé avec Intersect, protégé par EnableEvents, enveloppé pour qu'une erreur ne puisse pas laisser les événements bloqués à l'arrêt. Vous gardez la feuille et le code ; vous vous épargnez le rituel initial qui consiste à figer votre propre classeur pour apprendre la règle.

Questions fréquentes

Pourquoi mon Worksheet_Change provoque-t-il une boucle infinie ou un blocage ?

Parce que votre gestionnaire écrit dans une cellule, et que cette écriture est elle-même un changement qui redéclenche Worksheet_Change — sans fin. Encadrez chaque écriture par Application.EnableEvents = False avant et Application.EnableEvents = True après, et réactivez toujours les événements dans un gestionnaire d'erreurs pour qu'un plantage ne puisse pas les laisser désactivés.

Comment faire en sorte que Worksheet_Change ne s'exécute que pour une colonne précise ?

Utilisez Intersect en tête du gestionnaire : If Intersect(Target, Range("B:B")) Is Nothing Then Exit Sub. Cela sort immédiatement, sauf si la modification a touché la colonne B. Intersect renvoie le chevauchement entre la plage modifiée et la plage qui vous intéresse, ou Nothing quand il n'y a aucun chevauchement.

Worksheet_Change se déclenche-t-il quand une formule est recalculée ?

Non. Il se déclenche uniquement quand le contenu d'une cellule est modifié — tapé, collé, supprimé ou écrit par VBA. Une cellule qui affiche une nouvelle valeur parce qu'une formule a été recalculée ne le déclenche pas. Pour cela, utilisez l'événement Worksheet_Calculate, qui se déclenche au recalcul mais ne vous donne pas de Target.

Où placer le code Worksheet_Change ?

Dans le module de code de la feuille concernée — double-cliquez sur la feuille (p. ex. Sheet1) sous « Microsoft Excel Objets » dans l'Explorateur de projets et placez-y Private Sub Worksheet_Change(ByVal Target As Range). Cela ne fonctionne pas depuis un Module standard. Pour toutes les feuilles à la fois, utilisez Workbook_SheetChange dans ThisWorkbook.

Mes événements VBA ont cessé de fonctionner — comment corriger ça ?

Un gestionnaire antérieur a probablement défini Application.EnableEvents = False et échoué avant de le rétablir, laissant les événements globalement désactivés. Tapez Application.EnableEvents = True dans la fenêtre Exécution (Ctrl+G) et appuyez sur Entrée, ou redémarrez Excel. Prévenez le problème en réactivant toujours les événements dans un gestionnaire d'erreurs.

Testé dans

Testé dans : Excel 365 (Windows 11), VBA 7.1 — dernière vérification le 02/08/2026.

Guides associés : VBA Worksheet_SelectionChange · VBA Workbook_Open · VBA On Error · VBA Range · VBA Boucle For