Insérer Private Sub dans une boucle

Bonjour à tous,

Je travaille sur un UF assez conséquent, avec déjà 500 TextBox, et j'utilise un Private Sub afin de les protéger en écriture, de deux sortes.

Pour les cellules à remplir, j'écris :

Private Sub TextBox1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
If InStr("1234567890,.", Chr(KeyAscii)) = 0 _
Or InStr(TextBox113.Value, ",") <> 0 And Chr(KeyAscii) = "," _
Or InStr(TextBox113.Value, ".") <> 0 And Chr(KeyAscii) = "." _
Or InStr(TextBox113.Value, ",") <> 0 And Chr(KeyAscii) = "." _
Or InStr(TextBox113.Value, ".") <> 0 And Chr(KeyAscii) = "," _
Then
    KeyAscii = 0: Beep
End If
End Sub

Et pour les cellules résultat (complètement bloquées), j'utilise :

Private Sub TextBox2_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)

If InStr("", Chr(KeyAscii)) = 0 Then
    KeyAscii = 0: Beep
End If
End Sub

Seulement, avec autant de cellules, cela me prend bien le quart du code juste pour contrôler la saisie. J'aimerais savoir s'il existe un moyen d'"alléger" le code en faisant varier les Private Sub dans des boucles, pour des séries de cellules (si c'est faisable .. ), ou simplement une autre méthode qui serait moins "lourde".

Je vous remercie d'avance, bonne journée à tous !

Bonjour,

Avec 500 TextBoxes dans ta UserForm ... tu dois impérativement utiliser des modules de classe ...

https://forum.excel-pratique.com/cours-astuces/utilisation-des-modules-de-classe-t4513.html

Bonjour James,

J'ai commencé à lire et comprendre des choses sur le module de classe, mais alors pour m'en servir dans mon cas, c'est autre chose ^^

Je peux changer le Private Sub en Public Sub dans ma classe, mais pour les TextBox_KeyPress(...), comment pourrais-je faire ?

Je ne demande qu'à comprendre et savoir utiliser les classes, ça me permettra de nettoyer et mettre de l'ordre dans mon code !

Re,

Dans le lien fourni ... tu pourras trouver plusieurs exemples concrets ...

Salut,

J'ai pu utiliser un des exemples et l'appliquer à mon cas, et cela fonctionne bien.

Code pour ceux que ça intéresse :

module de classe

Option Explicit

Public WithEvents TextBoxType1 As MSForms.TextBox

Private Sub TextBoxType1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
If InStr("1234567890,.", Chr(KeyAscii)) = 0 _
Or InStr(TextBoxType1.Value, ",") <> 0 And Chr(KeyAscii) = "," _
Or InStr(TextBoxType1.Value, ".") <> 0 And Chr(KeyAscii) = "." _
Or InStr(TextBoxType1.Value, ",") <> 0 And Chr(KeyAscii) = "." _
Or InStr(TextBoxType1.Value, ".") <> 0 And Chr(KeyAscii) = "," _
Then
    KeyAscii = 0: Beep
End If
End Sub

UF

Private Sub UserForm_Initialize()
Option Explicit
Dim TextBoxUsfGen() As New LesTextBoxs

Dim NbTextbox As Integer
Dim Ctrl As Control

NbTextbox = 0

For Each Ctrl In Me.Controls

    If TypeName(Ctrl) = "TextBox" Then
        NbTextbox = NbTextbox + 1

        ReDim Preserve TextBoxUsfGen(1 To NbTextbox)
        Set TextBoxUsfGen(NbTextbox).TextBoxType1 = Ctrl
    End If
Next Ctrl
End Sub

Le problème c'est que je ne veux pas l'appliquer à toutes les TextBox mais certaines .. j'ai donc essayé en écrivant dans l'uf

Private Sub UserForm_Initialize()
Option Explicit
Dim TextBoxUsfGen() As New LesTextBoxs
Dim Ctrl As Control
Dim i As Integer
i = 0
For Each Ctrl In Me.Controls
    For i = 190 To 200 'Par exemple ..
        If TypeName(Ctrl) = "TextBox" Then
        TextBoxUsfGen(i).TextBoxType1 = Ctrl
        End If
    Next i
    Exit For
Next Ctrl
End Sub

Cela ne présente pas de bug mais ça ne fonctionne pas. Aurais-tu une idée sur mon erreur ?

Merci d'avance, bonne journée

Bonjour,

Je te conseille de sortir Option Explicit de ton module d'initialisation ...

Au sujet de ta logique, il apparait tout à fait correcte ...

Par contre, il te faut "auditer" ta UserForm avec précaution ... sur la séquence de 1 à 500 ...

et encore plus préciséement ... sur le sous-ensemble que tu veux traiter ...

Re,

Le public Sub était en dehors de l'initialize, simple copié collé trop rapide ..

Mais je ne comprends pas bien quand tu dis "auditer" .. je dois d'abord définir l'ensemble des TextBox avant d'en choisir une partie ?

Bonjour Paul-Philippe3, james007

Question sur les textbox résultat :

  • pourquoi mettre des textbox et non des labels ? il n'y aurait plus besoin de protéger contre l'écriture.
  • si besoin de textbox, nommer celles servant pour le résultat différemment et utiliser la propriété locked=true ou enabled=false
par exemple :

textbox de saisie : textbox001, ...002 etc...

textbox résultat : TbxResult001, ...002 etc...

Bonjour Fred,

J'ai choisi des TextBox (avec une couleur de fond) simplement car ce n'est pas moi qui vais utiliser l'UF, et je trouve que c'est plus intuitif pour l'utilisateur, qui saura directement où seront ses résultats .. même avant de lancer les calculs

Je redoutais un peu cette solution pour cause de flemme de rechanger tous les noms ^^ mais je crois que c'est le plus sage ..

J'avais commencé l'UF sans savoir qu'il deviendrait aussi gros, et en débutant Vba, donc sans vraiment d'organisation.

C'est parti pour les changements de nom !

Merci James et Fred, à bientôt !

Re,

Désolé pour "auditer" ...

Pour moi, cela signifie ... se farcir les noms des 500 TextBoxes de ta UserForm ...

Bon Courage pour la suite ...

Bonjour,

Je reviens sur le sujet, mais 500 textbox ???

Ca me parait énorme quand même

Bonjour,

Je n'y suis pas encore mais ça risque d'arriver vite. J'en suis réellement à 277 pour le moment, mais j'utilise un multipage et une vingtaine de feuilles de calcul. L'utilisateur n'utilisera pas nécessairement toutes les txtbox mais je dois prévoir tous les cas de figure donc ça en fait beaucoup effectivement ..

Bonjour,

En tout état de cause ... lorsque tu auras finalisé ton projet ... ce serait sympa de le partager avec le Forum ...

Bonjour,

Je bosse en réalité dans la thermique pour un CR et c'est un projet en interne donc je ne pense pas pouvoir le diffuser une fois terminé .. Je vais néanmoins essaye de le modifier ou d'en faire une version "blanche" une fois que j'aurai terminé, avec les méthodes et les points sur lesquels j'ai galéré .. ça servira peut-être à certains, je l'espère !

Bonjour,

Je reviens sur ce sujet car je rencontre un problème. Je viens de finir de renommer toutes mes TextBoxes, en les séparant en :

TextBox de Saisie = TxbS.. et TextBox de Resultat = TxbR..

J'utilise ce code pour protéger l'écriture des TextBoxes (je sais que pour les TBx résultat je pouvais utiliser Locked, mais j'ai besoin d'un bip pour avertir .. )

Module de classe

Option Explicit

Public WithEvents TextBoxSaisie As MSForms.TextBox
Public WithEvents TextBoxResultat As MSForms.TextBox

Private Sub TextboxSaisie_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)

If InStr("1234567890,.", Chr(KeyAscii)) = 0 _
Or InStr(TextBoxSaisie.Value, ",") <> 0 And Chr(KeyAscii) = "," _
Or InStr(TextBoxSaisie.Value, ".") <> 0 And Chr(KeyAscii) = "." _
Or InStr(TextBoxSaisie.Value, ",") <> 0 And Chr(KeyAscii) = "." _
Or InStr(TextBoxSaisie.Value, ".") <> 0 And Chr(KeyAscii) = "," _
Then
KeyAscii = 0: Beep
End If
End Sub

Private Sub TextBoxResultat_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)

If InStr("", Chr(KeyAscii)) = 0 Then
    KeyAscii = 0: Beep
End If
End Sub

UF

Option Explicit

Dim TextBoxSUsfGen() As New LesTextBoxs
Dim TextBoxRUsfGen() As New LesTextBoxs

Private Sub UserForm_Initialize()

Dim NbreTextBoxSaisie As Integer
Dim Ctrl1 As Control

NbreTextBoxSaisie = 0

For Each Ctrl1 In Me.Controls

    If TypeName(Ctrl1) = "TxbS" Then
        NbreTextBoxSaisie = NbreTextBoxSaisie + 1
        ReDim Preserve TextBoxSUsfGen(1 To NbreTextBoxSaisie)
        Set TextBoxSUsfGen(NbreTextBoxSaisie).TextBoxSaisie = Ctrl1
    End If

Next Ctrl1

Dim NbreTextBoxResultat As Integer
Dim Ctrl2 As Controls

NbreTextBoxResultat = 0

For Each Ctrl2 In Me.Controls

    If TypeName(Ctrl2) = "TxbR" Then
        NbreTextBoxResultat = NbreTextBoxResultat + 1
        ReDim Preserve TextBoxRUsfGen(1 To NbreTextBoxResultat)
        Set TextBoxRUsfGen(NbreTextBoxResultat).TextBoxResultat = Ctrl2
    End If

Next Ctrl2

End Sub

J'ai une erreur d'exécution de type 13 avec "incompatibilité de type" ..

J'avoue que je suis un peu perdu là, j'espère vraiment ne pas avoir tout renommé pour rien !

Bonjour,

Que souhaitez vous faire exactement avec les textbox ?

La saisie concerne uniquement des valeurs réelles et positives. Je veux les brider afin qu'un utilisateur ne puisse pas rentrer de lettre ou 2 virgules, 2 points .. pour éviter les bug type "DIV/0!" dans mes feuilles Excel. Les textbox résultats sont utilisées uniquement pour afficher des résultats obtenus à partir des calculs des feuilles Excel. En fonction de leur valeur, certaines autres Textbox résultats s'affichent en dessous, et les couleurs varient également en fonction des valeurs.

S'il s'agit uniquement de saisies de nombre entier vous pouvez utiliser un module de classe nommé "NumBox" par exemple :

Public WithEvents TargetBox As MSForms.TextBox
Private Sub TargetBox_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
    If KeyAscii < 48 Or KeyAscii > 57 Then KeyAscii = 0: Beep
End Sub

Dans un module declarer comme ceci

Public NBox() As New NumBox

puis dans votre formulaire :

    ReDim NBox(44)
    For NumCtrl = 1 To 44
        Set NBox(NumCtrl).TargetBox = .Controls("Textbox" & NumCtrl)
        .Controls("TextBox" & NumCtrl) = ""
        .Controls("TextBox" & NumCtrl).Tag = 0
    Next NumCtrl

Ne pas oubli de déclarer la variable NumCtrl dans le formulaire

Private NumCtrl As Integer

ne pas oublier de modifier le nombre 44 et la boucle 1 à 44 en fonction du nombre de textbox que vous souhaitez inclure.

ReDim NBox(44)
For NumCtrl = 1 To 44

Merci pour votre réponse,

Mais ce type de code fonctionnera pour toutes les TextBox non ? Comment je pourrais séparer mes Txb de saisie avec mes Txb résultat ? Vu que je les ai toutes renommées, n'y a t-il pas moyen de se servir de leur nom ?

Remplacer Textbox par le nom des textbox conernées dans chaque ligne de ce type :

 .Controls("TextBox" & NumCtrl)
Rechercher des sujets similaires à "inserer private sub boucle"