TL;DR —
Workbook_BeforeCloseest un événement qu'Excel déclenche à l'instant où quelqu'un tente de fermer le classeur — avant que la moindre fenêtre ne soit démantelée. Il vous remet un seul argument,Cancel, et c'est tout l'enjeu : mettezCancel = Trueet la fermeture est annulée, le fichier reste ouvert. Ce n'est donc pas un mot d'adieu que vous exécutez sur le pas de la porte — c'est un point de contrôle capable de faire faire demi-tour à l'utilisateur sur le seuil. Le code doit résider dansThisWorkbook, et si vous voulez exécuter votre propre invite d'enregistrement sans qu'Excel demande lui aussi, mettezThisWorkbook.Saved = Truepour faire taire sa boîte de dialogue intégrée.
' Réside dans ThisWorkbook — PAS un Module.
Private Sub Workbook_BeforeClose(Cancel As Boolean)
If ThisWorkbook.Sheets("Form").Range("Approved").Value <> "Yes" Then
MsgBox "Set Approved = Yes before closing this file.", vbExclamation
Cancel = True ' <-- annule la fermeture ; le classeur reste ouvert
End If
End Sub
La plupart des macros s'exécutent quand un utilisateur le demande — un bouton, un
raccourci. Workbook_BeforeClose s'exécute quand un utilisateur tente de partir, et
ce moment précis est ce qui la rend utile et dangereuse à parts égales. C'est
l'événement derrière « vous avez des modifications non enregistrées », les validations
obligatoires, le nettoyage à la sortie et « journaliser qui a fermé le fichier ». C'est
aussi l'événement que l'on câble le plus souvent de travers — parce qu'on le traite
comme une notification alors qu'Excel offre en réalité un droit de veto.
Ce que vous allez apprendre
- Le modèle mental — un événement videur qui vous remet un droit de veto
Cancel, pas un simple avertissement - Comment réellement empêcher une fermeture (et pourquoi une invite
vbYesNoseule n'y suffit pas) - Le piège de la double invite — et le levier
ThisWorkbook.Saved = Truequi le corrige - Pourquoi
BeforeClosene doit jamais être votre filet de sécurité pour l'intégrité des données (les plantages l'ignorent) - Fermeture d'un classeur vs fermeture d'Excel entière — et où le code doit résider
Le modèle mental : un videur, pas un mot d'adieu
Workbook_BeforeClose se déclenche dès qu'une fermeture est demandée — le X de la
fenêtre, Fichier ▸ Fermer, Application.Quit, ou une autre macro qui appelle .Close
— et il se déclenche avant qu'Excel ne fasse quoi que ce soit d'irréversible. Point
crucial : il passe un unique Boolean par référence, nommé Cancel. Vous n'appelez
jamais ce Sub ; c'est Excel qui vous appelle, attend que vous ayez terminé, puis regarde
la valeur de Cancel.
Ce seul argument recadre tout. Si vous laissez Cancel tel quel, la fermeture se
déroule normalement. Si vous mettez Cancel = True, Excel abandonne la fermeture et
le classeur reste ouvert exactement tel qu'il était. Le gestionnaire est donc un
videur : il peut laisser passer l'utilisateur, ou l'arrêter et le renvoyer corriger
quelque chose. Lisez-le comme « préviens-moi avant de fermer » et vous passerez à côté
de toute la puissance de l'événement.
La signature est figée et l'emplacement n'est pas négociable :
Private Sub Workbook_BeforeClose(Cancel As Boolean), dans le module de code
ThisWorkbook — double-cliquez sur ThisWorkbook sous « Microsoft Excel Objets »
dans l'Explorateur de projets. Placez-le dans un Module standard et il ne se
déclenchera jamais, c'est la même règle du « où réside le code » que pour
Workbook_Open.
La règle qui compte le plus : une invite sans Cancel n'est que du théâtre
Voici l'erreur que presque tout le monde commet en premier. Vous voulez confirmer avant de fermer, alors vous écrivez :
Private Sub Workbook_BeforeClose(Cancel As Boolean)
MsgBox "Are you sure you want to close?", vbYesNo ' pose la question... et ignore la réponse
End Sub
La boîte de dialogue s'affiche, l'utilisateur clique sur Non — et le classeur se
ferme quand même. Rien dans ce code ne touche à Cancel, donc Excel poursuit. L'invite
n'était que du théâtre. La règle : une décision que vous voulez imposer doit être
réécrite dans Cancel. Récupérez la réponse et agissez en conséquence :
Private Sub Workbook_BeforeClose(Cancel As Boolean)
If MsgBox("Close without exporting the report?", vbYesNo + vbQuestion) = vbNo Then
Cancel = True ' l'utilisateur a dit Non -> annuler la fermeture
End If
End Sub
Désormais, « Non » garde réellement le fichier ouvert. C'est toute la différence entre
un événement qui informe et un événement qui protège : la protection n'est réelle
que si Cancel = True peut être atteint.
Le piège qui agace les utilisateurs : Excel demande deux fois d'enregistrer
Le second bug classique surgit dès que votre gestionnaire enregistre. Vous ajoutez une étape « enregistrer avant de partir », et voilà que fermer un classeur modifié produit deux boîtes de dialogue : la vôtre, puis celle d'Excel, « Voulez-vous enregistrer les modifications ? ». La raison : vous et Excel tentez tous deux de gérer le même état non enregistré.
Le levier, c'est la propriété Saved du classeur. Saved est l'indicateur qu'Excel
utilise pour « il n'y a aucune modification non enregistrée ». Quand vous la mettez à
True, vous dites à Excel que le fichier est propre — il se ferme donc sans afficher
sa propre invite d'enregistrement, même s'il existe réellement des modifications. Gérez
l'enregistrement vous-même, puis basculez Saved :
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim answer As VbMsgBoxResult
answer = MsgBox("Save changes before closing?", vbYesNoCancel + vbQuestion)
If answer = vbCancel Then
Cancel = True ' ne pas fermer du tout
ElseIf answer = vbYes Then
ThisWorkbook.Save ' enregistrer, puis laisser la fermeture se poursuivre
Else ' vbNo
ThisWorkbook.Saved = True ' abandonner : dire à Excel qu'il est propre pour qu'il ne redemande pas
End If
End Sub
Mettre Saved = True n'enregistre rien — cela supprime l'invite en prétendant que
le classeur est déjà enregistré. Utilisez-le à dessein : c'est l'interrupteur qui fait
de votre propre logique d'enregistrement la seule que l'utilisateur voit.
La règle qui protège vos données : BeforeClose n'est pas un filet de sécurité
Workbook_BeforeClose se déclenche à chaque fermeture ordonnée — le X, Fichier ▸
Fermer, .Close, Application.Quit. Il ne se déclenche pas quand Excel plante,
quand le processus est tué, ou lors d'une coupure de courant. D'où une tentation
dangereuse : ne faites jamais de BeforeClose le seul mécanisme qui enregistre vos
données. Si la logique « enregistrer l'unique copie » réside ici et qu'Excel meurt, la
copie est perdue. Traitez BeforeClose comme une courtoisie (inviter, ranger,
journaliser), et gardez la vraie persistance sur un enregistrement explicite ou une
sauvegarde automatique minutée, pas sur le chemin de sortie.
Un dernier cas limite à connaître : quand l'utilisateur quitte Excel lui-même avec
plusieurs classeurs ouverts, chaque classeur reçoit son propre BeforeClose. Mettre
Cancel = True dans l'un d'eux empêche ce classeur de se fermer, mais les autres qui
ont déjà exécuté leur gestionnaire peuvent se retrouver dans un état à moitié fermé. Si
vous voulez du « tout ou rien » à la fermeture, coordonnez depuis
Workbook_BeforeClose avec parcimonie et testez le cas multi-fichiers.
La distinction qui fait trébucher : BeforeClose vs BeforeSave
BeforeClose protège la sortie ; son jumeau
Workbook_BeforeSave protège l'enregistrement et
vous remet le même genre de droit de veto Cancel (plus un indicateur SaveAsUI). Ils
forment une paire naturelle — valider à l'enregistrement, confirmer à la fermeture — et
tous deux partagent la règle d'or de la famille d'événements : si un gestionnaire écrit
dans des cellules ou enregistre, encadrez cette action par
Application.EnableEvents = False … = True et rétablissez-la dans un gestionnaire
d'erreurs, exactement comme le fait Worksheet_Change,
afin que votre propre écriture ne puisse pas redéclencher la mécanique.
Comment ExcelMaster aide
Un garde-fou de fermeture, ce sont quatre petites décisions faciles à rater
subtilement : le code dans ThisWorkbook (pas un Module), l'écriture de Cancel qui
arrête réellement la fermeture, le basculement Saved = True qui évite la double
invite, et le jugement sur ce qu'il ne faut pas confier au chemin de sortie.
ExcelMaster
vous laisse décrire le comportement à la place. Dites « avant que ce fichier ne se
ferme, si la cellule Approved n'est pas à Yes, arrête la fermeture et préviens
l'utilisateur », et il écrit un Workbook_BeforeClose dans ThisWorkbook qui règle
Cancel correctement, gère l'invite d'enregistrement sans la dédoubler, et protège
toute écriture. Vous gardez le classeur et le code ; vous vous épargnez les tâtonnements
pour apprendre quel levier fait quoi.
Questions fréquentes
Comment empêcher un classeur de se fermer en VBA ?
Mettez l'argument Cancel à True dans Workbook_BeforeClose :
Private Sub Workbook_BeforeClose(Cancel As Boolean) … Cancel = True. Excel passe
Cancel par référence et le vérifie après l'exécution de votre gestionnaire ; True
annule la fermeture et le fichier reste ouvert. Un MsgBox seul ne fait rien — vous
devez réécrire la décision dans Cancel.
Pourquoi Excel me demande-t-il deux fois d'enregistrer à la fermeture ?
Parce que votre gestionnaire BeforeClose propose d'enregistrer et qu'Excel pense
encore qu'il y a des modifications non enregistrées, il affiche donc lui aussi sa propre
boîte de dialogue. Gérez l'enregistrement vous-même, puis mettez
ThisWorkbook.Saved = True pour dire à Excel que le classeur est propre — cela supprime
son invite intégrée « Voulez-vous enregistrer ? ».
Où placer le code Workbook_BeforeClose ?
Dans le module de code ThisWorkbook — double-cliquez sur ThisWorkbook sous
« Microsoft Excel Objets » dans l'Explorateur de projets et collez-y
Private Sub Workbook_BeforeClose(Cancel As Boolean). Il ne se déclenche pas depuis un
Module standard, et les macros doivent être activées.
Workbook_BeforeClose s'exécute-t-il si Excel plante ?
Non. Il ne se déclenche que lors d'une fermeture ordonnée — le X de la fenêtre, Fichier
▸ Fermer, .Close ou Application.Quit. Un plantage, un processus tué ou une coupure
de courant l'ignorent complètement. Ne comptez jamais sur BeforeClose comme seul
mécanisme d'enregistrement de vos données.
En quoi BeforeClose diffère-t-il de Workbook_BeforeSave ?
BeforeClose se déclenche quand le fichier se ferme et vous laisse annuler la
fermeture ; Workbook_BeforeSave se déclenche quand le fichier est en cours
d'enregistrement et vous laisse annuler l'enregistrement. Fermer un fichier modifié
déclenche généralement une invite d'enregistrement, si bien que les deux apparaissent
souvent ensemble, mais ce sont des événements distincts avec des indicateurs Cancel
distincts.
Testé dans
Testé dans : Excel 365 (Windows 11), VBA 7.1 — dernière vérification le 05/08/2026.
Guides associés : VBA Workbook_BeforeSave · VBA Worksheet_Activate et Deactivate · VBA Workbook_Open · VBA Worksheet_Change · VBA On Error
