XL 2016 VBA - Comment savoir dans le code d'un UserForm s'il a été ouvert en vbModal ou vbModeless ?

  • Initiateur de la discussion Initiateur de la discussion Dudu2
  • Date de début Date de début

Boostez vos compétences Excel avec notre communauté !

Rejoignez Excel Downloads, le rendez-vous des passionnés où l'entraide fait la force. Apprenez, échangez, progressez – et tout ça gratuitement ! 👉 Inscrivez-vous maintenant !

Solution
Tu as mis le doigt sur quelque chose d'inattendu !
Si Obj est un Frame TypeOf Obj Is UserForm = True !!!

Je trouve cela très étrange et je ne sais pas si cela fait sens mais je dirais que c'est un bug car le TypeOf Frame existe bel et bien.

Le bon code est donc:
VB:
'-------------------------------------
'Mode d'affichage du UserForm
'
'- Obj est soit un Control du UserForm
'          soit un UserForm
'
'- Return: vbModal (1)
'          vbModeless (0)
'          Erreur (-1)
'-------------------------------------
Function UserFormShowMode(ByVal Obj As Object) As Integer
    On Error Resume Next
    
    'Cherche l'objet au sommet de la hiérarchie
    Do While Err.Number = 0
        Set Obj =...
J'adore me poser des questions à moi-même.
1628262429674.gif


Et pour ceux qui auraient la même...
VB:
'-------------------------------------
'Mode d'affichage du UserForm
'
'- Obj est soit un Control du UserForm
'          soit un UserForm
'
'- Return: vbModal (1)
'          vbModeless (0)
'          Erreur (-1)
'-------------------------------------
Function UserFormShowMode(Obj As Object) As Integer
    On Error Resume Next
    
    If TypeOf Obj Is UserForm Then
        Obj.Show vbModeless
    ElseIf TypeOf Obj.Parent Is UserForm Then
        Obj.Parent.Show vbModeless
    Else
         UserFormShowMode = -1
    End If
    
    If Err.Number = 0 Then
        UserFormShowMode = vbModeless
    Else
        UserFormShowMode = vbModal
    End If
    
    On Error GoTo 0
End Function
 
J'ai pas de solution miracle. Je fais ça:
VB:
'-------------------------------------
'Mode d'affichage du UserForm
'
'- Obj est soit un Control du UserForm
'          soit un UserForm
'
'- Return: vbModal (1)
'          vbModeless (0)
'          Erreur (-1)
'-------------------------------------
Function UserFormShowMode(ByVal Obj As Object) As Integer
    On Error Resume Next
   
    'Init Return Value
    UserFormShowMode = -1
   
    While Not TypeOf Obj Is UserForm
        Set Obj = Obj.Parent
        If Err.Number Then GoTo ExitFunction
    Wend
   
    Obj.Show vbModeless
   
    'Return Value
    If Err.Number = 0 Then
        UserFormShowMode = vbModeless
    Else
        UserFormShowMode = vbModal
    End If
   
ExitFunction:
    On Error GoTo 0
End Function
 
re
tiens
en fait il te faut remonter le parent avant tout test
dans une simple boucle do while
et ce n'est qu'ensuite que tu peux tester en mettant une reserve ici 200 tours de boucle
ca devrait pas mal couvrir les eventuelles imbrication de conctrol (arrière grand père/grand père/parent/enfant/petit fils etc...) a auteur de 200 imbrications
🤣
je bloque à 200 tours avec I
si malgré tout au bout de 200 tours obj n'est toujours pas un userform c'est "-1"
la boucle s’arrête aussi à obj="application"

et voila tu peux tester tout et n'importe quoi tu devrais recevoir la réponse adéquate

VB:
Sub testNonModal()
    UserForm1.Show 0
End Sub
Sub testModal()
    UserForm1.Show
End Sub
Sub test_avec_un_control_du_userform()    'le meme test est efectué au click sur le bouton dans le userform  en modal
    MsgBox UserFormShowMode(UserForm1.CommandButton1)
End Sub
Sub test_avecquelquechose()    'pour provoquer une erreur on injecte n'importe quoi
    MsgBox UserFormShowMode([A1])

    Dim toto As Object
    MsgBox UserFormShowMode(toto)

    MsgBox UserFormShowMode(ActiveSheet)

End Sub


'-------------------------------------
'Mode d'affichage du UserForm
'
'- Obj est soit un Control du UserForm
'          soit un UserForm
'
'- Return: vbModal (1)
'          vbModeless (0)
'          Erreur (-1)
'-------------------------------------
Function UserFormShowMode(Obj As Object) As Integer
    Dim I&
    On Error Resume Next
    If Not TypeOf Obj Is UserForm Then
        Do While TypeName(Obj) <> "UserForm" And I < 200 Or TypeName(Obj) <> "Application": I = I + 1: Set Obj = Obj.Parent
            Debug.Print TypeName(Obj)
            If Err.Number > 0 Then Err.Clear: Exit Do
        Loop
    End If

    'on teste quand meme  typeof  userform au cas ou la boucle aurait atteint 200 sans trouver le parent userform avec l'obj injecté
    ' le 200eme parent d'un control devrait couvrir pas mal la remonter si controls beaucoup imbriqué  :) LOL!!!
    If Not TypeOf Obj Is UserForm Then UserFormShowMode = -1: Exit Function Else Obj.Show vbModeless

    If Err.Number = 0 Then UserFormShowMode = vbModeless Else UserFormShowMode = vbModal

    On Error GoTo 0
End Function
voila 😉
 
@patricktoulon,
Comme je te l'ai dit dans une autre sujet à propos de ton code ci-dessus, je ne vois pas trop ce que ça apporte par rapport au mien, plus simple.

Le compteur à 200 est pour moi inutile, vu que de toutes façons un Set Obj = Obj.Parent finira toujours pas se planter quand on arrive au sommet de la hiérarchie des objets, où l'objet au sommet n'a plus de propriété .Parent.

Et si l'objet qu'on cherche (un UserForm) est bien celui qui correspond à l'objet courant, c'est gagné.
 
Le compteur à 200 est pour moi inutile, vu que de toutes façons un Set Obj = Obj.Parent finira toujours pas se planter quand on arrive au sommet de la hiérarchie des objets, où l'objet n'a plus de propriété .Parent.
c'est pour ce la que je l’arrête à "application et j'ai fait une erreur c'est "And" et non "Or"
' la flemme de corriger hier) 😳 😎

je ne vois pas trop ce que ça apporte par rapport au mien, plus simple.
heu si quand même!!!! tu ne travaille qu'avec les enfants directs du userform moi je peux commencer tout en bas et remonte tout en haut 😉
 
Tu as mis le doigt sur quelque chose d'inattendu !
Si Obj est un Frame TypeOf Obj Is UserForm = True !!!

Je trouve cela très étrange et je ne sais pas si cela fait sens mais je dirais que c'est un bug car le TypeOf Frame existe bel et bien.

Le bon code est donc:
VB:
'-------------------------------------
'Mode d'affichage du UserForm
'
'- Obj est soit un Control du UserForm
'          soit un UserForm
'
'- Return: vbModal (1)
'          vbModeless (0)
'          Erreur (-1)
'-------------------------------------
Function UserFormShowMode(ByVal Obj As Object) As Integer
    On Error Resume Next
    
    'Cherche l'objet au sommet de la hiérarchie
    Do While Err.Number = 0
        Set Obj = Obj.Parent
    Loop
    
    If Not TypeOf Obj Is UserForm Then
        UserFormShowMode = -1
    Else
        Err.Clear
        Obj.Show vbModeless
        
        'Return Value
        If Err.Number Then
            UserFormShowMode = vbModal
        Else
            UserFormShowMode = vbModeless
        End If
    End If
    
    On Error GoTo 0
End Function
 

Pièces jointes

Dernière édition:
re
Bonjour @Dudu2
oui je sais avec les frames selon la version d'excel il y a des non cohérences avec les fonctions
je pense que justement comme les frames ont un handle window ,(et oui!!elle sont des window a part entière)
peut être que Ms a modifié pour palier justement a ça et pouvoir utiliser les fonctions pour control sur elles

car les autres controls a part listbox , multipage n'ont pas de handle
tout du moins les api te donnent le même pour tous 🤣

maintenant met un autre object a la place du control dans l'appel
et shbountch!!! ça tourne sans fin c'est pour ca que j’arrête l'a boucle a application
 
Dernière édition:
- Navigue sans publicité
- Accède à Cléa, notre assistante IA experte Excel... et pas que...
- Profite de fonctionnalités exclusives
Ton soutien permet à Excel Downloads de rester 100% gratuit et de continuer à rassembler les passionnés d'Excel.
Je deviens Supporter XLD

Discussions similaires

Réponses
1
Affichages
252
Retour