Fermeture et enregistrement d'un classeur Excel à partir d'un bouton

Messages postés
18
Date d'inscription
vendredi 29 février 2008
Statut
Membre
Dernière intervention
11 septembre 2009
- - Dernière réponse : cs_petchy
Messages postés
710
Date d'inscription
jeudi 20 février 2003
Statut
Membre
Dernière intervention
19 mai 2015
- 4 sept. 2009 à 10:01
Bonjour à tous,

J'ai un fichier Excel qui propose l'enregistrement de mon classeur à la fermeture par l'événement BeforeClose :

' A la fermeture du classeur
Private Sub Workbook_BeforeClose(Cancel As Boolean)
    ' On vérifie si le classeur est ouvert en lecture seule ou non
    If Not Me.ReadOnly Then
        ' On demande si l'utilisateur veut enregistrer les modifications
        Msgresult = MsgBox("Attention, vous êtes sur le point de quitter le fichier en mode écriture." & vbCrLf & _
                            " Souhaitez vous enregistrer les modifications apportées ?" & vbCrLf & vbCrLf & _
                            "Si vous sélectionnez NON, toutes les modifications seront perdues !" _
                            , vbYesNoCancel, "Sauvegarder les modifications ...")
                            
        If Msgresult = vbYes Then        
            ' On enregistre le classeur
            Me.Save
            ElseIf Msgresult = vbNo Then
                ' On ignore les modifications que le classeur a subi.
                Me.Saved = True
                Else
                    Cancel = True
                    Exit Sub
        End If
        Else
            ' On considére qu'il est enregistré pour ne pas afficher le message d'enregistrement
            '       et ainsi on ignore les modifications que le fichier a subi.
            Me.Saved = True
    End If
    
    ' On met fin à l'éxecution du code et on libère les ressources
    End
End Sub


Mon problème est le suivant: ce code (simplifié) fonctionne parfaitement lorsque je clique sur fermer Excel ou le classeur, les croix en haut à droite de l'écran.
Pour plus de convivialité sur mon classeur, j'ai ajouté un bouton QUITTER auquel j'ai associé la macro Quitter.

Sub Quitter()
    ThisWorkbook.Close
End Sub


Malheureusement pour moi, cela ne fonctionne pas.
La macro déclenche bien l'événement BeforeClose qui m'affiche le MsgBox mais lorsque je veux enregistrer, le code exécute Me.save mais sans conséquence. A la fin de la procédure j'obtiens la fenêtre Excel: "Voulez vous sauvegarder ?", qui ne devrait pas s'afficher. (et si toutefois je sélectionne oui pour enregistrer, j'obtiens une erreur de violation de partage).
J'ai constaté que plusieurs fonction tel que la sélection de feuille ne fonctionne pas dans les mêmes circonstances.

J'ai aussi essayé, sans succès :
Sub Quitter()
    Application.Quit
End Sub


Quelqu'un peux t-il m'expliquer pourquoi mon code ne fonctionne pas de la même façon suivant que j'utilise la croix ou la fonction thisworkbook.close et comment puis-je faire pour corriger ce problème ???

Toute aide me sera précieuse !

Vincent Kro à votre service.
Afficher la suite 

11 réponses

Meilleure réponse
Messages postés
710
Date d'inscription
jeudi 20 février 2003
Statut
Membre
Dernière intervention
19 mai 2015
3
1
Merci
peut etre que la variable Me.Save
ne conrespond pas,as tu essayer avec
ActiveWorkbook.Save
a part ça je ne voit pas,désolé

Dire « Merci » 1

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 218 internautes nous ont dit merci ce mois-ci

Commenter la réponse de cs_petchy
Messages postés
710
Date d'inscription
jeudi 20 février 2003
Statut
Membre
Dernière intervention
19 mai 2015
3
0
Merci
salut
pourquoi tu ne met pas ton code dans un moduel.?

Sub quit()
' On vérifie si le classeur est ouvert en lecture seule ou non
If Not Me.ReadOnly Then
' On demande si l'utilisateur veut enregistrer les modifications
Msgresult = MsgBox("Attention, vous êtes sur le point de quitter le fichier en mode écriture." & vbCrLf & _
" Souhaitez vous enregistrer les modifications apportées ?" & vbCrLf & vbCrLf & _
"Si vous sélectionnez NON, toutes les modifications seront perdues !" _
, vbYesNoCancel, "Sauvegarder les modifications ...")

If Msgresult = vbYes Then
' On enregistre le classeur
Me.Save
ElseIf Msgresult = vbNo Then
' On ignore les modifications que le classeur a subi.
Me.Saved = True
Else
Cancel = True
Exit Sub
End If
Else
' On considére qu'il est enregistré pour ne pas afficher le message d'enregistrement
' et ainsi on ignore les modifications que le fichier a subi.
Me.Saved = True
End If

' On met fin à l'éxecution du code et on libère les ressources
End

End Sub

petchy
Commenter la réponse de cs_petchy
Messages postés
18
Date d'inscription
vendredi 29 février 2008
Statut
Membre
Dernière intervention
11 septembre 2009
1
0
Merci
Salut Petchy,

J'ai déjà pensé à cette idée mais je ne pense pas que cela est judicieux pour mon cas.
Je m'explique, mon code permet d'enregistrer le classeur avant de le fermer.

Si je fais un module pour le faire, à la fermeture du classeur j'appelle le module.
Lorsque je vais appelé le module à partir du bouton, je vais appelé le module et ensuite fermer le classeur, ce qui va entraîner l'exécution du module par l'événement BeforeClose.
Je pense que mon idée de départ et correcte mais doit être améliorée !

Dis moi voir comment tu vois là chose ?

Vincent Kro à votre service.
Commenter la réponse de Vincentkro
Messages postés
710
Date d'inscription
jeudi 20 février 2003
Statut
Membre
Dernière intervention
19 mai 2015
3
0
Merci
Re
essaye se code dans Workbook_BeforeSave
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
' On vérifie si le classeur est ouvert en lecture seule ou non
    'If Not Me.ReadOnly Then
        ' On demande si l'utilisateur veut enregistrer les modifications
        Msgresult = MsgBox("Attention, vous êtes sur le point de quitter le fichier en mode écriture." & vbCrLf & _
                            " Souhaitez vous enregistrer les modifications apportées ?" & vbCrLf & vbCrLf & _
                            "Si vous sélectionnez NON, toutes les modifications seront perdues !" _
                            , vbYesNoCancel, "Sauvegarder les modifications ...")
                            
        If Msgresult = vbYes Then
            ' On enregistre le classeur
        Me.Save
     
            ElseIf Msgresult = vbNo Then
                ' On ignore les modifications que le classeur a subi.
                Me.Saved = True
                Else
                    Cancel = True
                    Exit Sub
                    
        End If
      
            ' On considére qu'il est enregistré pour ne pas afficher le message d'enregistrement
            '       et ainsi on ignore les modifications que le fichier a subi.
            Application.DisplayAlerts = False
          
            Application.Quit
          
End Sub


Sub Quitter()
  Application.DisplayAlerts = False
   ThisWorkbook.Close
End Sub


petchy
Commenter la réponse de cs_petchy
Messages postés
710
Date d'inscription
jeudi 20 février 2003
Statut
Membre
Dernière intervention
19 mai 2015
3
0
Merci
oups,une petite erreur
Private Sub CommandButton1_Click()
ThisWorkbook.Save
Application.DisplayAlerts = False
End Sub
Commenter la réponse de cs_petchy
Messages postés
18
Date d'inscription
vendredi 29 février 2008
Statut
Membre
Dernière intervention
11 septembre 2009
1
0
Merci
Merci des réponses,

J'ai encore un petit souci, je pense que ta solution d'utiliser BeforeSave est bonne, mais j'ai un autre problème.
Si j'utilise :
Private Sub Workbook_BeforeClose(Cancel As Boolean)
    Me.Save
    Application.DisplayAlerts = False
End sub


le code fonctionne, petite modification tout de même :
        If Msgresult = vbYes Then
            ' On enregistre le classeur
            Me.Save
            ElseIf Msgresult = vbNo Then
                ' On ignore les modifications que le classeur a subi.
                ' Me.Saved = True --> Sans effet dans l'événement BeforeSave (puisque l'on a demandé l'enregistrement)
                Cancel = True
                Else
                    Cancel = True
                    Exit Sub
        End If


Par contre, lorsque je ferme le classeur, je peux enregistrer mais je ne peux plus empêcher sa fermeture !
Je ne souhaite pas submerger l'utilisateur de messages(un pour la fermeture, un pour l'enregistrement, etc.).

Est-il possible d'annuler la fermeture dans le BeforeSave ?

Vincent Kro à votre service.
Commenter la réponse de Vincentkro
Messages postés
710
Date d'inscription
jeudi 20 février 2003
Statut
Membre
Dernière intervention
19 mai 2015
3
0
Merci
pourquoi tu veut utiliser l'événement
Private Sub Workbook_BeforeClose(Cancel As Boolean)

Est-il possible d'annuler la fermeture dans le BeforeSave ?

oui,tu enleve
Application.Quit

petchy
Commenter la réponse de cs_petchy
Messages postés
18
Date d'inscription
vendredi 29 février 2008
Statut
Membre
Dernière intervention
11 septembre 2009
1
0
Merci
Re,

Désolé de ne pas avoir explicité correctement mon idée:

Principe:
1 classeur excel
2 types utilisateurs :
- Admin: classeur en écriture
- User: classeur en lecture seul ainsi que l'attribut du fichier pour ne pas avoir le message d'ouverture en lecture seule à l'ouverture de mon classeur.

L'idée et de dire, lorsque je ferme mon classeur (peu importe comment) et que le classeur est en écriture(mode admin), j'affiche mon message. Ce message à trois choix:
- OUI: je sauvegarde et je ferme le classeur
- NON: je ferme le classeur sans le sauvegarder
- CANCEL: j'annule la fermeture de mon classeur

Maintenant, tu comprendra mieux mes choix de départ, je pense!
Le BeforeClose n'est pas vraiment le problème, il fonctionne à merveille avec mon petit bout de code, là où je ne comprend plus c'est pourquoi lorsque pour des raisons pratiques, je souhaite automatiser la fermeture du classeur par un bouton et une macro, mon code fonctionne "à moitié".

Pourtant après pas mal de tentatives, j'arrive toujours au même résultat, l'événement est bien déclenché (que j'utilise les croix ou que j'utilise ThisWorkbook.Close) mais lorsqu'il est déclenché par du code certaines des fonctions restes sans effets et sans erreur. Pour mon cas, j'ai une fonction select, pour afficher une feuille définie et la plus ennuyante, la fonction Me.Save qui ne sauvegarde rien du tout.

Si tu vois mieux l'intérêt d'utiliser le BeforeClose, tu pourra peut-être m'aider à comprendre ce qui cloche dans mon code ?
Pour l'instant j'ai l'impression qu'il n'y a pas d'erreur et que je fais de la bidouille pour arriver à mes fins. J'aimerai vraiment comprendre où est l'erreur, si erreur il y a et surtout comment la corriger !

En tout cas merci du temps que tu passe pour m'aider.

Vincent Kro à votre service.
Commenter la réponse de Vincentkro
Messages postés
18
Date d'inscription
vendredi 29 février 2008
Statut
Membre
Dernière intervention
11 septembre 2009
1
0
Merci
Malheureusement pour moi, oui :

j'ai même essayé workbooks(Me.Name).save.
sans succès !

Le pire, c'est que le Me est reconnu car avec un MsgBox Me.Name
je récupère bien le nom de mon classeur.

Je suis perplexe

Vincent Kro à votre service.
Commenter la réponse de Vincentkro
Messages postés
18
Date d'inscription
vendredi 29 février 2008
Statut
Membre
Dernière intervention
11 septembre 2009
1
0
Merci
Re,

J'ai un peu progressé sur mon pb !

Après beaucoup de recherches, je suis tombé là dessus :
--> http://support.microsoft.com/kb/898511/fr
--> http://support.microsoft.com/kb/816138/fr

Autant dire que les explications ne sont pas très limpide mais ce que j'en ai compris,
c'est qu'il ne faut pas espérer réaliser du code dans les événements lorsqu'ils sont déclenchés eux mêmes par du code.

J'ai donc modifié ("Bidouiller") mon code, en passant le tout dans une macro que j'associe à mon bouton QUITTER et que j'appelle à l'événement BeforeClose :
' A la fermeture du classeur
Private Sub Workbook_BeforeClose(Cancel As Boolean)
    If Not Me.ReadOnly And Not Me.Saved Then
        Call Quitter    ' Module6
    End If
End Sub


' **********************************************************************************************************
' ***************                          Fermer le classeur Excel                          ***************
' **********************************************************************************************************
Sub Quitter()
    Dim Feuil As Worksheet
    Dim Msgresult As VbMsgBoxResult
    
    ' On vérifie si le classeur est ouvert en lecture seule ou non
    If Not ThisWorkbook.ReadOnly Then
        ' On demande si l'utilisateur veut enregistrer les modifications
        Msgresult = MsgBox("Attention, vous êtes sur le point de quitter le tableau de bord en mode écriture." & vbCrLf & _
                            " Souhaitez vous enregistrer les modifications apportées ?" & vbCrLf & vbCrLf & _
                            "Si vous selectionnez NON, toutes les modifications seront perdues !" _
                            , vbYesNoCancel, "Sauvegarder les modifications ...")
                            
        If Msgresult = vbYes Then
            ' Affiche le bouton d'identification (Il réalise la même chose que l'ouverture du formulaire)
            Set Feuil = ThisWorkbook.Worksheets("Init")
            Feuil.Select
            
            ' On masque les onglets du classeur
            Windows(ThisWorkbook.Name).DisplayWorkbookTabs = False
            
            ' On enregistre le classeur
            ThisWorkbook.Save
            ElseIf Msgresult = vbNo Then
                ' On ignore les modifications que le classeur a subi.
                ThisWorkbook.Saved = True
                Else
                    Exit Sub
        End If
        
        ' On modifie l'attribut du fichier en lecture seule
        SetAttr ThisWorkbook.FullName, vbReadOnly  ' Evite l'affichage de la demande du mot de passe ou de la lecture seule à l'ouverture du fichier
        
        Else
            ' On considére qu'il est enregistré pour ne pas afficher le message d'enregistrement
            '       et ainsi on ignore les modifications que le fichier a subi.
            ThisWorkbook.Saved = True
    End If
    
    ' On ferme le classeur
    ThisWorkbook.Close
    
    ' On met fin à l'éxecution du code et on libère les ressources
    End
End Sub


Le Not Me.Saved est indispensable dans l'événement BeforeClose pour ne pas effectuer deux fois la procédure de sauvegarde à la fermeture du classeur.

Voilà, si ça peut aider quelqu'un !
Si vous avez mieux à me proposer, je suis toujours preneur !

Vincent Kro à votre service.
Commenter la réponse de Vincentkro
Messages postés
710
Date d'inscription
jeudi 20 février 2003
Statut
Membre
Dernière intervention
19 mai 2015
3
0
Merci
salut
ben voila ,si ça fonctionne en passant par un module tans mieux.
@ plus
petchy
Commenter la réponse de cs_petchy