Microsoft 365 EXCEL - VBA - Problème sur la sélection d'une textbox

Yann Sama

XLDnaute Nouveau
Bonjour,

Je suis en difficultés sur un formulaire.
Je dois renseigner une date dans un textbox mais je souhaiterais y mettre un message d'erreur si ce qui est saisi n'est pas une date.
Jusque là tout va bien, mais je souhaiterais rajouter un détail, à savoir que le texte soit sélectionné automatiquement après la validation du message.

DateEve c'est le nom de ma textbox.
Je me suis déjà renseigné sur les forums et il semblerait que le bon code soit :
DateEve.SetFocus
DateEve.SelStart = 0
DateEve.SelLength = Len(DateEve.Text)

Mais ça ne veut pas marcher.
Pire encore, ça fonctionne si j'écris du texte dans la seconde textbox qui est totalement absente de mon code.

Alors est-ce que mon code n'est pas bon ou incomplet?
Est-ce que j'utilise la bonne procédure événementielle, à savoir que j'ai déjà utilisé after update, exit et change avec le même code?
Quand je le mets dans "Change", ça fonctionne mais ça le fait à chaque caractère que je tape.

Merci à vous

VB:
Private Sub DateEve_AfterUpdate()

If IsDate(DateEve) Or DateEve = "" Then
    Exit Sub
Else
    MsgBox "Tu sais pas écrire une date ou quoi?"
    DateEve.SetFocus
    DateEve.SelStart = 0
    DateEve.SelLength = Len(DateEve.Text)

End If

End Sub
 

Fichiers joints

fanch55

XLDnaute Impliqué
Bonjour, à tester :
VB:
Public Terminate As Boolean
 
Private Sub DateEve_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)

    With DateEve
        If Not (IsDate(.Value) Or .Value = "" Or Terminate) Then
            MsgBox "Tu sais pas écrire une date ou quoi?"
            .SelStart = 0
            .SelLength = Len(DateEve)
            Cancel = True
        End If
    End With

End Sub

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    Terminate = True
End Sub
 

Yann Sama

XLDnaute Nouveau
Bonjour, à tester :
VB:
Public Terminate As Boolean

Private Sub DateEve_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)

    With DateEve
        If Not (IsDate(.Value) Or .Value = "" Or Terminate) Then
            MsgBox "Tu sais pas écrire une date ou quoi?"
            .SelStart = 0
            .SelLength = Len(DateEve)
            Cancel = True
        End If
    End With

End Sub

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    Terminate = True
End Sub
Euh, et bien ça fonctionne... Alors je vais commencer par te dire merci :)
Mais je ne comprends pas, c'est quoi "Terminate"? et l'évènement "Query close"?
 

fanch55

XLDnaute Impliqué
QueryClose, événement
Cet événement se produit avant la fermeture d’un objet UserForm .

Terminate :
c'est une variable commune que j'ai déclarée et que je met à vrai à la fermeture de l'Userform et que je teste dans l'évent BeforeUpdate, sinon vous allez avoir le message systématiquement à la fermeture de l'userform .
 

Yann Sama

XLDnaute Nouveau
QueryClose, événement
Cet événement se produit avant la fermeture d’un objet UserForm .

Terminate :
c'est une variable commune que j'ai déclarée et que je met à vrai à la fermeture de l'Userform et que je teste dans l'évent BeforeUpdate, sinon vous allez avoir le message systématiquement à la fermeture de l'userform .

Ah oui effectivement, je l'ai trouvé aussi.
Mais je ne comprends toujours pas le Terminate.

Puisque oui c'est une variable, oui je vois que vous la mettez à vrai en fermeture de formulaire et que VBA la considère fausse par défaut mais dans le BeforeUpdate, vous ne faîtes que nommer la variable, je ne vois pas de test.
 

fanch55

XLDnaute Impliqué
Pour un booleen, il suffit de le citer pour savoir si c'est vrai ou faux :

Si vrai alors ...
Si faux alors ...
Si non vrai alors ...
Si non faux alors ...
Si Terminate alors ....

Etc ...

C'est comme lorsque vous faites If IsDate(DateEve) then...
Isdate vous renvoie vrai ou faux .

Terminate aussi .
 

patricktoulon

XLDnaute Barbatruc
bonjour a tous les
combien de fois je devrait le dire;)
le test isdate est "BIDON!!" si le len n'est pas égal à 10
c'est un défaut de isdate qui est connu pourtant ;)
testez ça pour comprendre
et regardez comment vba interprète
msgbox isdate("1/1")
msgbox isdate("02/05")
msgbox isdate("2020/02")
MsgBox Year("23/02")
MsgBox Month("20/02")
MsgBox Month("02/23")
toute ces chaines ci dessus passe dans ton textbox pour des dates

j'avoue moi aussi ne pas comprendre terminate dans ce contexte précis
fanch55 si tu veux donner des explications sur ce point
car en l’état tel que dans ton code ,pour moi cette variable sert a rien en tout cas pas a dateEve

elle est en public ok elle pourrait donc servir a autre chose dans le classeur
sauf que quand le unload est effectif(userform fermé) ta variable est vidée (redevient false)
conclusion à quoi sert elle???
 

fanch55

XLDnaute Impliqué
Salut Patrick,
L'événement _BeforeUpdate est déclenché après le Query_Close ( à ma grande surprise par ailleurs) .
La variable Terminate a été déclarée en Public (vite fait), mais un simple dim en début d'userform aurait pu suffire .
Obligé pour ne pas avoir le message trente six fois pour rien .
 

fanch55

XLDnaute Impliqué
Pour le isdate, c'est ben vrai, il vaut mieux utiliser le gestionnaire d'erreur sur un Cdate :
VB:
Dim Terminate As Boolean
 
Private Sub DateEve_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)

    With DateEve
        Select Case True
            Case .Value = vbNullString
            Case Terminate
            Case Is_Date(.Value): .Value = CDate(.Value)
            Case Else
                MsgBox "Tu sais pas écrire une date ou quoi?"
                .SelStart = 0
                .SelLength = Len(DateEve)
                Cancel = True
        End Select
    End With

End Sub

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    Terminate = True
End Sub

Function Is_Date(ByVal Tbox) As Boolean
    On Error Resume Next
    Tbox = CDate(Tbox)
    Is_Date = Err = 0
End Function
 

patricktoulon

XLDnaute Barbatruc
re
L'événement _BeforeUpdate est déclenché après le Query_Close ( à ma grande surprise par ailleurs)
finalement c'est pas surprenant du tout
si l'userform est fermé après avoir modifier le textbox, son beforeupdate est bien obligé de s’exécuter

donc si je comprends bien ton procc ta variable est pour pouvoir fermer brutalement l'USF sans déclencher le message
 

Yann Sama

XLDnaute Nouveau
Merci pour ces explications.
C'est presque clair. En fait je pense avoir compris mais pourtant j'ai un bug sur le même type de code pour une autre textbox.

VB:
Private Sub TextBox5_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)

If Not (IsNumeric(TextBox5) Or TextBox5 = "" Or Terminate) Then
    If Label12 = "punaise" Then
        MsgBox "Des chiffres...!!! Avec des 1, des 2, des 3,..."
    Else
        MsgBox "Merci de saisir une donnée numérique"
        Label12 = "punaise"
    End If
    TextBox5.SelStart = 0
    TextBox5.SelLength = Len(TextBox5)
    Cancel = True

End If

End Sub
Quand j'exécute le code, les msgbox s'affichent bien comme je le souhaite sauf que lorsque le label12 devient "punaise", je garde une donnée texte dans ma textbox et lorsque je valide une première fois, le code tourne deux fois, et à la deuxième validation du même texte, il ne tourne qu'une seule fois, à la validation suivante, il tourne deux fois et ainsi de suite...

Comment ça se fait?
 

patricktoulon

XLDnaute Barbatruc
Bonjour
c'est pas très cohérent ton truc là
tu veux faire quoi avec ce textbox finalement
ca devient du grand n’importe quoi
que vient faire ce label dans l'histoire?
regarde ton shema

si c'est pas numeric alors
si label= punaise alors
msgbox tapez des chiffre svp
sinon
merci de taper de chiffres svp
label= punaise


dis moi a quel moment tu enlève punaise pour la fois prochaine
je vois pas vraiment l’intérêt du label pour juste monter le ton du msgbox

bref je ferais comme ca
VB:
option explicit
Dim xx&
Dim terminate
Private Sub TextBox5_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
    With TextBox5
        If Not (IsNumeric(.Value) Or .Value = "" Or terminate) Then
            xx = xx + 1
            If xx = 1 Then MsgBox "Merci de saisir une donnée numérique"
            If xx = 2 Then MsgBox "tu es sourd gros balo!!!!Des chiffres...!!! Avec des 1, des 2, des 3,...tete d'ampoule figure de poulpe !!!!!!!"
            If xx = 2 Then xx = 0
            TextBox5.SelStart = 0
            TextBox5.SelLength = Len(TextBox5)
            Cancel = True
        Else
            xx = 0
        End If
    End With
End Sub


Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
TextBox5 = ""
terminate = True
End Sub
et dans ton queryclose il faut vider ton textbox sinon tu a les deux message ma fois c'est normal
 

Yann Sama

XLDnaute Nouveau
J'essaierai ce soir mais on utilise la même logique. Sauf que toi c'est plus pro lol... (quoique le "tête dampoule" me fait poser des questions mdr)

En gros, sur mon formulaire, si la saisie dans la textbox n'est pas numérique, il m'affiche des messages d'erreurs. Et comme tu l'as bien compris, je voulais faire un message différent s'il refait la meme erreur... donc le label, à la fermeture du formulaire, il se régénère tout seul.

Dans ton code, est ce que la variable xx ne va pas toujours etre égale à 1. Puisque une fois que le before_update est fait, la variable se vide, non?
 

Yann Sama

XLDnaute Nouveau
Bonjour,

Alors c'est essayé et j'ai le même problème. A savoir que j’enchaîne les entrées texte sur la textbox5 et voici ce que j'obtiens. Chaque numéro c'est quand je sors de la textbox5

1. Le message normal apparait
2. Le message rigolo apparait et après validation de celui-ci, le message normal apparaît
3. Le message rigolo apparait uniquement
4. Le message normal apparaît et après validation de celui-ci, le message rigolo apparaît
5. Le message normal apparaît
6. Le message rigolo apparait et après validation de celui-ci, le message normal apparaît
Et voilà après on retourne sur le 3. et ainsi de suite.

je m'arrache les cheveux, je comprends pas pourquoi il me sort plusieurs fois les msgbox.
 

patricktoulon

XLDnaute Barbatruc
re
VB:
option explicit
Dim xx&
Dim terminate
Private Sub TextBox5_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
   if  terminate=false then
   With TextBox5
        If Not (IsNumeric(.Value) Or .Value = "" ) Then
            xx = xx + 1
            If xx = 1 Then MsgBox "Merci de saisir une donnée numérique"
            If xx = 2 Then MsgBox "tu es sourd gros balo!!!!Des chiffres...!!! Avec des 1, des 2, des 3,...tete d'ampoule figure de poulpe !!!!!!!"
            If xx = 2 Then xx = 0
            TextBox5.SelStart = 0
            TextBox5.SelLength = Len(TextBox5)
            Cancel = True
        Else
            xx = 0
        End If
    End With
end if
End Sub


Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
terminate = True
TextBox5 = ""
End Sub
 

Yann Sama

XLDnaute Nouveau
Non navré. Ca ne fonctionne toujours pas.
Après deux tentatives, le formulaire est "figé"

Ah ça y est, enfin... J'ai essayé de comprendre un peu ton code.
En fait, le fait de mettre :
VB:
Cancel = True
L'évènement "Before Update" tourne en boucle.
Donc le check sur le contenu de la cellule se fait de nouveau.
En incrémentant une variable, on peut savoir donc combien de fois on boucle l'évènement.

C'est bien ça?

Donc j'ai fini par remplacer If xx = 2 Then xx = 0 par If xx > 2 Then xx = 1.
Comme ça on finit par retomber sur le deuxième message.

Alors je vais pas chipoter mais bizarrement après 3 messages rigolos (correspondant à 3 tentatives de mettre du texte), rien ne se passe les deux fois suivantes où je valide du texte, puis j'ai le droit à nouveau à 3 messages rigolos, puis rien les deux tours suivants, puis 3 messages rigolos et ainsi de suite.

En tout cas merci pour votre aide et vos explications passées et à venir ;)
 

Créez un compte ou connectez vous pour répondre

Vous devez être membre afin de pouvoir répondre ici

Créer un compte

Créez un compte Excel Downloads. C'est simple!

Connexion

Vous avez déjà un compte? Connectez vous ici.

Haut Bas