[VBA]Condition TextBox = Nombre positif

Résolu
micaub Messages postés 36 Statut Membre -  
micaub Messages postés 36 Statut Membre -
Bonjour à tous,

Je suis en train de créer un formulaire en VBA pour Excel. Dans ce dernier se trouve une grande quantité de Textbox dont certaines (une 20aine) ne peuvent accueillir que des nombres positifs (ce sont des longueurs en mm) ou du vide si on ne remplit pas la case.

Pour ce faire, j'ai créer ce code :

Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
If IsNumeric(TextBox1.Text) = False And TextBox1.Text <> "" Then
Cancel = True
MsgBox "La valeur rentrée n'est pas pas un nombre."
ElseIf TextBox1 < 0 Then
Cancel = True
MsgBox "La valeur rentrée n'est pas un nombre positif."
End If
End Sub

Et je le duplique ensuite pour chacune de mes textbox. J'obtiens le résultat escompté, mais je trouve cette programmation lourde : j'ai du recopier 20 fois ce code dans ma macro. Quelqu'un aurait-il une idée pour optimiser ce code ou pour éviter de le recopier 20 fois, si tant est qu'il y ait une solution plus optimale (ce que je pense) ?

D'avance merci pour votre aide.

Cordialement.

MA
Configuration: Windows XP
Internet Explorer 6.0

13 réponses

  1. Bidouilleu_R Messages postés 1209 Statut Membre 296
     
    Bonjour,

    j'ai rencontré lemême problème il y a quelques temps,
    jse fais un scan de tous les controls puis je regarde si le nom est textbox xx
    et je regarde si ce n'est pas vide ( on peut modifier )
    si cela ne correspond pas on quitte la procedure puis on place le focus sur l'intrus...
    bon courage.

    If IK > 1 Then
    For Each MyControl In Controls
    If Left(MyControl.Name, 7) = "TextBox" Then ' on lit un textbox
    If MyControl.Name="" then
    s = Chr(10) & "Manque une valeur" & Chr(10)
    suite = MsgBox(s, vbOKOnly)
    Userform1.Mycontrols.SetFocus
    Exit Sub
    End If

    End If
    Next
    End If
    3
  2. Bidouilleu_R Messages postés 1209 Statut Membre 296
     
    Le problème vient du fait que tu utilise un variant pour mycontrol2
    donc il ne possède pas la propriété .caption
    mycontrol2 est une variable qui contient "Lab...."
    mycontrol est un objet de la classe controls.
    je corrige comme suit....

    For Each mycontrol In Controls
    mycontrol2 = "Lab" & Mid(mycontrol.Name, 4, 100)
    If Left(mycontrol.Name, 3) = "Txt" Then ' on lit un textbox
    If IsNumeric(mycontrol.Text) = False And mycontrol.Text <> "" Then
    s = MsgBox("Vous n'avez pas rempli la case " & mycontrol2 & " avec une valeur numérique !", vbCritical, "Erreur")
    Exit Sub
    mycontrol.Name.SetFocus
    ElseIf mycontrol < 0 Then
    s = MsgBox("La valeur " & mycontrol2 & " ne peut pas être négative !", vbCritical, "Erreur")
    mycontrol.SetFocus
    Exit Sub
    Exit For
    End If
    End If
    Next

    et je te propose ce code ... retour sur le controle qui est en défaut.

    For Each mycontrol In Controls
    mycontrol2 = "Lab" & Mid(mycontrol.Name, 4, 100)
    If Left(mycontrol.Name, 3) = "Txt" Then ' on lit un textbox
    If IsNumeric(mycontrol.Text) = False And mycontrol.Text <> "" Then
    s = MsgBox("Vous n'avez pas rempli la case " & mycontrol2 & " avec une valeur numérique !", vbCritical, "Erreur")
    mycontrol.SetFocus
    Exit for


    ElseIf mycontrol < 0 Then
    s = MsgBox("La valeur " & mycontrol2 & " ne peut pas être négative !", vbCritical, "Erreur")
    mycontrol.SetFocus
    mycontrol.SetFocus
    Exit for

    End If
    End If
    Next

    A+
    1
  3. Bidouilleu_R Messages postés 1209 Statut Membre 296
     
    Je comprends le soucis...

    le problème c'est que l'utilisation de la boucle for each entraine un examen des objets
    dans l'ordre de création. et je ne pense pas qu'ilsoient tous créés ....label1, textbox1,label2,textbox2
    Ce qui limite les possibilités.

    il est possible d'utiliser mycontrol2 en tant qu'objet en écrivant

    Dim mycontrol2 As Control
    mais il n'aura jamais la propriété "caption" mais "value"

    dim mycontrol2 as object
    '...
    '....

    i=0
    For Each mycontrol In Controls

    set mycontrol2=controls.item(i)

    '...
    '...
    i=i+1 ' incrémente le controle
    next

    j'aimerai te soumettre une suggestion.
    lorsque la boucle for each lit un controle textbox : pourquoi lire le contenu d'un autre controle (le label)?
    Ne serait-il pas judicieux de faire référence à controltiptex
    ainsi il serait possible d'utiliser mycontrol.controltiptext
    et dans controltiptext tu écris ce que tu veux.

    sinon sans faire "d'usine à gaz" je ne vois pas
    1
  4. Utilisateur anonyme
     
    VBA ne gère pas la programmation objet et donc il n'y a pas d'autre solution que de faire de la programmation procédurale. Donc il n'est pas possible de faire autrement.
    0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. Bidouilleu_R Messages postés 1209 Statut Membre 296
     
    la réponse post 2 m'a laissé perplexe, je viens de vérifié

    on peut aussi écrire

    toujours dans le bouton de validation

    Private Sub Valider_Click()

    ' pour ecrire le contenu des textbox paramètre

    For Each mycontrol In Controls
    If Left(mycontrol.Name, 7) = "TextBox" Then ' on lit un textbox
    If mycontrol.Value = "" Then
    s = MsgBox(" vide ici dans " & mycontrol.name, vbCritical, "Erreur")
    Exit For
    End If

    End If
    Next

    End Sub
    0
  7. micaub Messages postés 36 Statut Membre
     
    Merci à vous deux pour vos réponses.

    Je craignais que la programmation objet ne soit pas gérée par VBA, c'est le cas. Tant pis...

    @Bidouilleu_R
    Merci pour l'astuce. Je l'ai experimenté, l'adaptant à mes besoins... Ca a l'air de fonctionner, même si ça ne marche que lors de la validation du formulaire et non pas lors de la saisie des TextBox ; je vais donc combiner les 2. De plus, il va falloir que je modifie un peu le nom de mes textBox afin de différencier celles qui doivent répondre à la condition (les TextBox de longueur) et les autres qui n'ont pas à avoir de telles conditions.

    Encore merci pour votre aide à vous 2 et à bientôt.

    MA
    0
  8. Bidouilleu_R Messages postés 1209 Statut Membre 296
     
    une deuxième astuce

    pour pour gagner du temps il est possible d'ajouter....
    ce qui permet d'aller immédiatement sur le control en défaut

    For Each mycontrol In Controls
    If Left(mycontrol.Name, 7) = "TextBox" Then ' on lit un textbox
    If mycontrol.Value = "" Then
    s = MsgBox(" vide ici dans " & mycontrol.name, vbCritical, "Erreur")
    mycontrol.setfocus
    Exit For
    End If

    End If
    Next
    0
  9. micaub Messages postés 36 Statut Membre
     
    Merci Bidouilleu_R, le programme fonctionne bien avec ce que j'ai fait.

    Seule petite optimisation que j'ai tenté d'effectuer, c'est de remplacer le nom de la textbox (un peu rébarbatif) par le caption du Label qui lui est associé. J'ai tenté une petite astuce mais je ne comprends pourquoi ça ne fonctionne pas :

    For Each mycontrol In Controls
    mycontrol2 = "Lab" & Mid(mycontrol.Name, 4, 100)
    If Left(mycontrol.Name, 3) = "Txt" Then ' on lit un textbox
    If IsNumeric(mycontrol.Text) = False And mycontrol.Text <> "" Then
    s = MsgBox("Vous n'avez pas rempli la case " & mycontrol2.Caption & " avec une valeur numérique !", vbCritical, "Erreur")
    Exit Sub
    mycontrol.Name.SetFocus
    ElseIf mycontrol < 0 Then
    s = MsgBox("La valeur " & mycontrol2.Caption & " ne peut pas être négative !", vbCritical, "Erreur")
    mycontrol.SetFocus
    Exit Sub
    Exit For
    End If
    End If
    Next

    L'erreur semble venir de mycontrol2.Caption alors que mycontrol2 semble bien renvoyer ce que je désire....

    Je tiens à préciser que toutes mes TextBox commencent par Txt et que tous mes Labels commencent par Lab...
    Pour chaque TextBox Txt[nom], un Label Lab[nom] lui est associé avec [nom] identique, cela va de soi...

    Si quelqu'un a une petite idée ^^

    Bonne journée à tous !

    MA
    0
  10. micaub Messages postés 36 Statut Membre
     
    Merci pour ton explication Bidouilleu_R, je comprend mieux pourquoi il refusait de faire mon .Caption.
    Merci également pour tes corrections : il n'y a plus aucun bug dans ce code et tout fonctionne de manière impecable !
    Promis, c'est la dernière question et après, j'arrête de vous embêter :
    N'y a-t-il pas moyen de transformer un Variant en Objet afin que je puisse au final utiliser mon .Caption ?

    Exemple :
    Le nom de ma Textbox est "TxtRisque".
    Le nom du Label qui lui est associé est "LabRisque".
    Le Caption du Label, donc LabRisque.Caption, est "Risque identifié".
    Avec la méthode élaborée gràçe à toi, si je remplis mal, la MsgBox écrit : "La valeur LabRisque ne peut pas être négative !"
    Ne pourrait-on avoir "La valeur Risque identifié ne peut pas être négative !" ?

    Bah, si ce n'est pas possible, c'est pas grave : le code tel que tu m'as permis de l'avoir est déjà très bien XD.

    Encore une fois, merci à tous pour l'aide que vous accordez aux plus nuls (ne soyons pas si méchants, on dira plutôt aux moins bons) en prenant sur votre temps : une fois plus calé en VBA, j'espère bien pouvoir moi aussi participer activement.

    A bientôt.

    MA
    0
  11. Bidouilleu_R Messages postés 1209 Statut Membre 296
     
    j'ai une idée mais il faut que je teste....
    Pour information je ne considère pas que les autres sont nuls en ceci ou cela
    Je dirai plutôt qu'ils prennent le chemin pour apprendre ou découvrir ce que d'autres ont vu avant...
    je regarde et je te tiens au courant.
    0
  12. micaub Messages postés 36 Statut Membre
     
    Mais c'est bien sûr !!!
    Je n'avais pas du tout pensé à ta suggestion, pourtant simple, alors que j'avais utilisé l'équivalent avec des OptionButton dont je ne voulais pas retranscrire le .Caption tel quel dans mon tableur.

    Merci encore une fois de plus Bidouilleu_R : ta dernière astuce me permet vraiment de faire tout ce que je voulais faire. Associer à l'autre bout de programme, j'ai vraiment qqch qui correspond en tous points à mes attentes.

    Et pour couronner le tout, j'aurais appris qq trucs dans ce topic grace à tes explications.

    Encore merci et bravo pour ces interventions.

    A bientôt p-ê sur un autre topic !

    MA
    0
  13. Bidouilleu_R Messages postés 1209 Statut Membre 296
     
    Ben! je suis content pour toi!

    tu peux mettre résolu si ... tu pense que c'est résolu

    Bonne journée.

    R
    0
  14. micaub Messages postés 36 Statut Membre
     
    Ne t'inquiète pas, c'est fait depuis hier : ta dernière astuce n'était que du bonus alors j'avais déjà résolu le Topic ;)

    Encore merci et bonne soirée.

    MA
    0