XL 2016 Evénement BeforeSave plutôt que BeforeClose

Lu76Fer

XLDnaute Occasionnel
Anomalie dans l'évènement BeforeClose
En écrivant une procédure de sortie dans une application je me suis rendu compte que l'évènement ne se déclenche pas dans un cas particulier ce qui entraîne une erreur à la réouverture de mon application.
Voici un petit bout de code à placer dans le module ThisWorkbook si vous souhaitez constater l'anomalie :
VB:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
    MsgBox "Event BeforeClose"
End Sub
Il faut avoir ce seul classeur ouvert au préalable.
Modifiez la grille sans sauvegarder et fermez le classeur.
Le message 'Event BeforeClose' s'affiche et ensuite la question "Voulez-vous enregistrez ...", choisissez 'Cancel' pour annuler.
Fermez à nouveau le classeur et là le message 'Event BeforeClose' ne s'affiche plus.

Je travaille sur la version XLS2016 et je ne sais pas si cette anomalie a lieu sur toutes les versions. J'ai aussi testé sur la version XLS2003 et il n'y avait pas cette anomalie.
Je pense que c'est une sécurité qui a été ajoutée afin de ne pas pouvoir écrire un code qui empêche la fermeture d'Excel.
Voici comment on pouvait le faire sous Excel2003 :
VB:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
    Cancel = True
End Sub

Après tests, je n'ai pas réussi à trouver de solution en utilisant cet évènement pour contourner l'anomalie et m'assurer que ma procédure de sortie soit toujours exécutée. Après tests l'évènement 'BeforeSave' même s'il ne réagit pas sur le même évènement est une bonne alternative car ce qui compte c'est l'état enregistré au moment de la sortie de l'application.
De plus il existe aussi l'évènement 'AfterSave' si on veut rétablir le contexte en cas de sauvegarde sans sortir de l'application. Noté que toute modification effectuée par AfterSave n'est pas sauvé au moment de la fermeture de l'appli.

Dites-moi si vous aviez constaté cette spécificité et sur quelle version vous travaillez.
 

Dranreb

XLDnaute Barbatruc
(Pas de Bonjour même à Noël ?)
Non, je ne constate pas ça et j'ai aussi Excel 2016.
Le message est affiché chaque fois que je demande la fermeture.
Et puisque vous parlez d'un autre évènement, il y a aussi Workbook_Deactivate et Workbook_WindowDeactivate.
Il pourrait permettre de détecter une fermeture effective après sauvegarde consentie lors d'une séquence de fermeture engagée. Combinaisons à essayer :
VB:
Option Explicit
Private FermetureDemandée As Boolean
Private Sub Workbook_BeforeClose(Cancel As Boolean)
   FermetureDemandée = True
   End Sub
Private Sub Workbook_Deactivate()
   If FermetureDemandée And Not Me.Saved Then Me.Save
   End Sub
Private Sub Workbook_Activate()
   FermetureDemandée = False
   End Sub
 

TooFatBoy

XLDnaute Barbatruc
Bonjour,

Il faut avoir ce seul classeur ouvert au préalable.
Modifiez la grille sans sauvegarder et fermez le classeur.
Le message 'Event BeforeClose' s'affiche et ensuite la question "Voulez-vous enregistrez ...", choisissez 'Cancel' pour annuler.
Fermez à nouveau le classeur et là le message 'Event BeforeClose' ne s'affiche plus.

Dites-moi si vous aviez constaté cette spécificité et sur quelle version vous travaillez.
Excel 2016.
Ceci dit, si on passe par les menus ( Fichier \ Fermer ), ladite spécificité n'apparaît pas.
 
Dernière édition:

Lu76Fer

XLDnaute Occasionnel
(Pas de Bonjour même à Noël ?)
Non, je ne constate pas ça et j'ai aussi Excel 2016.
Le message est affiché chaque fois que je demande la fermeture.
Et puisque vous parlez d'un autre évènement, il y a aussi Workbook_Deactivate et Workbook_WindowDeactivate.
Il pourrait permettre de détecter une fermeture effective après sauvegarde consentie lors d'une séquence de fermeture engagée. Combinaisons à essayer :
VB:
Option Explicit
Private FermetureDemandée As Boolean
Private Sub Workbook_BeforeClose(Cancel As Boolean)
   FermetureDemandée = True
   End Sub
Private Sub Workbook_Deactivate()
   If FermetureDemandée And Not Me.Saved Then Me.Save
   End Sub
Private Sub Workbook_Activate()
   FermetureDemandée = False
   End Sub
Bonsoir et bien-sûr de bonnes fêtes de Noël Dranreb !
Petite vérification, en faisant le test vous aviez bien ce seul classeur ouvert ?
Je vais tester cet événement aussi mais je suis surpris qu'on est pas le même résultat ... Et il faut aussi utiliser la croix (en haut à droite), comme m'a fait remarquer TooFatBoy.
 

TooFatBoy

XLDnaute Barbatruc
Effectivement, c'est exact dans ce cas cela fonctionne mais cela laisse un trou dans la raquette du coup :rolleyes:
1200x845.jpg
 

patricktoulon

XLDnaute Barbatruc
re
Bonsoir
juste en passant
je n'ai pas bien saisi le problème mais
aurais tu essayé en sub classant
pour bénificier de l'object workbook implémenté
dans l'event original l'object est implicite ce qui peut peut être être le problème en cas de plusieur classeur ouvert )

ci dessous les deux events de substitution

VB:
Public WithEvents app As Application
'event de substitution
Private Sub app_WorkbookBeforeClose(ByVal Wb As Workbook, Cancel As Boolean)
    If Wb.Name = ThisWorkbook.Name Then
        'ton code ici

    End If
End Sub

Private Sub app_WorkbookBeforeSave(ByVal Wb As Workbook, ByVal SaveAsUI As Boolean, Cancel As Boolean)
    If Wb.Name = ThisWorkbook.Name Then
        'ton code ici

    End If
End Sub

'event original
Private Sub Workbook_BeforeClose(Cancel As Boolean)

End Sub

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)

End Sub
 

Lu76Fer

XLDnaute Occasionnel
re
Bonsoir
juste en passant
je n'ai pas bien saisi le problème mais
aurais tu essayé en sub classant
pour bénificier de l'object workbook implémenté
dans l'event original l'object est implicite ce qui peut peut être être le problème en cas de plusieur classeur ouvert )

ci dessous les deux events de substitution

VB:
Public WithEvents app As Application
'event de substitution
Private Sub app_WorkbookBeforeClose(ByVal Wb As Workbook, Cancel As Boolean)
    If Wb.Name = ThisWorkbook.Name Then
        'ton code ici

    End If
End Sub

Private Sub app_WorkbookBeforeSave(ByVal Wb As Workbook, ByVal SaveAsUI As Boolean, Cancel As Boolean)
    If Wb.Name = ThisWorkbook.Name Then
        'ton code ici

    End If
End Sub

'event original
Private Sub Workbook_BeforeClose(Cancel As Boolean)

End Sub

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)

End Sub
Bonsoir Patricktoulon !
Même réaction en passant par une classe ...
Bonne idée mais cela ne change pas le comportement d'Excel.
 

TooFatBoy

XLDnaute Barbatruc
je n'ai pas bien saisi le problème

1- Ouvrir un classeur vierge et ajouter la macro suivante :
VB:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
    MsgBox "Event BeforeClose"
End Sub

2- Enregistrer ce classeur et le fermer.

3- Rouvrir le classeur et modifier le contenu d'une cellule.

4- Cliquer sur la croix pour fermer Excel.

5- Une MsgBox avec le message "Event BeforeClose" s'affiche.

6- Cliquer sur le bouton "OK".

7- Excel demande si on veut enregistrer le classeur : cliquer sur "Annuler" afin de ne pas fermer le classeur.

8- Cliquer de nouveau sur la croix pour fermer Excel.

9- Cette fois-ci la MsgBox avec le message "Event BeforeClose" ne s'affiche pas.
 
Dernière édition:

Lu76Fer

XLDnaute Occasionnel
1- Ouvrir un classeur vierge et ajouter la macro suivante :
VB:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
    MsgBox "Event BeforeClose"
End Sub

2- Enregistrer ce classeur et le fermer.

3- Rouvrir le classeur et modifier le contenu d'une cellule.

4- Cliquer sur la croix pour fermer Excel.

5- Une MsgBox avec le message "Event BeforeClose" s'affiche.

6- Cliquer sur le bouton "OK".

7- Excel demande si on veut enregistrer le classeur : cliquer sur "Annuler" afin de ne pas fermer le classeur.

8- Cliquer de nouveau sur la croix pour fermer Excel.

9- Cette fois-ci la MsgBox avec le message "Event BeforeClose" ne s'affiche pas.
J'ai juste simplifié pour montrer l'anomalie de comportement. Dans mon cas j'ai écrit une interface et je dois changer le contexte avant de quitter l'application pour qu'il n'y ait pas d'anomalie à sa réouverture.
Du coup j'expliquai qu'il fallait mieux éviter d'utiliser cet événement pour faire cela et préférer BeforeSave ou peut-être Workbook_Deactivate comme Dranreb me le suggère : #2
 

Discussions similaires

Statistiques des forums

Discussions
312 213
Messages
2 086 307
Membres
103 174
dernier inscrit
OBUTT