Loop et checkbox
Bonjour,,
J'ai créé un formulaire VBA qui contient environ 160 controls dont au moins 1/3 de checkboxes. L'idée est que l'utilisateur coche autant de checkbox que nécessaire et qu'une fois le formulaire validé, le "caption" de la checkbox viennent s'ajouter à la suite du reste des données du tableau en colonne A.
J'aimerais éviter d'écrire une condition pour chacune des checkbox et j'ai donc écrit le code suivant. Sauf que je n'arrive pas à faire en sorte que le "caption" de ma checkbox soit ajouté à mon tableau.
Quelqu'un aurait-il une solution?
Merci d'avance
Private Sub Update_Click()
Dim LastRow As Long
Dim ctrl As Control
On Error GoTo ErrorHandle
LastRow = Worksheets("Rapport").Cells(Rows.Count, 1).End(xlUp).Row + 1
For Each ctrl In Me.Controls
If TypeOf ctrl Is MSForms.CheckBox Then
If CheckBox.Value = True Then
Cells(LastRow, 1).Value = CheckBox.Caption
End If
End If
LastRow = LastRow + 1
Next ctrl
ErrorHandle:
MsgBox Err.Description
End SubBonjour Gerald, bonjour le forum,
Essaie comme ça :
Private Sub Update_Click()
Dim LastRow As Long
Dim ctrl As Control
On Error GoTo ErrorHandle
LastRow = Worksheets("Rapport").Cells(Rows.Count, 1).End(xlUp).Row + 1
For Each ctrl In Me.Controls
If TypeOf ctrl Is MSForms.CheckBox Then
If ctrl.Value = True Then
Worksheets("Rapport").Cells(LastRow, 1).Value = ctrl.Caption
End If
LastRow = LastRow + 1
End If
Next ctrl
ErrorHandle:
MsgBox Err.Description
End SubBonjour Thauthème,
Merci de ta réponse. Cependant, ça ne fonctionne pas tout à fait.
Si je ne choisis qu'une checkbox, j'ai bien le résultat souhaité. Par contre dès que j'en choisi plus, ça ne fonctionne pas, il ne me récupère que le caption de la dernière checkbox sélectionnée.,
De plus, le "on error go to" car si je choisis 10 checkbox, j'avaais 10 msgbox sans aucun message et sur lesquelle je devais cliquer OK.
Aurais-tu une idée`pour savoir ce qui ne joue pas??
Merci
ReBonjour ThauThème,
J'ai trouvé d'où venait le problème:
J'ai remplacé cette ligne: Worksheets("Rapport").Cells(LastRow, 1).Value = ctrl.Caption par activecell.Value... et j'ai rajouté un offset just avant le premier end if.
Maintenant, j'ai un autre problème, mon formulaire est ainsi
Tâche / Commentaire / Temps (CheckBox/TxtBox/TxtBox)
J'ai une quarantaine de ligne avec pour chacune ces 3 types de contrôles.
L'idée était donc de dire que si ma checkbox était cochée, j'avais en colonne A l'intitulé de ma tâche, en colonne B le commentaire et en colonne C le temps.
Maintenant que j'ai ce qu'il me faut en colonne A, y a-t-il un moyen de préparer quelque chose du type:
ActiveCell.Value = ctrl.Caption
ActiveCell.Offset(0, 1).Value =ctrl + 1.caption
ActiveCell.Offset(0, 2).Value =ctrl + 2.caption
Merci d'avance
Bonjour Gerald, bonjour le forum,
D'abord je ne comprends pas, malgré tes explications, ce qui clochait dans le code que je t'avais proposé. Ensuite, sans un fichier exemple, je ne vois pas comment t'aider davantage.
Re bonjour Thauthème,
Voici donc le fichier en pièce jointe, pour des questions de confidentialité, j'ai effacé certaines données.
Donc, comme tu pourras le constater, j'ai diverses tâches et des commentaires et donc j'ai besoin que si je coche une activité, la valeur de cette activité soit rappatriée en colonne A, les commentaires correspondant en colonne B et le temps passé en colonne C.
J'ai essayé de bricoler mais je n'y arrive pas.
Ce serait vraiment génial si tu arrivais à solutionner mon problème.
Merci d'avance.
Gérald
Re,
Gérald désolé mais je ne vois aucune Checkbox dans ton fichier.
Je conçois que tu effaces les données confidentielles mais laisse au mois des données bidons pour qu'on puisse comprendre !...
Soit plus clair dans tes explications, je ne sais même pas de quel onglet tu parles. Je ne peux rien pour toi si tu ne fais pas le minimum d'effort...
Bonjour Thauthème,
Je me suis peut-être mal exprimé mais il n'y a aucun control directement sur la feuille excel, tout est dans le formulaire
La feuille client ne sert qu'à alimenter la combobox LstClient du formulaire, la feuille consultant me sert à alimenter la combobox CboConsultant du formulaire.
Ensuite dans le formulaire, chaque tâche est une checkbox dont le caption commence par "chk".
Comme expliqué précédemment, j'ai besoin qu'une fois le formulaire validé, toutes les tâches qui sont validées ainsi que les commentaire et le temps passé pour chaque tâche viennent alimenter le tableau de la feuille "Rapport"
Je n'arrive pas à faire de printscreen mais il y a 40 tâches qui sont toutes des checkbox.
Merci d'avance.
Gérald.
Re,
Oui désolé je n'avais pas vu qu'il y avait une UserForm. C'est plus clair maintenant... Toutefois je ne vois pas l'utilité de l'onglet Activité. Quel est-il ?
Je regarde ça après le repas...
Re, l'onglet activité n'a plus d'utilité, faut que je l'efface.
Merci encore
Re,
Essaie comme ça :
Private Sub Update_Click()
Dim O As Worksheet
Dim LastRow As Long
Dim ctrl As Control
Dim ref As String
Set O = Worksheets("Rapport")
LastRow = O.Range("A" & Application.Rows.Count).End(xlUp).Row
For Each ctrl In Me.Controls
If TypeOf ctrl Is MSForms.CheckBox Then
If ctrl.Value = True Then
ref = Split(ctrl.Name, "Chk")(1)
O.Cells(LastRow, 1).Value = ctrl.Caption
O.Cells(LastRow, 2).Value = Me.Controls("Txt" & ref).Value
O.Cells(LastRow, 3).Value = Me.Controls("TxtTime" & ref).Value
O.Cells(LastRow, 4).Value = Me.Lst_Client.Value
O.Cells(LastRow, 5).Value = Me.CboConsultant.Value
O.Cells(LastRow, 6).Value = Me.date_dmd.Value
End If
End If
Next ctrl
Unload Me
End SubC'est rare de voir une UserForm aussi bien structurée ! Bravo, ça permet un code simple...
Re,
Merci pour le compliment, ça fonctionne nickel, encore merci mille fois!!!!!!
Re,
Code corrigé ! J'ai déplacé le définition de LastRow à l'intérieur de la boucle If ctrl.Value = True Then...
Private Sub Update_Click()
Dim O As Worksheet
Dim LastRow As Long
Dim ctrl As Control
Dim ref As String
Set O = Worksheets("Rapport")
For Each ctrl In Me.Controls
If TypeOf ctrl Is MSForms.CheckBox Then
If ctrl.Value = True Then
LastRow = O.Range("A" & Application.Rows.Count).End(xlUp).Row
ref = Split(ctrl.Name, "Chk")(1)
O.Cells(LastRow, 1).Value = ctrl.Caption
O.Cells(LastRow, 2).Value = Me.Controls("Txt" & ref).Value
O.Cells(LastRow, 3).Value = Me.Controls("TxtTime" & ref).Value
O.Cells(LastRow, 4).Value = Me.Lst_Client.Value
O.Cells(LastRow, 5).Value = Me.CboConsultant.Value
O.Cells(LastRow, 6).Value = Me.date_dmd.Value
End If
End If
Next ctrl
Unload Me
End SubBonsoir Thauthème,
Merci pour ta réponse concernant le if isnumeric.
Je ne suis pas certain de comprender la différence entre un module et un module de classe
E
n fait, c'est vrai que j'aurais aimé forcer les utilisateurs dès la saisie à saisir au bon format. Vu que je ne sais pas faire, je pensais plutôt à une vérification au moment de la validation du formulaire. Si le format n'est pas juste, une message box indique que le format est erronné.
Au vu du nombre actuel de textboxes (qui risque d'augmenter par la suite), je ne me vois pas écrire une condition pour chaque textbox.
Pour rappel, voici le code que j'avais préparé:
For Each ctrl In Me.Controls
If TypeOf ctrl Is MSForms.TextBox And Left(ctrl.Name, 7) = "txtTime"
Then
If Not IsNumeric(Me.ActiveControl.value) And Me.ActiveControl.value <> vbNullString Then
MsgBox "Merci de ne saisir que des valeurs numériques. Exemple:
1h15=1.25"
Exit Sub
End If
End If
Next ctrlVoici celui proposé:
Private Sub TxtTimeOp1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
If KeyAscii = 44 Then KeyAscii = 46
Exit Sub 'remplace la virgule par le point
If KeyAscii = 46 Then Exit Sub 'si un point est tapé sort de la procédure
If KeyAscii < 48 Or KeyAscii > 57 Then KeyAscii = 8 'n'autorise que les caractères {0, 1, 2, 3, 4, 5, 6, 7, 8 et 9}
End SubMerci d'avance.
Gérald
Bonjour Gerald, bonjour le forum,
Comme tu le dis, ce n'est pas l'idéal de copier le code autant de fois qu'il a de textboxes Time. D'où l'utilité du module de classe. À l'initialisation de l'UserForm, on définit dans un tableau quelles sont les texboxes qui vont faire partie de la classe du module. Ensuite on écrit un code commun pour toutes les instances de cette classe.
Dans ton cas (bien structuré), il m'a suffit de dire que toutes les textboxes dont le nom commence par TxtTime faisaient partie du tableau des instances de la classe (j'ai utilisé Ucase car il y avait aussi des txtTime). J'ai rajouté le code à l'initialisation de l'UserForm...
Malheureusement, tous les événements ne sont pas permis dans un module de classe, notamment l'événement AfterUpdate. Le code qui réduit les touches du clavier aux seuls caractères {., 0, 1, 2, 3, 4, 5, 6, 7, 8 ou 9} utilise l'événement KeyPress (qui réagit à l'appui sur une touche du clavier). Mais avec ce système, impossible (sans écrire un code pour chaque textboxes) de vérifier "after update". Je te propose donc un seul message à l'ouverture de l'UserForm (à adapter) pour prévenir du format. Ensuite, pour toutes les textboxes Time, si l'utilisateur presse une touche autre que celles citées plus haut, le caractère est aussitôt effacé et donc n'apparaît pas dans la TextBox.
Si plus tard tu rajoutes des textboxes, il suffira que son nom commence par TxtTime pour qu'il soit automatiquement intégré au tableau des instances de la classe.
Le fichier :
Bonjour Thauthème,
Encore une fois merci pour ton temps et pour ta réponse.
Alors en fait, en attendant, j'ai quand même continué à chercher et au final, j'ai dupliquer plus ou moins ce que tu avais fait précédemment. Au final, ça ne bloque pas à la saisie mais ça empêche la validation de la procédure si le format des textboxes concernés n'est pas numérique.
Voici donc le morceau de code:
For Each ctrl In Me.Controls
If TypeOf ctrl Is MSForms.TextBox Then
If Left(ctrl.Name, 7) = "txtTime" Then
ref_bis = Split(ctrl.Name, "txtTime")(1)
If Not IsNumeric(Me.Controls("txtTime" & ref_bis).value) And Me.Controls("txtTime" & ref_bis).value <> vbNullString Then
MsgBox "Merci de ne saisir le temps passé en valeurs numériques. Exemple: 1h15=1.25"
Exit Sub
End If
End If
End If
Next ctrlJ'avais déjà essayé sans que ça ne fonctionne, la seule chose c'est qu'au début au lieu d'avoir 2 if, j'avais un if AND.
Comme ça ne fonctionnait pas, j'ai fait 2 if et ça fonctionne.
Encore merci pour ton temps
Gerald