TL;DR —
DoEventsmet 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 appelezDoEventsà 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équence —
DoEventsà 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
DoEventsn'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
