VBA - textbox - simplification code
Bonjour,
J'ai crée un Userform-DEVIS et il y a des TEXTBOX pour mettre des quantité, et un fois VALIDER par un Commandbox, celui ci change de Couleur pour signaler a l'utilisateur que c'est OK et il peut retourné au menu.
Mais il arrive que meme apres Validation il change de quantité etc, pas de soucis le Commandbox change de couleur passe au Rouge par exemple afin de revalider.
Donc pour arrivé a cela, j'ai crée plusieurs Private Sub MENUIV1_Change() et jusqu'a Private Sub MENUIV50_Change()
donc j'ai 50 private Sub pour 50 Textbox avec la meme commande dans chaque Sub
Et ma question et peut on simplifier
en un seul SUB par exemple ?
D'avance Merci et j'espere avoir était clair
Bonjour,
Oui, c'est même recommandéé, mais un petit peu compliqué :Si tu n'en a jamais fait il te faudra faire sous-traiter ça par un expert...
Sinon faire une recherche sur Google sur le thème " module de classe vba "
A+
Bonjour fathlaur, galopin01,
Oui, au lieu d'avoir 50 Private Sub différents pour chaque TextBox, vous pouvez utiliser une seule procédure et l'attribuer à tous les TextBox en utilisant la fonction Handles. Cependant, cela n'est pas directement possible en VBA, mais vous pouvez utiliser une technique similaire en utilisant le gestionnaire d'événements de classe.
Voici un exemple sur la façon de le faire:
1 Créez une nouvelle classe. Pour cela, allez dans "Insert" > "Class Module". Nommez cette classe, disons clsTextBox.
2 Dans ce nouveau module de classe, ajoutez le code suivant :
Public WithEvents tb As MSForms.TextBox
Private Sub tb_Change()
' Votre logique de validation ici.
' Utilisez tb pour accéder aux propriétés du TextBox qui a déclenché l'événement.
End Sub3 Ensuite, dans votre UserForm, vous devez déclarer une Collection ou un Array pour stocker des instances de clsTextBox, et assigner chaque TextBox à une instance.
Private textBoxes As Collection
Private Sub UserForm_Initialize()
Set textBoxes = New Collection
Dim ctl As Control
For Each ctl In Me.Controls
If TypeOf ctl Is MSForms.TextBox Then
Dim ctb As New clsTextBox
Set ctb.tb = ctl
textBoxes.Add ctb
End If
Next ctl
End SubMaintenant, chaque fois qu'un TextBox change, le gestionnaire d'événements dans clsTextBox sera déclenché. Vous pouvez ajouter votre logique de validation dans tb_Change() pour changer la couleur du TextBox, etc.
Sachez que chaque fois que vous modifiez le TextBox, vous utilisez l'objet tb pour accéder aux propriétés et méthodes du TextBox qui a déclenché l'événement. J'espère que cela vous aidera !
Merci Abderrahmane BENALI cela m'as un peu aidé, mais ...
Pour info mais textbox je l'ai est renommé par MENUIV. (Question de clarté, car j'ai pour la menuiserie, electricité etc)
Mais pour faire le teste, dans mon userform, j'ai crée 4 textbox sans les renommés, textbox1 textbox2 etc. Donc j'ai recopié vos informations de code et dans le code de module j'ai fait une modif juste pour l'essai
Public WithEvents tb As MSForms.TextBox
Private Sub tb_Change()
msgbox(" ESSAI DE FONCTIONNEMENT ") ' bien sur pour l'essai
' Votre logique de validation ici.
' Utilisez tb pour accéder aux propriétés du TextBox qui a déclenché l'événement.
End SubJuste un truc que je ne comprend pas, pourquoi quand je modifie dans les 3 premiers textbox crée, cela fonctionne pas, mais si je modifie le 4eme sa fonctionne ???
et peut importe l'ordre c'est toujours le 4eme ? et pour info (J'ai essayé en rajoutant 2 autres et c'est le dernier qui est pris en compte).
Et m'as question est faut il que je renomme mais textbox MENUIV et textbox1 2 3 etc. et autre question je peux faire un call validation par exemple dans le module class, sachant que validation et coder dans mon userform ? Pour le call j'ai trouvé call userform.validation (par exemple)
Lorsque vous utilisez la syntaxe Dim ctb As New clsTextBox, le nouvel objet est créé immédiatement. Cependant, si vous le faites dans une boucle, le nouvel objet écrase l'objet précédent à chaque itération, c'est pourquoi seul le dernier TextBox semble déclencher l'événement.
Pour éviter cela, vous pouvez créer un nouvel objet de manière distincte en utilisant Set,
Private Sub UserForm_Initialize()
Set textBoxes = New Collection
Dim ctl As Control
For Each ctl In Me.Controls
If TypeOf ctl Is MSForms.TextBox Then
Dim ctb As clsTextBox
Set ctb = New clsTextBox
Set ctb.tb = ctl
textBoxes.Add ctb
End If
Next ctl
End SubAvec cette modification, chaque TextBox devrait maintenant déclencher l'événement Change() dans la classe clsTextBox.
Concernant la question de renommer vos TextBox, cela dépend de votre préférence. Si vous souhaitez que votre code soit plus clair et plus explicite, vous pouvez les renommer comme MENUIV1, MENUIV2, etc. Cependant, cela n'a pas d'impact sur la logique de votre programme tant que vous pouvez identifier chaque TextBox univoquement. Vous pouvez utiliser le nom d'origine TextBox1, TextBox2, etc. tant que vous pouvez les distinguer et comprendre leur fonction dans votre programme.
Parfait un grand merci.
Juste comme mon userform a plusieurs page, je vais voir pour faire une condition en fonction de la page. Car pour chaque page la validation est différentes
Une approche pourrait être d'ajouter une condition dans votre méthode tb_Change() pour vérifier la page actuelle et d'appliquer la logique de validation correspondante.
Puisque vous avez mentionné que vous utilisez plusieurs pages, j'imagine que vous utilisez un contrôle MultiPage. Si c'est le cas, vous pouvez vérifier la page actuellement sélectionnée en utilisant MultiPage.Value. Par exemple, vous pouvez ajouter quelque chose comme ceci dans votre classe clsTextBox
Private Sub tb_Change()
Select Case MultiPage.Value
Case 0
' Logique de validation pour la première page
Case 1
' Logique de validation pour la deuxième page
' etc.
End Select
End SubNotez que MultiPage.Value donne l'index de la page actuellement sélectionnée, en commençant par 0.
Cependant, veuillez noter que dans ce code, MultiPage doit être remplacé par le nom réel de votre contrôle MultiPage. Vous aurez également besoin de déterminer comment accéder à ce contrôle depuis la classe - une option pourrait être de le passer en tant que paramètre à la classe. J'espère que cela vous aidera ! ^^
j'était entrain de voir avec un if ...
Mais votre code et plus simple a gerér. Donc j'ai bien MultiPage1 de la page 0 a 5
Donc j'ai fait ceci, en modifiant multipage par multipage1
Private Sub tb_Change()
Select Case MultiPage1.Value
Case 0
Msgbox(" Page 0")
' Logique de validation pour la première page
Case 1
Msgbox(" Page 1")
' Logique de validation pour la deuxième page
' etc.
End Select
End SubMais j'ai erreur exécution 424, objet requis ??
sur la premier ligne select case .............
L'objet MultiPage1 est un contrôle dans votre UserForm, mais la classe clsTextBox ne le voit pas directement car elle est dans un autre espace de noms. Vous pouvez résoudre ce problème en passant une référence à votre UserForm à la classe.
Ajoutez une nouvelle variable dans la classe clsTextBox pour contenir une référence à votre UserForm
Public WithEvents tb As MSForms.TextBox
Public myForm As UserFormQuand vous créez de nouvelles instances de clsTextBox dans votre UserForm, définissez également myForm
Private Sub UserForm_Initialize()
Set textBoxes = New Collection
Dim ctl As Control
For Each ctl In Me.Controls
If TypeOf ctl Is MSForms.TextBox Then
Dim ctb As clsTextBox
Set ctb = New clsTextBox
Set ctb.tb = ctl
Set ctb.myForm = Me
textBoxes.Add ctb
End If
Next ctl
End SubMaintenant, vous pouvez accéder à MultiPage1 dans votre classe en utilisant myForm.MultiPage1
Private Sub tb_Change()
Select Case myForm.MultiPage1.Value
Case 0
MsgBox ("Page 0")
' Logique de validation pour la première page
Case 1
MsgBox ("Page 1")
' Logique de validation pour la deuxième page
' etc.
End Select
End SubChaque instance de clsTextBox aura une référence à votre UserForm, et vous pourrez accéder à tous les contrôles de l'UserForm depuis la classe clsTextBox. J'espère que cela vous aidera !
Que dire a part PARFAIS
Vraiment merci, de votre temps, et surtout j'ai pu apprendre de nouvelle info.
Pas de souci