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
Bonjour,

Quoique tu fasses, l'évènement _Exit() de la TextBox sera déclenché (et traité pas ton Sub) en priorité.
Tu ne peux absolument pas en sortir si Cancel = True.

Il faut prévoir par exemple d'accepter une valeur vide (Cancel = False) pour laisser passer quitte à faire une vérification des zones vides non valides sur un "Valider" ultérieur.

Une technique plus complexe à mettre en œuvre est de ne pas utiliser le Cancel et de déclencher le contrôle sur la TextBox de manière asynchrone (Application.OnTime Now, "FonctionDeContrôleTextBox") et si le contrôle détecte une erreur d'y faire un TextBox.SetFocus (qui est hélas sans effet dans l'_Exit() de la TextBox concernée).

Edit:
Ou alors, encore mieux, limiter le rôle de la fonction asynchrone au TextBox.SetFocus. en cas d'erreur détectée par les instructions de contrôle de validité de l'_Exit().
 
Dernière édition:

RyuAutodidacte

XLDnaute Impliqué
Supporter XLD
Bonjour,

Quoique tu fasses, l'évènement _Exit() de la TextBox sera déclenché (et traité pas ton Sub) en priorité.
Tu ne peux absolument pas en sortir si Cancel = True.

Il faut prévoir par exemple d'accepter une valeur vide (Cancel = False) pour laisser passer quitte à faire une vérification des zones vides non valides sur un "Valider" ultérieur.

Une technique plus complexe à mettre en œuvre est de ne pas utiliser le Cancel et de déclencher le contrôle sur la TextBox de manière asynchrone (Application.OnTime Now, "FonctionDeContrôleTextBox") et si le contrôle détecte une erreur d'y faire un TextBox.SetFocus (qui est hélas sans effet dans l'_Exit() de la TextBox concernée).

Edit:
Ou alors, encore mieux, limiter le rôle de la fonction asynchrone au TextBox.SetFocus. en cas d'erreur détectée par les instructions de contrôle de validité de l'_Exit().
ok Merci Dudu2,

Donc si je comprends bien, je laisse le Cancel à False je créé une fonction pour le focus qui se lance si erreur détecté via Application.OnTime,
c'est bien ça…

je suis pas sur d'avoir tout compris correctement …

Genre ceci :
VB:
'd'un coté on a :
Application.OnTime Now + TimeValue("00:00:02"), "AsyncTextBox"


'Et de l'autre on a :
Function AsyncTextBox(MyTexBox)
    
    If UserForm1.MyTexBox.Value = "" Then MyTexBox.SetFocus

End Function
 

Dranreb

XLDnaute Barbatruc
Bonjour.
Peut être quelque chose à combiner avec BeforeUpdate, qui n'est plus invoqué une seconde fois si la TextBox n'est plus modifiée, ce qui permettrait de positionner à True un global Boolean seulement s'il l'est, l'Exit le remettant à False à la fin. À tester …
 

patricktoulon

XLDnaute Barbatruc
re
bonsoir
si me.hide:me.show fini par surcharger et bloquer excel
n'utilise pas l'instance de classe active du userform mais cell e de l'appel
me.hide:userform1.show
ça arrive de temps en temps avec les new version d'excel
je sais que c'est obscure pour certains mais c'est bien ca
change userform1 pour le nom de ton userform
;)
 

Dudu2

XLDnaute Barbatruc
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 vide dans la TextBox pour laisser passer et permettre au CommandButton de jouer son rôle.

b) - Fermer le UserForm par son menu système (la croix X en haut)

c) - Intercepter une touche (comme ESCAPE) dans la TextBox si cette convention est acceptable dans le contexte application

d) - Intercepter l'évènement CommandButton_MouseDown qui certes intervient après l'évènement _Exit() mais qui lui au moins est déclenché et permet de fermer le UserForm après l'affichage du MsgBox.
 

Pièces jointes

  • Exit sur Control de UserForm.xlsm
    23.6 KB · Affichages: 12
Dernière édition:

patricktoulon

XLDnaute Barbatruc
@Dudu2 je tape "dudu" dans le textbox 1 et valide
j'ai le message et après le message il ne reprends pas le focus
comme je l'ai dis dans la discussion concerné le msgbox enlève le focus au userform il n'est plus la fentre active alors pour rendre le focus a un de ses enfants je pense que tu peut courir encore longtemps
;)
c'est immuable
 

Dudu2

XLDnaute Barbatruc
Animation.gif


Avec le SetFocus Asynchrone comme dans mon fichier,si ,le Focus revient.
VB:
MsgBox "Vous devez entrer une valeur numérique !"
Set SetFocusControl = Me.TextBox1
Application.OnTime Now, "SetFocus"
 

Discussions similaires