95 votes

Exécuter automatiquement une macro Excel lors d'un changement de cellule

Comment puis-je exécuter automatiquement une macro Excel chaque fois qu'une valeur dans une cellule particulière change?

En ce moment, mon code de travail est le suivant :

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Range("H5")) Is Nothing Then Macro
End Sub

"H5" est la cellule particulière surveillée et Macro est le nom de la macro.

Y a-t-il un meilleur moyen?

0 votes

Est-ce que la fonction RunMacroWhenValueChanges dans FormulaDesk répond à vos besoins? formuladesk.com

0 votes

116voto

Mike Rosenblum Points 7063

Votre code est assez bon.

Cependant, soyez prudent, car votre appel à Range("H5") est une commande raccourcie vers Application.Range("H5"), qui est équivalent à Application.ActiveSheet.Range("H5"). Cela pourrait être correct, si les seules modifications sont des modifications faites par l'utilisateur - ce qui est le plus courant - mais il est possible que les valeurs des cellules de la feuille de calcul changent lorsqu'elle n'est pas la feuille active via des modifications programmatiques, par exemple en VBA.

À ce sujet, j'utiliserais Target.Worksheet.Range("H5"):

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Target.Worksheet.Range("H5")) Is Nothing Then Macro
End Sub

Ou vous pouvez utiliser Me.Range("H5"), si le gestionnaire d'événements est sur la page de code de la feuille de calcul en question (ce qui est généralement le cas) :

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Me.Range("H5")) Is Nothing Then Macro
End Sub

4 votes

Et si la cellule H5 est modifiée à partir d'une autre feuille, disons sheet2, alors la fonction ci-dessus ne fonctionne pas. Veuillez m'aider à ce sujet.

3 votes

Pour ceux qui viennent ici à partir d'une recherche Google, assurez-vous de coller ce code dans la feuille en VBA, pas dans un module comme je l'ai fait. Regardez stackoverflow.com/questions/15337008/…

0 votes

Application.ActiveSheet.Range("H5"). ==> target.parent.range("H5") is even safer

7voto

Joe Points 60749

Gérez l'événement Worksheet_Change ou l'événement Workbook_SheetChange.

Les gestionnaires d'événements prennent un argument "Target As Range", vous pouvez donc vérifier si la plage qui change inclut la cellule qui vous intéresse.

0 votes

Merci, ça marche. Je vérifie la plage avec, disons, Target.Address = Range("H5").Address. Y a-t-il une façon plus facile?

0 votes

Une alternative : Pas (Intersect(Cible, Plage("H5")) Est Rien) . Est-ce ainsi que vous le feriez ?

2 votes

Le premier commentaire (Target.Address = Range("H5").Address) ne fonctionnerait pas si votre cellule faisait seulement partie de la plage modifiée. Le deuxième commentaire souffre toujours des problèmes décrits par Mike Rosenblum.

7voto

J'ai passé beaucoup de temps à rechercher et à apprendre comment tout cela fonctionne, après avoir vraiment perturbé les déclencheurs d'événements. Comme il y avait tellement d'informations dispersées, j'ai décidé de partager tout ce que j'ai trouvé qui fonctionne, tout au même endroit, pas à pas comme suit :

1) Ouvrez l'Éditeur VBA, sous le Projet VBA (VotreNomDeClasseur.xlsm) ouvrez l'Objet Microsoft Excel et sélectionnez la Feuille à laquelle l'événement de changement sera lié.

2) La vue par défaut du code est "Général". Dans la liste déroulante en haut au milieu, sélectionnez "Feuille de calcul".

3) Private Sub Worksheet_SelectionChange y est déjà comme il se doit, ne le modifiez pas. Copiez/collez le code de Mike Rosenblum ci-dessus et changez la référence .Range à la cellule pour laquelle vous surveillez un changement (B3, dans mon cas). Ne placez pas encore votre Macro, cependant (j'ai enlevé le mot "Macro" après "Then") :

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Me.Range("H5")) Is Nothing Then
End Sub

ou dans la liste déroulante en haut à gauche, sélectionnez "Changer" et dans l'espace entre Private Sub et End Sub, collez If Not Intersect(Target, Me.Range("H5")) Is Nothing Then

4) À la ligne après "Then" désactivez les événements pour que lorsque vous appelez votre macro, cela ne déclenche pas d'événements et essaie de relancer ce Worksheet_Change dans un cycle sans fin qui fait planter Excel et/ou perturbe autrement tout :

Application.EnableEvents = False

5) Appelez votre macro

Call NomDeVotreMacro

6) Réactivez les événements pour que le prochain changement (et tous les autres événements) se déclenchent :

Application.EnableEvents = True

7) Terminez le bloc If et le Sub :

    End If
End Sub

Le code entier :

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Me.Range("B3")) Is Nothing Then
        Application.EnableEvents = False
        Call UpdateAndViewOnly
        Application.EnableEvents = True
    End If
End Sub

Cela permet d'éliminer le fait de mettre en marche/arrêt les événements dans les modules, ce qui crée des problèmes et permet simplement au changement de se déclencher, de désactiver les événements, d'exécuter votre macro et de réactiver les événements.

3voto

Javier Torón Points 51

Je préfère cette façon, ne pas utiliser une cellule mais une plage

    Dim cell_to_test As Range, cells_changed As Range

    Set cells_changed = Target(1, 1)
    Set cell_to_test = Range( PLAGE_DE_CELULES_A_DETECTER )

    If Not Intersect(cells_changed, cell_to_test) Is Nothing Then 
       Macro
    End If

0 votes

C'est la même chose qu'une cellule. Vous pouvez définir une plage comme une cellule, une série de cellules continues ou même des cellules dispersées (toutes séparées par une virgule).

0voto

Juan Garcia Points 1

J'ai une cellule qui est liée à une base de données d'actions en ligne et mise à jour fréquemment. Je veux déclencher une macro chaque fois que la valeur de la cellule est mise à jour.

Je pense que c'est similaire à un changement de valeur de cellule par un programme ou toute mise à jour de données externe mais les exemples ci-dessus ne fonctionnent pas pour moi. Je pense que le problème vient du fait que les événements internes d'Excel ne sont pas déclenchés, mais c'est juste une supposition.

J'ai fait ce qui suit,

Private Sub Worksheet_Change(ByVal Target As Range) 
  If Not Intersect(Target, Target.Worksheets("Symboles").Range("$C$3")) Is Nothing Then
   'Exécuter la macro
End Sub

1 votes

Je n'arrive pas à faire fonctionner cela pour une raison quelconque. Lorsque je demande au code de s'exécuter en VBA, il affiche un menu contextuel et me demande si je veux exécuter la macro au lieu de l'exécuter automatiquement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X