Microsoft 365 Userform : Astuce pour pourvoir utiliser le bouton UnLoad Me - quand exit Cancel sur textbox

RyuAutodidacte

XLDnaute Impliqué
Supporter XLD
Bonjour à tous en ce dimanche,

Dans un UserForm (Pas de code ActiveX svp qui ne sont pas géré chez moi) , j'ai 2 TextBox qui utilisent un event Exit.
Pour les TextBox : Tant que les conditions ne sont pas remplis (donnée valide) le Exit est en Cancel True et garde donc le focus

Ce que j'aimerai et malgré ce focus est une astuce qui me permettrait quand même de pouvoir cliquer sur le Bouton qui UnLoad me
Déjà est ce possible ? et si oui comment svp ?
 
Solution
Il y a 2 problèmes:

1 - Le MsgBox à la sortie duquel un _Exit() / Cancel = True ne repositionne pas le curseur dans la TextBox qui a gardé le Focus si le UserForm a été affiché en vbModeless.

2 - Forcer la sortie du UserForm dans un _Exit() / Cancel = True

Le problème #1 se règle avec un Application.OnTime (voir le module dédié Module_SetFocus dans le fichier)

Le problème #2 est beaucoup plus délicat, car même en appuyant sur un CommandButton, l'_Exit() sera exécuté en priorité et un _Exit() / Cancel = True empêchera l'exécution du _CommandButton_Click() !!!

Les solutions:

a) - Accepter une saisie...

Dudu2

XLDnaute Barbatruc
Animation.gif
 

patricktoulon

XLDnaute Barbatruc
re



j'utilise le fichier du post #12
et comme ça
j'ai ajouté la condition modeclose pour ne pas déclencher le message si fermeture forcé par la croix avec un txt vide ou non numérique
VB:
Dim modeclose

Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
    If modeclose = 1 Then Exit Sub
    With TextBox1
        If Not IsNumeric(.Value) Then
            MsgBox " non raté essaie encore"
            réactivewindow TextBox1
            Cancel = True
        End If
    End With
End Sub


Private Sub TextBox2_Exit(ByVal Cancel As MSForms.ReturnBoolean)
If modeclose = 1 Then Exit Sub
    With TextBox2
        If Not IsNumeric(.Value) Then
            MsgBox " non raté essaie encore"
            réactivewindow TextBox2
            Cancel = True
        End If
    End With
End Sub

'pour pouvoir quitter meme avec le textbox vide ou  non numerique sans redeclencher le message
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
modeclose = 1
End Sub

Sub réactivewindow(ctrl As MSForms.TextBox)
    hwnd = ExecuteExcel4Macro("CALL(""user32"",""GetActiveWindow"",""JCC"")")         'handle fenetre active
    ExecuteExcel4Macro ("CALL(""user32"",""ShowWindowA"",""JJJJJ""," & hwnd & "," & 5 & ")")'réactive la fenetre
    ctrl.SetFocus
    ctrl.SelStart = 0: ctrl.SelLength = 100
End Sub
 

patricktoulon

XLDnaute Barbatruc
re
le bouton Quitter fait son effet mais la croix peut fermer sans message pour pouvoir abandonner la saisie
VB:
Dim modeclose

Private Sub CommandButton1_Click() 'bouton Quitter
Unload Me
End Sub

Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
    If modeclose = 1 Then Exit Sub
    With TextBox1
        If Not IsNumeric(.Value) Then
            MsgBox " non raté essaie encore"
            réactivewindow TextBox1
            Cancel = True
        End If
    End With
End Sub


Private Sub TextBox2_Exit(ByVal Cancel As MSForms.ReturnBoolean)
If modeclose = 1 Then Exit Sub
     With TextBox2
        If Not IsNumeric(.Value) Then
            MsgBox " non raté essaie encore"
            réactivewindow TextBox2
            Cancel = True
        End If
    End With
End Sub

'pour pouvoir quitter meme avec le textbox vide ou  non numerique sans redeclencher le message
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = 0 Then modeclose = 1 Else modeclose = 0
End Sub

Sub réactivewindow(ctrl As MSForms.TextBox)
    hwnd = ExecuteExcel4Macro("CALL(""user32"",""GetActiveWindow"",""JCC"")")         'handle fenetre active
    ExecuteExcel4Macro ("CALL(""user32"",""ShowWindowA"",""JJJJJ""," & hwnd & "," & 5 & ")")
    ctrl.SetFocus
    ctrl.SelStart = 0: ctrl.SelLength = 100
End Sub
 

Dudu2

XLDnaute Barbatruc
J'ai mis à jour le Post #12 et son fichier pour indiquer une solution supplémentaire - voir item d) - pour fermer le UserForm.
Certes elle ne permet pas d'éviter l'affichage du message d'erreur, mais au moins le UserForm se ferme après le clic sur le bouton.

A mon avis c'est finalement la plus simple à mettre en œuvre.
 

RyuAutodidacte

XLDnaute Impliqué
Supporter XLD
Re, je vais étudié vos code afin de les comprendre correctement …

@Dudu2 ce que tu m'as proposé est vraiment intéressant, à 1ère vu j'ai pas eu de problème sur ma version d'excel 365 Mac

@patricktoulon ton code aussi, par contre je plante sur la partie réactivewindow … surement du code propre à windows …

J'ai eu aussi des remarques interessantes de tout le monde que je vais prendre en compte afin de savoir
quelle direction que je vais prendre, (peut être un mixte du condensé des réponse …)

En tout cas grand Merci, je reviens vers vous dès que j'aurais fait tous mes tests et pris une décision
Les réponses données de tout le monde m'enlèvent une bonne épines du pied ;)

Pour infos : ce qui faut savoir sur Excel MAC :
Toutes les versions après Excel 2011, ne permettent plus d'ajouter/créer un Userform, on est obligé d'en créer un depuis Excel PC, pour le pouvoir ensuite le coder ensuite sur Mac, mais ce n'est pas tout …
Lorsque l'on sélectionne L'UserForm sur Excel Mac on pas même plus accès au propriétées (bref une vrai aberration de MS, alors qu'ils pouvait reprendre de l'existant sur Excel 2011 et l'améliorer)
Bien sur pour coder un Userform sur Mac, pas d'AtiveX, DLL, ou code propre à windows.
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
Pour info je te donne le fichier limité à la version que je considère comme la plus simple et que j'utiliserais probablement même si elle a le petit inconvénient d'envoyer le message d'erreur (si erreur il y a) avant la fermeture.
 

Pièces jointes

  • Exit sur Control de UserForm Option Simple.xlsm
    24.8 KB · Affichages: 7

RyuAutodidacte

XLDnaute Impliqué
Supporter XLD
re
ah oui pardon j'utilise la user32 de windows donc sur mac ça ne peux pas marcher 🤣
mille excuse Ryu
a tu essayé le me.hide:nomuserform.dhow
Coucou Patrick ;)
concernant le Me.Hide: Userform1.Show j'ai le même soucis avec ma version d'excel Mac malheureusement, au bout d'un moment ca bloque.
là je vais me pencher sur vos code …
 
Dernière édition:

RyuAutodidacte

XLDnaute Impliqué
Supporter XLD
Re à tous,

J'ai pris en compte l'ensemble des remarques (j'ai fait aussi le moins risqué par rapport à Excel Mac étant donné que parfois ça ne réagit pas comme sur PC - quoiqu'il en soit cela devrait marché sur les 2 plateformes) :

@Dranreb L'idée de gestion via une Msgbox est ce qu'il retourne est très bonne, mais malheureusement, j'ai toujours le même problème du curseur qui ne s'affiche plus

@patricktoulon @Dudu2 la gestion du UserForm_QueryClose j'aime bien et je me le mets de coté

@Dudu2 le Unload Me dans le KeyPress je prends, et le principe de Application.OnTime est la méthode la plus stable chez moi

je m'étais lancé sur une méthode sans MsgBox et grâce à vos exemples et conseils précieux, j'ai pu finalisé mon code.;
Pour être sur de la stabilité dans tous les cas, j'ai créé une méthode de Compteur pour les Textbox qui me permet d'afficher la 1ère fois le msg d'alerte puis la 2è fois il donne la main ce qui permet de Cancel (+ la possibilité de quitté direct avec le KeyPress)

Voilà, je vais vous fournir le fichier … si vous avez des remarques ou des axes d'amélioration je suis preneur, merci à tous
 

Pièces jointes

  • USERFORM PC-MAC FINAL.xlsm
    69.1 KB · Affichages: 5

Dranreb

XLDnaute Barbatruc
Bonjour.
Attention les opérateurs de comparaison sont prioritaires sur les opérateurs logiques.
je préfère vous le dire car je vois aussi des = True et = False derrière des expressions Boolean, ce qui est inutile vu que la nouvelle expression Boolean ainsi formée à toujours la même valeur que l'expression seule.
VB:
' If TxtB1 And TxtB2 = True Then CommandButton1.Enabled = True 
If TxtB1 And TxtB2 Then CommandButton1.Enabled = True 
…
' If TxtB1 And TxtB2 = False Then CommandButton1.Enabled = False
If TxtB1 And Not TxtB2 Then CommandButton1.Enabled = False
N'y aurait il pas plus simple parfois de ce genre ? :
VB:
CommandButton1.Enabled = TxtB1 And TxtB2
 

patricktoulon

XLDnaute Barbatruc
on peut simplifier
VB:
Private Sub TextBox1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
    If KeyAscii = 27 Then Unload Me
     If Not Chr(KeyAscii) Like "[0-9,-]" Then KeyAscii = 0
 ' If Not IsNumeric(Chr(KeyAscii)) And Not Chr(KeyAscii) = "-" Then KeyAscii = 0
End Sub
Private Sub TextBox2_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
    If KeyAscii = 27 Then Unload Me
        If Not Chr(KeyAscii) Like "[0-9,-]" Then KeyAscii = 0
   ' If Not IsNumeric(Chr(KeyAscii)) And Not Chr(KeyAscii) = "-" Then KeyAscii = 0
End Sub
 

Discussions similaires

Statistiques des forums

Discussions
312 112
Messages
2 085 409
Membres
102 884
dernier inscrit
Macarena