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 ?
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 = Trueempêchera l'exécution du _CommandButton_Click() !!!
re
le tiret(ou moins) tu ne peux le mettre que devant
VB:
'*****************************************************
' KEYPRESS Forcer ˆ utiliser que les chiffres et tiret + UnLoad
'*****************************************************
Private Sub TextBox1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
With TextBox1
If KeyAscii = 27 Then Unload Me
If Not Chr(KeyAscii) Like "[0-9-]" Then KeyAscii = 0
If Chr(KeyAscii) = "-" And Len(.Value) > 0 Then KeyAscii = 0
End With
End Sub
Private Sub TextBox2_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
With TextBox2
If KeyAscii = 27 Then Unload Me
If Not Chr(KeyAscii) Like "[0-9-]" Then KeyAscii = 0
If Chr(KeyAscii) = "-" And Len(.Value) > 0 Then KeyAscii = 0
End With
End Sub
Oui c'est exactement ca PS : le => If KeyAscii = 27 Then Unload Me je l'ai mis au pour donner la priorité au Unload
Edit : oui pour le 1er TextBox le tiret est que devant, tandis que pour le 2ème TextBox le tiret se trouve entre 2 chiffres dont le chiffre1 <= chiffre2
Donc pour PrivateSub TextBox2_KeyPress ton code ne rempli pas les conditions
Ci-dessous je t'écris/montre mes conditions concernant ma TextBox2
VB:
TB_TextBox2 = Split(TextBox2,"-")
TextBox2 Like "*#-#*" and IsNumeric(TB_TextBox2(0)) and IsNumeric(TB_TextBox2(1)) and TB_TextBox2(0) <= TB_TextBox2(1)
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 ? :
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.
Re Patrick, pas sur d'avoir compris t a phrase mais j'ai modifié mon poste #33 (si c'est de ça dont tu parlais …)
Oui en effet, il y a des choses plus compliqué parfois pour avoir les mêmes choses que sur PC
PS : je suis qd même assez content de l'astuce du compteur qui me donne l'effet escompté (pour moi)
du coup aujourd'hui j'ai fait qq modifs et je l'ai testé sur un PC que l'on m'a prété et tout à l'air OK
Si c'est ok (sans les dernières modif.) de ton/votre (cher membres du forum), c'est Top
Je reviens vers vous pour un petit update (sachant que sur Mac difficile d'appréhender les UserForms étant donné que l'on ne peut pas les créer sur Mac Grrrrr MS) - astuce supp en plus de la solution de Dudu2
Donc j'ai revu … revu … et revu mon code (bon entrainement sur les Userforms) et je me suis aperçu que j'avais besoin en plus des Actions Tab | Tab + Shift | Return pour passer de TextBox en TextBox
J'en ai profité pour remettre les MsgBox sachant que je devais m'occuper de la perte du curseur dans la TextBox active ; j'ai réussi à biaiser avec le SetFocus en faisant un aller-retour vers : autre Control=>TextBox (pour que ça marche correctement sur Mac (testé) et PC (pas testé - pas de pc sous la main)
J'ai aussi revu le code afin qu'il soit plus simple …
SVP Votre Avis m'intéresse … pour/contre …multiplateforme PC/MAC … ça donne quoi sur PC ? … etc …
Merci d'avance
Bonjour à tous
oui ben çaen fait un bins pour pouvoir fermer un usf avec un exit cancel=true sur un textbox
perso je préfère voir les chose plus simplement
le probleme c'est quoi :
ben tout simplement que le bouton ne peut pas prendre le focus puisqu'il est automatiquement redonné au textbox qui n'a pas recu la donnée et qui est donc en cancel =true
ben la méthode la plus simple et la plus évidente c'est de supprimer le focus au click du bouton
conclusion tu met la property du bouton "takefocusonclick " a false dans le bouton
et tu peux d'es l'ors faire ce que tu veux et décider comment le userform doit reagir dans le bouton
tout simplement
avant de dire j'ai testé
un userform , 2 textbox et un bouton
voila avec ça je peux quand même fermer le userform même si l'un ou l'autre ou les deux textbox sont vides en mettant cette propriété a false le click est exécuté quand même
avec cette methode la réaction des textbox avec cancel est bien effective entre textbox mais exclu le bouton de l'équation
terminé
VB:
Private Sub CommandButton1_Click()
Unload Me
End Sub
Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
If TextBox1 = "" Then Cancel = True
End Sub
Private Sub TextBox2_Exit(ByVal Cancel As MSForms.ReturnBoolean)
If TextBox2 = "" Then Cancel = True
End Sub
demo avec message
VB:
Dim objActif As Object
Private Sub CommandButton1_Click()
If objActif = "" Then MsgBox " le " & objActif.Name & " est vide " & "ben je ferme quand meme au revoir"
Unload Me
End Sub
Private Sub TextBox1_Enter()
Set objActif = TextBox1
End Sub
Private Sub TextBox2_Enter()
Set objActif = TextBox2
End Sub
Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
If TextBox1 = "" Then Cancel = True
End Sub
Private Sub TextBox2_Exit(ByVal Cancel As MSForms.ReturnBoolean)
If TextBox2 = "" Then Cancel = True
End Sub
mapomme : l'approche est différente et est très clair avec un code vraiment très propre,
ça me montre une bonne vision de comment on peut procéder dans le codage d'un Userform.
Alors dans cette situation, comme le bouton Proceed gère les message d'erreur puis redonne le focus au TextBox, cela ne pose donc pas de problème sur la perte du curseur dans les TextBox.
Merci pour cette exemple très concis ( bien les trad. en anglais c'est très clair )
Patricktoulon : J'adore l'astuce, je me la garde sous le coude
PS : je souhaite quand même forcer l'utilisateur à faire une bonne saisie dès le départ, … histoire qu'il prenne les bonnes habitudes dès le début - en tout cas c'est bien cool
Je reviens sur cette question car je suis confronté aux problèmes liés à l'évènement _Exit() d'un Control pour mes développements applicatifs et après avoir fouillé la question je peux dire ce qui suit.
Avec l'évènement <Control>_Exit() qui est fort utile pour effectuer des contrôles sur la valeur saisie en TextBox et ComboBox, il n'y a pas moins de 2 problèmes spécifiques et 1 problème général:
Tant qu'on est dans la fonction <Control>_Exit() (Cancel = True) aucun autre évènement (Bouton cliqué...) ne peut se déclencher sauf les évènements liés au <Control> lui-même.
Donc pas moyen de faire autre chose que de sortir du <Control>_Exit() par un Cancel = False ou fermer le UserForm par la croix du menu système.
Un <Control>.SetFocus dans une fonction <Control>_Exit() donne des résultats aberrants qui dépendent de la distance en TabIndex du Control en <Control>_Exit(). - 2nd appel récursif de la fonction <Control>_Exit() sur le SetFocus d'un Control au-delà du Control en TabIndex + 1.
- Impossibilité de SetFocus sur un Control au-delà du Control en TabIndex + 2.
C'est le cas par exemple où, selon la valeur saisie, on veut se positionner sur tel ou tel autre Control du UserForm.
De plus, de manière générale, si on utilise un MsgBox (ou un autre UserForm de message) dans une fonction d'évènement d'une TextBox ou ComboBox de UserForm affiché en vbModeless, le curseur ne s'affiche pas au retour du MsgBox, même si l'ActiveControl est correct.
Je vais adresser ces problèmes dans 2 Ressources:
-> MsgBox en UserForm vbModless (en attente de publication)
-> Problèmes liès à l'évènement Exit d'un Control
En effet, pour "réactiver" le Control j'utilisais la séquence:
VB:
With Control
.Visible = False
.Visible = True
End With
Mais que ce soit avec la propriété .Visible ou la propriété .Enabled, cela provoque inévitablement le déclenchement de l'évènement Control_Exit(), un effet induit parfaitement indésirable.
Donc je suis passé à une méthode indolore qui consiste à simuler l'action de l'utilisateur avec un clic souris.
Il est donc maintenant parfaitement possible d'écrire sans effets secondaires:
VB:
Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
'UserForm is closed = condition to move out of TextBox1
If Not Me.Visible Then Exit Sub
'TextBox1 is empty = condition to move out of TextBox1
If Len(Trim(Me.TextBox1.Value)) = 0 Then Exit Sub
'Not numeric value = condition to stay in TextBox1
If Not IsNumeric(Me.TextBox1.Value) Then
MsgBoxInModelessUserForm "You need to input a numeric value !"
Cancel = True
End If
End Sub
Reste encore à publier une petite Ressource pour le bon usage du Contol_Exit() et du SetFocus asynchrone qui va avec. Car il est dommage d''avoir ces limitations dues à des problèmes purement Excel sur une fonction évènementielle aussi utile que le Contol_Exit() et qui est à mon avis sous-utilisée.
Souvent c'est l'évènement Control_Change() qui est utilisé mais il ne donne que des valeurs intermédiaires et pas la valeur finale. Donc c'est assez difficile d'en tirer quelque chose sauf pour des cas particuliers.