Problème avec un bouton "Fermer"

alias_2003

XLDnaute Occasionnel
Bonjour à tous,
Mon fichier "exemple" ci-joint contient un userform me permettant de masquer l'application excel, condition indispensable pour mon fichier. Mon fichier "exemple" peut exister sous plusieurs copies.
Pour naviguer entre différents fichiers excel ouverts, j'ai ajouté une variable boolean "userform1_visible" qui permet de masquer l'userform1 lorsque le fichier est désactivé et qu'un autre fichier est affiché ou d'afficher l'userform1 lorsque le classeur est activé.
Tout fonctionne bien.
Mais problème est le suivant : j'ai un bouton "fermer" dans mon classeur pour fermer le fichier. Lorsque plusieurs fichiers du même type (cad contenant cet userform1) sont ouverts, si je clique sur le bouton "Fermer" d'un fichier, celui-ci est fermer, mais le problème est que le classeur qui s'affiche ensuite, n'est pas activé et que l'userform1 ne s'affiche pas.
Avez-vous une idée pour résoudre ce problème ??
Merci beaucoup,
Bonne journée
 

Pièces jointes

  • Exemple.xlsm
    18.1 KB · Affichages: 67
  • Exemple.xlsm
    18.1 KB · Affichages: 71
  • Exemple.xlsm
    18.1 KB · Affichages: 77
Dernière édition:

alias_2003

XLDnaute Occasionnel
Re : Problème avec un bouton "Fermer"

Bonjour à tous,
si je reprends mon problème, il revient à :
* si un seul classeur est ouvert, on quitte l'application excel. Pas de problème.
* si plusieurs classeurs sont ouverts, lorsque l'on clique sur "Fermer", on recense les classeurs ouverts (leur nom ?), on ferme le classeur actif et on active le suivant. Ou sinon, reproduire ce que fait le clic sur la croix rouge du classeur.
Est-ce possible ???
Merci à tous,
Bonne journée
 
Dernière édition:

PMO2

XLDnaute Accro
Re : Problème avec un bouton "Fermer"

Bonjour,

Constat :
Votre programme se déroule et doit se dérouler dans une seule et unique instance d'Excel.
***
Pourquoi votre code est inopérant :
1) Vous utilsez une variable de portée publique (Public userform1_visible As Boolean) portant le même nom dans chaque classeur. Elle n'aura qu'une seule valeur.
2) Les évènements Workbook_Activate (et autres) sont définis au niveau classeur.
Si un classeur à la main, les évènements ne sont pas répercutés sur les autres classeurs.
***
Piste à suivre :
Pour palier aux 2 causes susdites, il convient d'utiliser un module de classe application qui permet de créer plusieurs instances de la classe.
1) On n'a plus besoin de variable publique
2) Les évènements propres à un classeur seront encapsulés dans l'instance de classe et seront indépendants des évènements des autres classeurs.
***

MARCHE A SUIVRE :
1) Créez un module de classe "Classe1" et copiez le code suivant dans sa fenêtre de code
Code:
Public WithEvents XLapp As Application
Dim USF As Object

Private Sub GetUSF()
Dim VBComp As Object
For Each VBComp In ThisWorkbook.VBProject.VBComponents
  If VBComp.Type = 3 Then
    Set USF = VBA.UserForms.Add(VBComp.Name)
    Exit For
  End If
Next VBComp
End Sub

Private Sub XLapp_WorkbookActivate(ByVal Wb As Workbook)
If ThisWorkbook Is Wb Then
  If USF Is Nothing Then GetUSF
  On Error Resume Next
  USF.Show vbModeless
End If
End Sub

Private Sub XLapp_WorkbookDeactivate(ByVal Wb As Workbook)
On Error Resume Next
If ThisWorkbook Is Wb Then
  If Not USF Is Nothing Then USF.Hide
End If
End Sub

Private Sub XLapp_WorkbookBeforeClose(ByVal Wb As Workbook, Cancel As Boolean)
If Not ThisWorkbook Is Wb Then
  On Error Resume Next
  USF.Show vbModeless
End If
End Sub

2) Copiez le code suivant dans la fenêtre de code de UserForm1
Code:
Private Sub Fermer_Click()
If Application.Workbooks.Count = 1 Then
  Application.Quit
Else
  ThisWorkbook.Close savechanges:=False
End If
End Sub

Private Sub UserForm_Initialize()
Me.Width = Application.Width - 10
Me.Height = Application.Height - 5
End Sub

3) Copiez le code suivant dans la fenêtre de code de ThisWorkbook
Code:
Dim AppClass As New Classe1

Private Sub Workbook_Open()
Set AppClass.XLapp = Application
End Sub

4) Vérifiez si tout fonctionne en réouvrant le classeur concerné
5) Si c'est bien le cas, copiez plusieurs fois le classeur et ouvrez les tous pour faire un test

Je mets, en pièce jointe, un dossier zippé contenant un classeur exemple accompagné de 2 copies (ils sont tous à ouvrir dans la même instance Excel).
Merci de me tenir au courant.
 

Pièces jointes

  • Dossier exemples pour alias_2003.zip
    69.8 KB · Affichages: 44

alias_2003

XLDnaute Occasionnel
Re : Problème avec un bouton "Fermer"

Bonsoir PM02,
J'ai testé ta brillante solution et elle fonctionne très bien !
Malheureusement, je dois ajouter une contrainte supplémentaire : un ou plusieurs userform(s) qui s'affichent à partir de ce userform principal. Est-ce que votre code peut s'appliquer dans ce cas ?
Merci encore de votre aide,
Bonne soirée !
 

Pièces jointes

  • Exemple_pmo New.xlsm
    27.8 KB · Affichages: 52

alias_2003

XLDnaute Occasionnel
Re : Problème avec un bouton "Fermer"

Bonjour à tous,
Je me permets de revenir vers vous au sujet de cette demande. La solution que PM02 m'a apportée est parfaite. Merci encore !
Dans mon fichier d'origine, l'usf comporte une procédure qui demande à l'usf de se fermer, puis de se rouvrir. Cette procédure me permet de bloquer certains champs de l'usf. Mon soucis est que dès lors, les variables USF et wb contenues dans le module de classe, ne sont plus définies et le module de classe devient inopérant.
Je vous joins un fichier exemple: faites le test en ouvrant ce fichier, puis un autre et en naviguant de l'un à l'autre, l'userform1 apparaît ou disparaît selon le fichier. Tout fonctionne parfaitement !
Si maintenant, vous cliquez sur le bouton"Unload and show" et que vous essayiez de naviguer d'un fichier à l'autre, l'userform reste toujours au premier plan...
Auriez-vous la gentillesse de m'aider svp ?
Merci beaucoup,
Bon we :)
 

Pièces jointes

  • Exemple_pmo.xlsm
    21.2 KB · Affichages: 42
  • Exemple_pmo.xlsm
    21.2 KB · Affichages: 46
  • Exemple_pmo.xlsm
    21.2 KB · Affichages: 50
Dernière édition:

PMO2

XLDnaute Accro
Re : Problème avec un bouton "Fermer"

Dans mon fichier d'origine, l'usf comporte une procédure qui demande à l'usf de se fermer, puis de se rouvrir. Cette procédure me permet de bloquer certains champs de l'usf. Mon souci est que dès lors, les variables USF et wb contenues dans le module de classe, ne sont plus définies et le module de classe devient inopérant.
Bonjour,

L'erreur vient du fait d'essayer d'ouvrir directement UserForm1 sans passer par la classe.
*****

Il faut rendre publique la méthode GetUSF de la classe afin qu'elle soit accessible de l'extérieur
1) Code Classe1
Code:
Public WithEvents XLapp As Application

'/////////////////////////////////////////////////////////////////
'/// Nécessité de rendre la méthode publique (Public vs Private)
'/// car l'USF est UnLoader dans le code de UserForm1
Public Sub GetUSF()   'Private Sub GetUSF()
Dim VBComp As Object
For Each VBComp In ThisWorkbook.VBProject.VBComponents
  If VBComp.Type = 3 Then
    Set USF = VBA.UserForms.Add(VBComp.Name)
    Exit For
  End If
Next VBComp
End Sub
'/////////////////////////////////////////////////////////////////

Private Sub XLapp_WorkbookActivate(ByVal Wb As Workbook)
If ThisWorkbook Is Wb Then
  If USF Is Nothing Then GetUSF
  On Error Resume Next
  USF.Show vbModeless
End If
End Sub

Private Sub XLapp_WorkbookDeactivate(ByVal Wb As Workbook)
On Error Resume Next
If ThisWorkbook Is Wb Then
  If Not USF Is Nothing Then USF.Hide
End If
End Sub

Private Sub XLapp_WorkbookBeforeClose(ByVal Wb As Workbook, Cancel As Boolean)
If Not ThisWorkbook Is Wb Then
  On Error Resume Next
  USF.Show vbModeless
End If
End Sub

2) Dans un module Standard
Code:
'### Variables de classe rendues publiques ###
Public AppClass As Classe1
Public USF As Object

3) Dans la fenêtre de code de ThisWorkbook
Code:
Private Sub Workbook_Open()
Set AppClass = New Classe1
Set AppClass.XLapp = Application
End Sub

4) Dans la fenêtre de code de UserForm1
Code:
Private Sub CommandButton1_Click()
Unload Me
'///////////////////////////////////////////////////
'/// Appelle la méthode GetUSF et ouvre l'UserForm
'/// par la classe et NON PAS par UserForm1.Show
'///////////////////////////////////////////////////
Call AppClass.GetUSF
USF.Show vbModeless
End Sub

Private Sub Fermer_Click()
If Application.Workbooks.Count = 1 Then
  Application.Quit
Else
  ThisWorkbook.Close savechanges:=False
End If
End Sub

Private Sub UserForm_Initialize()
Me.Width = Application.Width - 10
Me.Height = Application.Height - 5
End Sub
 

Pièces jointes

  • Exemple_pmo 2.00.xlsm
    19 KB · Affichages: 55

alias_2003

XLDnaute Occasionnel
Re : Problème avec un bouton "Fermer"

Bonjour PMO2, le Forum,
Je reviens vers vous pour, je l’espère, un ultime problème… J’aimerais protéger mon projet vba par un mot de passe, ce qui n’est pas compliqué :).
Par contre, dans ce cas, à l’ouverture du fichier, j’obtiens une erreur « 50289 », sans qu’il me soit possible de débugger…je ne peux alors que fermer le fichier.
Auriez-vous svp une idée ou une solution à ce problème ?
Merci beaucoup pour tout,
Bonne journée,
Amicalement
 

PMO2

XLDnaute Accro
Re : Problème avec un bouton "Fermer"

Je reviens vers vous pour, je l’espère, un ultime problème… J’aimerais protéger mon projet vba par un mot de passe, ce qui n’est pas compliqué .
Par contre, dans ce cas, à l’ouverture du fichier, j’obtiens une erreur « 50289 », sans qu’il me soit possible de débugger…je ne peux alors que fermer le fichier.

Bonjour,

Dans le module de classe, changez le code de la procédure Public Sub GetUSF() par le code suivant en prenant garde de signifier le nom exact du Userform
Code:
'/////////////////////////////////////////////////////////////////
'/// Nécessité de rendre la méthode publique (Public vs Private)
'/// car l'USF est UnLoader dans le code de UserForm1
Public Sub GetUSF()   'Private Sub GetUSF()

  '°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
  '°°° Si le projet est protégé par un mot de passe, ne pas utiliser
  '°°° les instructions suivantes pour éviter une erreur 50289
  '°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
'Dim VBComp As Object
'For Each VBComp In ThisWorkbook.VBProject.VBComponents
'  If VBComp.Type = 3 Then
'    Set USF = VBA.UserForms.Add(VBComp.Name)
'    Exit For
'  End If
'Next VBComp

  '°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
  '°°° mais plutôt cette instruction (faire attention au Name de l'Userform)
  '°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°
Set USF = Userform1

End Sub
'/////////////////////////////////////////////////////////////////
 

alias_2003

XLDnaute Occasionnel
Re : [Résolu] Problème avec un bouton "Fermer"

Bonjour à tous,
Je reviens vers vous pour une question toujours sur ce sujet : le code de PMO2 fonctionne parfaitement (Merci encore !!), j'aimerais ajouter une condition. J'aimerais qu'il ne soit pas possible de déplacer, redimensionner l'userform et ce, en gardant les fonctionnalités du code de PMO2 ! Est-ce possible ?
Merci beaucoup,
Amicalement
 

Statistiques des forums

Discussions
312 963
Messages
2 093 996
Membres
105 906
dernier inscrit
aifa