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

VBA DoEvents dans Excel — empêcher Excel de passer en Ne répond pas (et pourquoi il laisse votre macro s'exécuter deux fois)

|

VBA DoEvents dans Excel — empêcher Excel de passer en Ne répond pas (et pourquoi il laisse votre macro s'exécuter deux fois)

TL;DRDoEvents met votre macro en pause une fraction de seconde et laisse Excel gérer les clics, les frappes et les redessins mis en file pendant que votre code était occupé. C'est ce qui empêche la fenêtre de virer au gris en « Ne répond pas », et c'est ce qui rend possible un bouton Annuler qui fonctionne. Mais ce même moment de cession rend le contrôle à l'utilisateur en plein milieu de la macro — il peut donc cliquer de nouveau sur votre bouton et lancer une deuxième copie de la macro à l'intérieur de la première. Prémunissez-vous contre cette réentrance avec un drapeau d'exécution, et appelez DoEvents à intervalle régulier, pas à chaque itération :

Private mRunning As Boolean

Sub LongJob()
    If mRunning Then Exit Sub         ' garde anti-reentrance - refuse de lancer une deuxieme copie
    mRunning = True
    On Error GoTo CleanExit
    Dim i As Long
    For i = 1 To 500000
        ' ... traiter la ligne i ...
        If i Mod 1000 = 0 Then DoEvents   ' ceder la main de temps en temps pour qu'Excel reste vivant
    Next i
CleanExit:
    mRunning = False                  ' toujours remettre le drapeau a zero, meme apres une erreur
End Sub

Une longue boucle VBA s'exécute sur l'unique thread d'Excel, et pendant qu'elle tourne, Excel ne peut rien faire d'autre — ni repeindre, ni enregistrer un clic, ni mettre à jour la barre de titre. Au bout de quelques secondes, Windows décide que l'application est bloquée et estampille « Ne répond pas » par-dessus, alors même que votre macro fonctionne parfaitement. DoEvents est la soupape de secours. Ce guide repose sur une seule idée — DoEvents achète de la réactivité en rendant le contrôle, et « rendre le contrôle » inclut donner à l'utilisateur le pouvoir de tout casser. Ce n'est pas une ligne gratuite pour « rendre Excel fluide » ; c'est un compromis, et vous devez en payer le versant réentrance.

Ce que vous allez apprendre

  • Le modèle mental — un seul thread, une file de messages, et pourquoi une boucle fige la fenêtre
  • Ce que fait réellement DoEvents — vider la file, puis reprendre
  • Le vrai danger — la réentrance, et la garde par drapeau d'exécution qui l'arrête
  • Pourquoi vous devez en limiter la fréquenceDoEvents à chaque itération peut dominer votre temps d'exécution
  • Comment il alimente un bouton d'annulation, et comment cela se relie à une barre d'état
  • Pourquoi DoEvents n'est pas du multithreading, et quand simplement s'en passer

Le modèle mental : un seul thread et une file qui n'est jamais lue

Excel exécute votre VBA sur le même thread unique qu'il utilise pour tout le reste — dessiner la grille, gérer votre souris, rafraîchir le ruban. Pendant qu'une macro tourne, ce thread est à vous à 100 %. Chaque clic et chaque frappe de l'utilisateur ne disparaissent pas ; ils atterrissent dans une file de messages et attendent. Mais personne ne lit la file, parce que le thread est occupé dans votre boucle. L'écran se fige, la file s'accumule, et au bout de quelques secondes Windows peint « Ne répond pas » par-dessus la fenêtre.

DoEvents lit la file. Quand vous l'appelez, VBA met votre macro en pause, laisse Excel traiter tout ce qui attend — repeindre l'écran, gérer les clics, exécuter les gestionnaires d'événements déclenchés — puis rend le contrôle à la ligne située après DoEvents pour que votre macro continue.

' ... votre boucle monopolise le thread ; la fenetre est figee ...
DoEvents   ' Excel vide la file : repeint, traite les clics, execute les gestionnaires, puis revient
' ... votre macro reprend ici ...

C'est réellement utile : la fenêtre reste réactive, la barre d'état que vous avez définie se repeint vraiment, et l'utilisateur peut interagir. Le problème, c'est exactement cette dernière partie.

Le vrai danger : la réentrance

Voici la défaillance qui rend DoEvents dangereux plutôt que simplement lent. Votre macro est lancée par un bouton. À mi-parcours, vous appelez DoEvents. Excel traite les entrées en file — et l'utilisateur, voyant que la macro « prend un moment », a cliqué de nouveau sur le même bouton. Ce clic est maintenant traité pendant votre DoEvents, si bien qu'Excel démarre une deuxième exécution de la macro alors que la première est toujours en pause dans la boucle. Deux copies s'entremêlent désormais sur les mêmes données.

Les conséquences vont de fausses à catastrophiques : des lignes traitées deux fois, un compteur qui compte double, un fichier écrit par les deux exécutions, ou une erreur pure et simple quand la deuxième exécution modifie un état que la première croyait stable. C'est la réentrance, et c'est le bug numéro un de DoEvents — la même famille de défaillances qu'un gestionnaire d'événements qui se déclenche lui-même.

La garde est un drapeau au niveau du module qui refuse une seconde entrée :

Private mRunning As Boolean

Sub LongJob()
    If mRunning Then Exit Sub    ' deja en cours - ignorer le clic supplementaire
    mRunning = True
    On Error GoTo CleanExit
    ' ... boucle avec DoEvents ...
CleanExit:
    mRunning = False             ' remettre a zero en cas de succes ET d'erreur, sinon vous vous bloquez dehors
End Sub

Notez que le rétablissement CleanExit n'est pas facultatif ici non plus : si une erreur saute mRunning = False, le drapeau reste à True et la macro refuse de s'exécuter à nouveau jusqu'à ce que vous réinitialisiez le projet. La même discipline On Error que pour chaque interrupteur de ce cluster.

Limitez sa fréquence : DoEvents n'est pas gratuit

Même sans réentrance, DoEvents a un coût. Vider la file de messages et céder la main au système d'exploitation prend un temps réel — souvent bien plus que la minuscule part de travail d'une itération de boucle. Appelez-le à chaque itération d'une boucle serrée et vous pouvez transformer une macro de 2 secondes en une macro de 30 secondes, ayant passé le plus clair du temps à céder la main plutôt qu'à travailler.

Alors appelez-le à intervalle régulier — toutes les 1 000 lignes, ou tous les quarts de seconde sur un minuteur — pas à chaque passage :

For i = 1 To n
    ' ... traitement ...
    If i Mod 1000 = 0 Then DoEvents   ' assez reactif, sans payer a chaque ligne
Next i

L'intervalle est un curseur : plus fréquent signifie une fenêtre plus vive et un bouton d'annulation plus réactif ; moins fréquent signifie un débit brut plus rapide. i Mod 1000 est un bon point de départ pour un travail rapide par ligne ; ajustez-le à la durée de chaque itération.

Le bouton d'annulation qu'il rend possible

Le bon côté que la réentrance vous révèle est aussi la fonctionnalité que les gens désirent le plus : puisque DoEvents laisse Excel traiter les clics en cours d'exécution, un utilisateur peut cliquer sur un bouton Annuler et voir ce clic pris en compte pendant que la macro boucle encore. Reliez un drapeau public au bouton et vérifiez-le après chaque DoEvents :

Public gCancel As Boolean          ' mis a True par le gestionnaire de clic d'un bouton Annuler

Sub LongJob()
    Dim i As Long
    For i = 1 To 500000
        ' ... traitement ...
        If i Mod 1000 = 0 Then
            DoEvents
            If gCancel Then Exit For   ' le clic est passe - arret propre
        End If
    Next i
End Sub

Sans DoEvents, le clic sur Annuler reste simplement dans la file jusqu'à ce que la macro se termine d'elle-même — inutile. Avec lui, le bouton fonctionne. Associez-le à un message de barre d'état pour que l'utilisateur puisse voir la progression et l'arrêter.

Pourquoi ce n'est pas du multithreading — et quand s'en passer

DoEvents n'exécute pas votre macro en arrière-plan ni sur un autre thread. Tout reste en série sur l'unique thread ; DoEvents ne fait qu'intercaler le travail en attente d'Excel entre des morceaux du vôtre. Votre boucle n'accélère pas — au contraire, elle ralentit — elle cesse seulement de bloquer l'interface. Si vous avez réellement besoin que du travail s'exécute en parallèle, c'est un tout autre outil (un processus séparé, ou un langage qui gère les threads), pas DoEvents.

Et le choix par défaut honnête : si une macro se termine en moins d'une seconde ou deux, elle ne déclenche jamais « Ne répond pas », donc DoEvents ajoute un coût et un risque de réentrance sans aucun bénéfice — laissez-le de côté. N'y recourez que lorsque l'exécution est assez longue pour qu'une fenêtre figée soit un vrai problème, et une fois que vous le faites, protégez-vous de la réentrance et limitez la fréquence des appels. Une macro rapide avec des DoEvents disséminés dans sa boucle est plus lente et plus fragile que la même macro sans eux.

Comment ExcelMaster aide

Bien utiliser DoEvents, c'est un ensemble de jugements : seulement sur les exécutions longues, à intervalle régulier et non à chaque itération, derrière une garde anti-réentrance, avec le drapeau remis à zéro dans un gestionnaire d'erreurs, et associé à une vérification d'annulation et à un message de progression. Ratez-en un seul et vous obtenez une macro qui s'exécute deux fois, ou qui se traîne, ou un bouton Annuler qui ne se déclenche jamais.

ExcelMaster fait ces choix à votre place. Demandez-lui « un import long qui reste réactif et qu'on peut annuler », et il ajoute un drapeau d'exécution pour bloquer la réentrance, appelle DoEvents à un intervalle raisonnable, vérifie un drapeau d'annulation juste après, et remet tout à zéro dans un gestionnaire CleanExit — vous obtenez ainsi une macro réactive et interruptible au lieu d'une fenêtre figée ou d'une double exécution.

Questions fréquentes

Que fait DoEvents en VBA Excel ?

DoEvents met brièvement votre macro en pause et laisse Excel traiter les entrées et le travail de redessin mis en file pendant l'exécution de votre code — clics, frappes, redessins de l'écran, et tout gestionnaire d'événements déclenché. Puis il rend le contrôle à la ligne suivante et votre macro continue. C'est ce qui empêche une longue macro de figer la fenêtre Excel en « Ne répond pas ».

Pourquoi Excel affiche-t-il « Ne répond pas » pendant l'exécution de ma macro ?

Parce que votre macro utilise l'unique thread d'Excel, si bien qu'Excel ne peut ni repeindre ni gérer les entrées tant que la macro ne cède pas la main. Au bout de quelques secondes, Windows marque l'application comme bloquée — alors même que la macro fonctionne très bien. Ajouter DoEvents à intervalle régulier dans votre boucle laisse Excel respirer, et l'étiquette « Ne répond pas » disparaît.

DoEvents est-il dangereux ?

Il peut l'être, par la réentrance. Puisque DoEvents laisse Excel traiter les clics en cours d'exécution, un utilisateur peut relancer la même macro (en cliquant de nouveau sur son bouton) pendant que la première exécution est en pause, si bien que deux copies s'exécutent en même temps et corrompent mutuellement leur travail. Prémunissez-vous-en avec un drapeau « d'exécution » au niveau du module qui fait sortir la macro si elle tourne déjà, et remettez le drapeau à zéro dans un gestionnaire d'erreurs.

Dois-je appeler DoEvents à chaque itération de la boucle ?

Non — limitez sa fréquence. DoEvents a un vrai surcoût, et l'appeler à chaque itération d'une boucle serrée peut dominer votre temps d'exécution et rendre la macro bien plus lente. Appelez-le plutôt à intervalle régulier, comme If i Mod 1000 = 0 Then DoEvents, et ajustez l'intervalle à la durée de chaque itération.

DoEvents rend-il ma macro multithread ou plus rapide ?

Non. Tout s'exécute encore en série sur un seul thread ; DoEvents ne fait qu'intercaler le travail d'interface en attente d'Excel entre des morceaux de votre code. Votre boucle n'accélère pas — elle ralentit généralement un peu — elle cesse seulement de bloquer l'interface. Pour du vrai travail en parallèle, il vous faut un processus séparé, pas DoEvents.

Testé dans

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

Guides associés : VBA StatusBar · VBA DisplayAlerts · VBA ScreenUpdating · VBA EnableEvents · VBA On Error