OVH Cloud OVH Cloud

Parcours de controles

16 réponses
Avatar
elect31
Bonjour à tous
Dans le frame d'un userform, j'ai 40 controles divers et variés : 24
comboBox, 8 TextBox, 8 Label
Question : comment éviter de parcourir tous les controles du frame? Il
n'y a que les TextBox tagués "mains" qui m'interessent.
Dans le code ci dessous que j'utilise, Excel parcours tous les controles
jusqu'à ce qu'il en rencontre un tagué "mains".
N'y aurait il pas un moyen d'aller plus vite et de ne parcourir que les
TextBox?

With .Controls("FrameSeance" & CStr(i))
LaColonne = 0
For Each C In .Controls
If C.Tag = "mains" Then
C.Value = CStr(ThisWorkbook.Worksheets(date_seance). _
Range("CA5").Offset(laLigne, LaColonne).Value)
LaColonne = LaColonne + 1
End If
Next C
End With

PS: Ce code fonctionne. Je suis simplement en train d'essayer de
l'optimiser.

Merci de vos réponses

6 réponses

1 2
Avatar
elect31
Merci de ta réponse isabelle
Effectivement cela pourra me servir, mais dans le projet actuel je pense
que je vais plutôt utiliser les collections. Cela me semble plus adapté
à ma situation.
En fait, je veux parcourir certains contrôles d'un même frame, mai je
n'oublie pas cette astuce.
Cordialement
elect

isabelle a écrit :
bonjour Elect,

une autre méthode est de vérifier son Parent

Private Sub CommandButton1_Click()
Dim c As Control
For Each c In Me.Controls
If TypeName(c) = "TextBox" And c.Parent.Name = "Frame1" Then
MsgBox c.Name
End If
Next c
End Sub

isabelle

Le 2010-03-17 07:06, elect31 a écrit :
Aaaaahhhh!
Je savais bien qu'il y aurait un magicien pour me sortir un truc que
je ne connaissais pas.
Je m'en va l'essayer tout de suite.
Bon! Quand tu dis optimiser ton code, tu entends bien le faire aller
plus vite? (Même si je sais que la différence ne sera pas forcément
visible à l'oeil).
En tous les cas merci de cet enseignement. J'en comprends la logique
et je vais voir ce que ça donne dans mon code.
elect

Benoît Marchand [Benead] a écrit :
Bonsoir,

Si tu tiens à optimiser ton code, tu dois utiliser une collection. Tu
fais une première boucle pour créer ta collection de TexBox
(généralement dans l'initialisation du UserForm), ensuite il te
suffit de faire appel a collection de TextBox que tu viens de créer.
Cela donne cela (à adapter) :

' Variable à déclarer en début du UserForm ou si besoin en Public
dans un module classique
Dim TextBoxGroup As New Collection



Private Sub CommandButton1_Click()
.../...
' Boucle interne à ton programme
Dim TxB As Control
For Each TxB In TextBoxGroup
' .../...
TxB.BackColor = &H8080FF
Next TxB
.../...
End Sub



Private Sub UserForm_Initialize()

' A ajouter dans UserForm_Initialize
Dim Ctrl As Control
' Création d'une collection de TextBox ayant "mains" en Tag
For Each Ctrl In Me.Controls
If TypeName(Ctrl) = "TextBox" And Ctrl.Tag = "mains" Then
TextBoxGroup.Add Ctrl
End If
Next Ctrl

End Sub


Si ton programme est gourmand en mémoire et du code s'exécute après
le traitement des TextBox, par exemple quand tu décharges l'Userform
(Unload), il serait judicieux de supprimer ta collection en ajoutant
cette ligne :
Set TextBoxGroup = Nothing

A+
Benead
Excel 2000

elect31 a écrit :
Merci de ta réponse Benoit
Je peux remplacer Tag par TypeName à condition que tous les TextBox
soient concernés. Peut être que seulement certains TextBox (ceux que
j'ai tagué "mains") m'intéressent...
Sinon, effectivement, j'ai souvent plusieurs boucles imbriquées
l'une dans l'autre, d'où mon intention d'essayer d'accélérer le
processus.

Bon, tant pis! Même si la réponse à ma question est négative, j'y
aurai au moins gagné la certitude que ce bout de code est
optimisé... à moins que quelqu'un d'autre ait une solution miracle
comme certains peuvent les trouver. Du genre, là où je mets 10
lignes de code, ils en mettent 1. Je suis autodidacte dans le
domaine de la programmation, d'où mon questionnement.
Encore merci à tous ceux qui lisent et qui répondent dans ce forum.

Benoît Marchand [Benead] a écrit :
Bonjour,

Non à ma connaissance il n'est pas possible de parcourir uniquement
les TextBox.

Par contre tu peux remplacer avantageusement l'utilisation des Tag
par TypeName(C) :

Dim C As Control
For Each C In Controls
If TypeName(C) = "TextBox" Then
' ... Ton Code ...
End If
Next C

En terme de rapidité d'exécution, la différence entre 8 contrôles
ou 40 sera imperceptiblee sauf si cette boucle est elle-même inclue
dans une ou plusieurs boucles et encore...

Benead
Excel 2000

elect31 a écrit :
Bonjour à tous
Dans le frame d'un userform, j'ai 40 controles divers et variés :
24 comboBox, 8 TextBox, 8 Label
Question : comment éviter de parcourir tous les controles du
frame? Il n'y a que les TextBox tagués "mains" qui m'interessent.
Dans le code ci dessous que j'utilise, Excel parcours tous les
controles jusqu'à ce qu'il en rencontre un tagué "mains".
N'y aurait il pas un moyen d'aller plus vite et de ne parcourir
que les TextBox?

With .Controls("FrameSeance" & CStr(i))
LaColonne = 0
For Each C In .Controls
If C.Tag = "mains" Then
C.Value =
CStr(ThisWorkbook.Worksheets(date_seance). _
Range("CA5").Offset(laLigne,
LaColonne).Value)
LaColonne = LaColonne + 1
End If
Next C
End With

PS: Ce code fonctionne. Je suis simplement en train d'essayer de
l'optimiser.

Merci de vos réponses
Avatar
elect31
Ensuite, et si c'est dans le cadre de ta profession, tu
devras toujours te poser la question : le jeu en vaut-il la chandelle >?



Aaahhhh, C'est pour ça que certaines applications sont lentes et "mal
fagotées"? Quelques uns ont du se poser la question : " Entre le temps
passé et le gain obtenu, ça ne vaut pas le coup. Je ferai un patch
correctif plus tard si ça râle..."

Je plaisante bien sur. Comme tu dis, je suis en phase d'apprentissage et
j'essaye de faire le mieux possible. Je crois que c'est comme ça que
l'on apprend, mais je comprends bien les contraintes de la rentabilité.
Bien à vous tous.
elect

Benoît Marchand [Benead] a écrit :
Bonsoir,

Oui, quand je dis "optimiser le code" c'est pour que son exécution soit
plus rapide, mais parfois pour qu'il soit plus concis ou plus lisible.
Tant que tu es dans une phase d'apprentissage, je te conseille
effectivement de voir comment tu peux faire aller plus vite ton
programme. Ensuite, et si c'est dans le cadre de ta profession, tu
devras toujours te poser la question : le jeu en vaut-il la chandelle ?
Mais si tu codes pour ton compte personnel, aucun problème...

A+
Benead

elect31 a écrit :
Aaaaahhhh!
Je savais bien qu'il y aurait un magicien pour me sortir un truc que
je ne connaissais pas.
Je m'en va l'essayer tout de suite.
Bon! Quand tu dis optimiser ton code, tu entends bien le faire aller
plus vite? (Même si je sais que la différence ne sera pas forcément
visible à l'oeil).
En tous les cas merci de cet enseignement. J'en comprends la logique
et je vais voir ce que ça donne dans mon code.
elect

Benoît Marchand [Benead] a écrit :
Bonsoir,

Si tu tiens à optimiser ton code, tu dois utiliser une collection. Tu
fais une première boucle pour créer ta collection de TexBox
(généralement dans l'initialisation du UserForm), ensuite il te
suffit de faire appel a collection de TextBox que tu viens de créer.
Cela donne cela (à adapter) :

' Variable à déclarer en début du UserForm ou si besoin en Public
dans un module classique
Dim TextBoxGroup As New Collection



Private Sub CommandButton1_Click()
.../...
' Boucle interne à ton programme
Dim TxB As Control
For Each TxB In TextBoxGroup
' .../...
TxB.BackColor = &H8080FF
Next TxB
.../...
End Sub



Private Sub UserForm_Initialize()

' A ajouter dans UserForm_Initialize
Dim Ctrl As Control
' Création d'une collection de TextBox ayant "mains" en Tag
For Each Ctrl In Me.Controls
If TypeName(Ctrl) = "TextBox" And Ctrl.Tag = "mains" Then
TextBoxGroup.Add Ctrl
End If
Next Ctrl

End Sub


Si ton programme est gourmand en mémoire et du code s'exécute après
le traitement des TextBox, par exemple quand tu décharges l'Userform
(Unload), il serait judicieux de supprimer ta collection en ajoutant
cette ligne :
Set TextBoxGroup = Nothing

A+
Benead
Excel 2000

elect31 a écrit :
Merci de ta réponse Benoit
Je peux remplacer Tag par TypeName à condition que tous les TextBox
soient concernés. Peut être que seulement certains TextBox (ceux que
j'ai tagué "mains") m'intéressent...
Sinon, effectivement, j'ai souvent plusieurs boucles imbriquées
l'une dans l'autre, d'où mon intention d'essayer d'accélérer le
processus.

Bon, tant pis! Même si la réponse à ma question est négative, j'y
aurai au moins gagné la certitude que ce bout de code est
optimisé... à moins que quelqu'un d'autre ait une solution miracle
comme certains peuvent les trouver. Du genre, là où je mets 10
lignes de code, ils en mettent 1. Je suis autodidacte dans le
domaine de la programmation, d'où mon questionnement.
Encore merci à tous ceux qui lisent et qui répondent dans ce forum.

Benoît Marchand [Benead] a écrit :
Bonjour,

Non à ma connaissance il n'est pas possible de parcourir uniquement
les TextBox.

Par contre tu peux remplacer avantageusement l'utilisation des Tag
par TypeName(C) :

Dim C As Control
For Each C In Controls
If TypeName(C) = "TextBox" Then
' ... Ton Code ...
End If
Next C

En terme de rapidité d'exécution, la différence entre 8 contrôles
ou 40 sera imperceptiblee sauf si cette boucle est elle-même inclue
dans une ou plusieurs boucles et encore...

Benead
Excel 2000

elect31 a écrit :
Bonjour à tous
Dans le frame d'un userform, j'ai 40 controles divers et variés :
24 comboBox, 8 TextBox, 8 Label
Question : comment éviter de parcourir tous les controles du
frame? Il n'y a que les TextBox tagués "mains" qui m'interessent.
Dans le code ci dessous que j'utilise, Excel parcours tous les
controles jusqu'à ce qu'il en rencontre un tagué "mains".
N'y aurait il pas un moyen d'aller plus vite et de ne parcourir
que les TextBox?

With .Controls("FrameSeance" & CStr(i))
LaColonne = 0
For Each C In .Controls
If C.Tag = "mains" Then
C.Value =
CStr(ThisWorkbook.Worksheets(date_seance). _
Range("CA5").Offset(laLigne,
LaColonne).Value)
LaColonne = LaColonne + 1
End If
Next C
End With

PS: Ce code fonctionne. Je suis simplement en train d'essayer de
l'optimiser.

Merci de vos réponses
Avatar
FdeCourt
Aaahhhh, C'est pour ça que certaines applications sont lentes et "mal
fagotées"?



Je dirais que la question qui s'est posé est plutôt : "comment faire
au plus vite pour terminer au plus tôt, et tant pis si ça marche pas,
parceque de toute façon je ne serais plus la pour le voir".... et hop,
une appli lourde et mal fagotée !
Avatar
isabelle
bonjour Elect,

un autre méthode lorsqu'il y a beaucoup de controls sur plusieurs
Frames et sur différente pages d'un MultiPage

lb = Array(21210, 21211, 21310, 21311, 21312, _
21313, 21410, 21411, 21412, 21413, _
21212, 21213, 21214, 21215, 21216, 21314, 21315, 21316, 21317, 21414,
21415, 21416, 21417, 22218, 23111)

With Me
For i = LBound(lb) To UBound(lb)
With .Controls("Label" & lb(i))
Select Case i
Case 0 To 4: .Caption = Format(.Caption, "0")
Case 5 To 9: .Caption = Format(.Caption, "0.00")
Case 10 To 24: .Caption = Format(.Caption, "Currency")
Case Else
End Select
.TextAlign = 2
.Font.Size = 8
.ForeColor = RGB(0, 0, 255)
End With
Next
End With

à noter que pour cet exemple je n'ai pas mis 20000.. label dans le
userform mais je numérote les controls selon leur position,
c'est à dire 21 (no. du frame) , 2 (no. de colonne), 10 no. de ligne
dans le frame) donc le Label21210
je trouve que c'est plus facile ainsi de renommer les controls, et qu'il
y a moins de chance de tomber sur un numéro qui existe déjà.

isabelle

Le 2010-03-19 09:54, elect31 a écrit :
Merci de ta réponse isabelle
Effectivement cela pourra me servir, mais dans le projet actuel je
pense que je vais plutôt utiliser les collections. Cela me semble plus
adapté à ma situation.
En fait, je veux parcourir certains contrôles d'un même frame, mai je
n'oublie pas cette astuce.
Cordialement
elect

isabelle a écrit :
bonjour Elect,

une autre méthode est de vérifier son Parent

Private Sub CommandButton1_Click()
Dim c As Control
For Each c In Me.Controls
If TypeName(c) = "TextBox" And c.Parent.Name = "Frame1" Then
MsgBox c.Name
End If
Next c
End Sub

isabelle

Le 2010-03-17 07:06, elect31 a écrit :
Aaaaahhhh!
Je savais bien qu'il y aurait un magicien pour me sortir un truc que
je ne connaissais pas.
Je m'en va l'essayer tout de suite.
Bon! Quand tu dis optimiser ton code, tu entends bien le faire aller
plus vite? (Même si je sais que la différence ne sera pas forcément
visible à l'oeil).
En tous les cas merci de cet enseignement. J'en comprends la logique
et je vais voir ce que ça donne dans mon code.
elect

Benoît Marchand [Benead] a écrit :
Bonsoir,

Si tu tiens à optimiser ton code, tu dois utiliser une collection.
Tu fais une première boucle pour créer ta collection de TexBox
(généralement dans l'initialisation du UserForm), ensuite il te
suffit de faire appel a collection de TextBox que tu viens de
créer. Cela donne cela (à adapter) :

' Variable à déclarer en début du UserForm ou si besoin en Public
dans un module classique
Dim TextBoxGroup As New Collection



Private Sub CommandButton1_Click()
.../...
' Boucle interne à ton programme
Dim TxB As Control
For Each TxB In TextBoxGroup
' .../...
TxB.BackColor = &H8080FF
Next TxB
.../...
End Sub



Private Sub UserForm_Initialize()

' A ajouter dans UserForm_Initialize
Dim Ctrl As Control
' Création d'une collection de TextBox ayant "mains" en Tag
For Each Ctrl In Me.Controls
If TypeName(Ctrl) = "TextBox" And Ctrl.Tag = "mains" Then
TextBoxGroup.Add Ctrl
End If
Next Ctrl

End Sub


Si ton programme est gourmand en mémoire et du code s'exécute après
le traitement des TextBox, par exemple quand tu décharges
l'Userform (Unload), il serait judicieux de supprimer ta collection
en ajoutant cette ligne :
Set TextBoxGroup = Nothing

A+
Benead
Excel 2000

elect31 a écrit :
Merci de ta réponse Benoit
Je peux remplacer Tag par TypeName à condition que tous les
TextBox soient concernés. Peut être que seulement certains TextBox
(ceux que j'ai tagué "mains") m'intéressent...
Sinon, effectivement, j'ai souvent plusieurs boucles imbriquées
l'une dans l'autre, d'où mon intention d'essayer d'accélérer le
processus.

Bon, tant pis! Même si la réponse à ma question est négative, j'y
aurai au moins gagné la certitude que ce bout de code est
optimisé... à moins que quelqu'un d'autre ait une solution miracle
comme certains peuvent les trouver. Du genre, là où je mets 10
lignes de code, ils en mettent 1. Je suis autodidacte dans le
domaine de la programmation, d'où mon questionnement.
Encore merci à tous ceux qui lisent et qui répondent dans ce forum.

Benoît Marchand [Benead] a écrit :
Bonjour,

Non à ma connaissance il n'est pas possible de parcourir
uniquement les TextBox.

Par contre tu peux remplacer avantageusement l'utilisation des
Tag par TypeName(C) :

Dim C As Control
For Each C In Controls
If TypeName(C) = "TextBox" Then
' ... Ton Code ...
End If
Next C

En terme de rapidité d'exécution, la différence entre 8 contrôles
ou 40 sera imperceptiblee sauf si cette boucle est elle-même
inclue dans une ou plusieurs boucles et encore...

Benead
Excel 2000

elect31 a écrit :
Bonjour à tous
Dans le frame d'un userform, j'ai 40 controles divers et variés
: 24 comboBox, 8 TextBox, 8 Label
Question : comment éviter de parcourir tous les controles du
frame? Il n'y a que les TextBox tagués "mains" qui m'interessent.
Dans le code ci dessous que j'utilise, Excel parcours tous les
controles jusqu'à ce qu'il en rencontre un tagué "mains".
N'y aurait il pas un moyen d'aller plus vite et de ne parcourir
que les TextBox?

With .Controls("FrameSeance" & CStr(i))
LaColonne = 0
For Each C In .Controls
If C.Tag = "mains" Then
C.Value =
CStr(ThisWorkbook.Worksheets(date_seance). _
Range("CA5").Offset(laLigne,
LaColonne).Value)
LaColonne = LaColonne + 1
End If
Next C
End With

PS: Ce code fonctionne. Je suis simplement en train d'essayer de
l'optimiser.

Merci de vos réponses
Avatar
elect31
Bonjour
quelle est la différence dans le cas unique d'un contrôle entre :

Dim C as Control
If TypeName(C) = "TextBox" Then
et
If typeof C Is TextBox then

Merci de vos réponses éclairées
elect



Benoît Marchand [Benead] a écrit :
Bonjour,

Non à ma connaissance il n'est pas possible de parcourir uniquement les
TextBox.

Par contre tu peux remplacer avantageusement l'utilisation des Tag par
TypeName(C) :

Dim C As Control
For Each C In Controls
If TypeName(C) = "TextBox" Then
' ... Ton Code ...
End If
Next C

En terme de rapidité d'exécution, la différence entre 8 contrôles ou 40
sera imperceptiblee sauf si cette boucle est elle-même inclue dans une
ou plusieurs boucles et encore...

Benead
Excel 2000

elect31 a écrit :
Bonjour à tous
Dans le frame d'un userform, j'ai 40 controles divers et variés : 24
comboBox, 8 TextBox, 8 Label
Question : comment éviter de parcourir tous les controles du frame? Il
n'y a que les TextBox tagués "mains" qui m'interessent.
Dans le code ci dessous que j'utilise, Excel parcours tous les
controles jusqu'à ce qu'il en rencontre un tagué "mains".
N'y aurait il pas un moyen d'aller plus vite et de ne parcourir que
les TextBox?

With .Controls("FrameSeance" & CStr(i))
LaColonne = 0
For Each C In .Controls
If C.Tag = "mains" Then
C.Value =
CStr(ThisWorkbook.Worksheets(date_seance). _
Range("CA5").Offset(laLigne, LaColonne).Value)
LaColonne = LaColonne + 1
End If
Next C
End With

PS: Ce code fonctionne. Je suis simplement en train d'essayer de
l'optimiser.

Merci de vos réponses
Avatar
michdenis
Bonjour,

Il n'y a pas de différences dans l'exemple que tu indiques.
C'est plus une question d'habileté d'écrire une procédure
susceptible d'utiliser l'une ou l'autre façon de faire.

Voici un exemple en 2 parties :

A ) si tes textbox sont dans un formulaire (userform)
'-----------------------------
Private Sub CommandButton1_Click()
Dim A As Integer, b As Integer
Dim C As Control
For Each C In Me.Controls
If TypeName(C) = "TextBox" Then
A = A + 1
End If
If TypeOf C Is MSForms.TextBox Then
b = b + 1
End If
Next
MsgBox A & " TypeName(C)" & vbCrLf & b & " Typeof C"
End Sub
'-----------------------------

B ) Textbox dans une feuille de calcul
Textbox émanant de la boîte d'outils "Contrôle"
'----------------------------
Sub test()
Dim A As Integer, b As Integer
Dim C As OLEObject
For Each C In Me.OLEObjects
If TypeName(C.Object) = "TextBox" Then
A = A + 1
End If
If TypeOf C.Object Is MsForms.TextBox Then
b = b + 1
End If
Next
MsgBox A & " TypeName(C)" & vbCrLf & b & " Typeof C"
End Sub
'----------------------------






"elect31" a écrit dans le message de groupe de discussion :

Bonjour
quelle est la différence dans le cas unique d'un contrôle entre :

Dim C as Control
If TypeName(C) = "TextBox" Then
et
If typeof C Is TextBox then

Merci de vos réponses éclairées
elect



Benoît Marchand [Benead] a écrit :
Bonjour,

Non à ma connaissance il n'est pas possible de parcourir uniquement les
TextBox.

Par contre tu peux remplacer avantageusement l'utilisation des Tag par
TypeName(C) :

Dim C As Control
For Each C In Controls
If TypeName(C) = "TextBox" Then
' ... Ton Code ...
End If
Next C

En terme de rapidité d'exécution, la différence entre 8 contrôles ou 40
sera imperceptiblee sauf si cette boucle est elle-même inclue dans une
ou plusieurs boucles et encore...

Benead
Excel 2000

elect31 a écrit :
Bonjour à tous
Dans le frame d'un userform, j'ai 40 controles divers et variés : 24
comboBox, 8 TextBox, 8 Label
Question : comment éviter de parcourir tous les controles du frame? Il
n'y a que les TextBox tagués "mains" qui m'interessent.
Dans le code ci dessous que j'utilise, Excel parcours tous les
controles jusqu'à ce qu'il en rencontre un tagué "mains".
N'y aurait il pas un moyen d'aller plus vite et de ne parcourir que
les TextBox?

With .Controls("FrameSeance" & CStr(i))
LaColonne = 0
For Each C In .Controls
If C.Tag = "mains" Then
C.Value >> CStr(ThisWorkbook.Worksheets(date_seance). _
Range("CA5").Offset(laLigne, LaColonne).Value)
LaColonne = LaColonne + 1
End If
Next C
End With

PS: Ce code fonctionne. Je suis simplement en train d'essayer de
l'optimiser.

Merci de vos réponses
1 2