Ceci est une page optimisée pour les mobiles. Cliquez sur ce texte pour afficher la vraie page.

XL 2016 VBA - Lister les UserForms du Projet VBA

Dudu2

XLDnaute Barbatruc
Bonjour,

Je n'obtiens aucun résultat avec ce code:
VB:
Sub a()
    Dim Usf As Object
    Dim k As Integer
    
    For Each Usf In VBA.UserForms
        k = k + 1
        MsgBox k & " " & Usf.Name
    Next Usf
End Sub
Auriez-vous une solution ?
Merci par avance.
 

Pièces jointes

  • Classeur1.xlsm
    24.3 KB · Affichages: 4

Dudu2

XLDnaute Barbatruc
Bonjour les Experts,
Je viens de découvrir un truc qui vraiment m'a fait perdre un temps fou de debug !
Le simple fait de tester UserForm1.Visible lance sa fonction UserForm1_Initialize !
Et donc évidemment en fait un Load préalable !

Alors ok, vous allez me dire c'est normal, il faut que le bidule soit instancié quelque part pour tester sa propriété Visible. Mais en pure logique d'utilisation ce n'est pas si évident que ça.

Et cerise sur le gâteau ! Un simple Unload UserForm1 si UserForm1 n'est pas "Loadé" lance sa fonction UserForm_Initialize !

Donc on ne peut faire référence à aucune des propriétés (.Name, .Caption, .Visible, etc...) du UserForm sans de passer dans cette foutue fonction !

D'ou la nécessité, comme dans la fonction de @Hasco, de passer par une string et pas par l'objet pour tester s'il est affiché.
VB:
'----------------------------
'Test si UserForm est affiché
'Attention ! Si l'argument est UserFormX.Name alors il sera chargé et sa fontion UserForm_Initialize sera exécutée
'Voir https://excel-downloads.com/threads/vba-lister-les-userforms-du-projet-vba.20071238/page-3#post-20540897
'----------------------------
Public Function UserFormIsVisible(UsfName As String) As Boolean
    Dim Usf As Object
 
    'Parcours des UserForms chargés dans le Projet
    For Each Usf In VBA.UserForms
        If UCase(Usf.Name) = UCase(UsfName) Then
            If Usf.Visible Then Exit For
        End If
    Next Usf
 
    If Not Usf Is Nothing Then
        'Return value
        UserFormIsVisible = True
    End If
End Function

VB:
'---------------------------
'Test si UserForm est chargé = Load avec Visible = False (Hide) ou True (Show)
'Attention ! Si l'argument est UserFormX.Name alors il sera chargé et sa fontion UserForm_Initialize sera exécutée
'Voir https://excel-downloads.com/threads/vba-lister-les-userforms-du-projet-vba.20071238/page-3#post-20540897
'----------------------------
Public Function UserFormIsLoaded(UsfName) As Boolean
    Dim Usf As Object
 
    'Parcours des UserForms effectivement chargés dans le Projet
    For Each Usf In VBA.UserForms
        If UCase(Usf.Name) = UCase(UsfName) Then Exit For
    Next Usf
 
    If Not Usf Is Nothing Then
        'Return value
        UserFormIsLoaded = True
    End If
End Function
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
Donc, cet évènement UserForm_Initialize() est une vraie source de problèmes, utilisation à éviter !

Et lorsqu'on doit dissocier des actions d'initialisation du UserForm de celles d'activation (car on peut repasser par le UserForm_Activate() suite par exemple au retour d'un autre UserForm appelé par le premier) mieux vaut gérer un Private flag qui est remis à zéro à chaque UserForm.Show.
Code:
Private Init As Boolean

Private Sub UserForm_Activate()
    MsgBox "UserForm1 Activate"
  
    If Not Init Then
        Call UserForm1_Initialize
        Init = True
    End If
End Sub

Private Sub UserForm1_Initialize()
    MsgBox "UserForm1 Initialize"
End Sub

Private Sub CommandButtonUserForm2_Click()
    UserForm2.Show
End Sub
 

Pièces jointes

  • Classeur1.xlsm
    27.2 KB · Affichages: 2
Dernière édition:

patricktoulon

XLDnaute Barbatruc
re

Bonjour @Dudu2
je suis étonné de te voir surpris par ce phénomène qui n'en est pas un en fait
c'est même tout a fait normal et heureusement d'ailleurs

je te le redis
un module userform est un module classe avant tout
a partir du moment ou tu fait appel a userformX.quelquechose tu fait appel a la classe
et comme tout bon module classe ben l'events initialise est déclenché
je ne vois pas ce qui te perturbe là dedans

la seule différence avec un module classe c'est que tu n'a pas besoins de créer l' instances puisqu’à partir du moment ou il y est dans le classeur ouvert l'instance est déjà en route
prete à etre utilisée pour au minimum la fonction "Show"
 

Dudu2

XLDnaute Barbatruc
Bonjour @patricktoulon,
Que ce soit une classe ou autre chose, c'est la cuisine interne d'Excel.
Pour moi un formulaire est... un formulaire. Et il n'est pas évident à priori que, faisant référence à une propriété comme Formulaire-Visible ou Formulaire-Nom, on déclenche sa fonction d'initialisation.

C'est un peu comme si on lisait la plaque d'immatriculation d'une voiture et qu'elle se mettait à démarrer.
 

Dranreb

XLDnaute Barbatruc
J'ai aussi compris tardivement (mais il y a très très longtemps quand même maintenant) que les membres de la rubriques Feuilles ne sont pas comme des voitures mais plutôt comme des schémas de voitures.
Mais ils ont chacun un exemplaire par défaut, comme s'ils étaient déclarés Public SonNom As New SonNom
Et soit dit en passant Excel n'a absolument rien à voir la dedans, tout ça c'est MSForms.
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
re
et pourtant tout fonctionne comme ca en vba
sans exception sauf module standard

C'est un peu comme si on lisait la plaque d'immatriculation d'une voiture et qu'elle se mettait à démarrer.
tu t’égare dans ton raisonnement là
je pense que tu sature ces dernier jours tu a observé ou découvert plusieurs choses qui t’étaient inconnues
mais le contexte n'est pas encore bien assimilé

et je le redis heureusement que c'est comme ça sinon développer en vba serait une vrai torture
le vba est un langage object
ce qui veut dire
  1. instance de l'object
  2. propertie de l'object
  3. fonction de l'object
dans un classeur
quand tu ajoute une feuille tu ajoute son module en même temps (et hop instanciation de la classe feuille)
quand tu ajoute un userform tu ajoute son module (et hop instanciation de la classe UserFormX)
etc..etc...

je dirais presque que c'est ce qu'il faudrait savoir en premier
après vba est tellement assisté que l'on ne fait plus attention à ça
et que me certains developeur vba font des choses formidables sans jamais avoir compris cette base
 

Dudu2

XLDnaute Barbatruc
Oui, ok, merci à vous deux, j'ai à peu près compris de quoi il s'agit. Et au fond, en tant qu'utilisateur de ce système (car c'est ce que je suis) je ne lui demande que de fonctionner et pas de quelle manière il a été mis en place même si c'est intéressant de le savoir.

Comme vous l'aurez remarqué, c'est l'appel à la fonction UserForm_Initialize() que je remets en question du point de vue logique applicative. Mais si Excel a défini cette fonction au moment/évènement d'"exemplariser" le formulaire... soit ! Il faut juste le savoir. C'est à dire savoir que ce n'est pas du tout du tout lié strictement à un UserFromX.Show comme je l'ai supposé depuis 2 ans de manière erronée.

De fait, pour éviter les problèmes (un UserFromX.Visible intempestif ou non remarqué d'un code externe), exit le UserForm_Initialize().
VB:
Private UserFormInitialised As Boolean

'-----------------------
'Initialisation UserForm
'-----------------------
Private Sub UserForm_Initialisation()
    .../...
End Sub

'-----------------
'UserForm Activate
'-----------------
Private Sub UserForm_Activate()
 
    'Initialisation UserForm
    If Not UserFormInitialised Then
        UserFormInitialised = True
        Call UserForm_Initialisation
    End If

    .../...
End Sub
 
Dernière édition:

Hasco

XLDnaute Barbatruc
Repose en paix
Donc, cet évènement UserForm_Initialize() est une vraie source de problèmes, utilisation à éviter !
Bonjour Dudu2,
Non, ce qui est à éviter c'est de vouloir manger sa soupe avec une fourchette !
Les UserForm sont ainsi conçu et vous allez droit dans le mur si vous voulez les voir autrement.
UserForm_Initialize à grandement sa place et son utilitité.

cordialement
 

Dudu2

XLDnaute Barbatruc
Bonjour @Hasco,
UserForm_Initialize à grandement sa place et son utilitité.
Et bien c'est précisément ce que je me demandais à l'instant.
Que doit-on faire dans un UserForm_Initialize qu'on ne pourrait pas faire dans une UserForm_Activate ?
Dans les conditions que je connais maintenant de son déclenchement, perso je n'en ai aucune utilité, mais s'il existe je suppose qu'il en a.
 

Dranreb

XLDnaute Barbatruc
Bien sûr qu'il faut le savoir mais Excel n'a absolument rien à voir la dedans, tout ça c'est MSForms.
Quel problème avec la propriété Visible ?
Il est possible d'ajouter des méthodes et des propriétés à un UserForm. Je le fais souvent.
Dans l'UserForm_Initialize on doit initialiser ce qui est nécessaire pour des Show futurs, et dans l'UserForm_Activate on doit ajuster ce qui peut être particulier à un Show
 

Dudu2

XLDnaute Barbatruc
Dans l'UserForm_Initialize on doit initialiser ce qui est nécessaire pour des Show futurs
Non car l'UserForm_Initialize n'est pas srtictement lié à un Show. Alors tu peux faire ça si tu veux, mais quel intérêt de le faire en UserForm_Initialize plutôt qu'en UserForm_Activate qui lui est spécifiquement lié au Show ?

Quel problème avec la propriété Visible ?
Il n'y a pas de problème avec Visible. Simplement tu déclenches UserForm_Initialize que tu as programmé pour préparer un Show. C'est effectivement ce que je faisais avant cette discussion.
 

Dranreb

XLDnaute Barbatruc
J'aurais plutôt du dire que dans l'UserForm_Initialize on doit initialiser ce qui est nécessaire à la cohérence fonctionnelle possible de l'objet, qu'il fasse ou non l'objet d'un Show ultérieur.
Par exemple s'il utilise des objets j'en fais les Set d'initialisation.
 

Discussions similaires

Réponses
4
Affichages
439
Les cookies sont requis pour utiliser ce site. Vous devez les accepter pour continuer à utiliser le site. En savoir plus…