VBA listes déroulantes et boucles
Bonjour!
J'ai actuellement un problème avec des listes déroulantes :
J'ai en feuille1 une liste qui ressemble à çà:
---A---B
1--1----
2--1---1
3--1---2
4--1---3
5--1---4
6--2----
7--2---1
Etc. Etc. Etc.
Je voudrais rentrer en feuille2 tous les nombres de la colonne B de la feuille1 dont le nombre de la même ligne et colonne A est 1 (1;2;3;4...)
J'ai pour cela rentré le code suivant qui marche MAIS il ne va pas jusqu'au bout ou, des fois, il ne sort pas de la première boucle (je travail en déboggage avec F8, ça m'evite de redémarrer excel dans ces cas la)
Voici le code :
Private Sub ComboBox1_Change()
Dim i As Integer
I=17 'le tableau en feuille1 commence en fait en ligne 19
Sheets("Feuil1").Select
Do Until Selection.Cells(i, 1).Formula = "1"
i = i + 1
Loop
i = i + 1 ' pour ajuster le tir...
Do While Selection.Cells(i, 1).Fomula = "1" 'j'ai aussi essayé avec until et <>
ComboBox1.AddItem(ActiveSheet.Cells(i, 2).FormulaLocal) 'ou
i = i + 1. '.Formula
Loop
End Sub-- 07 Juil 2011, 14:06 --
Quelqu'un verrait l'erreur du code? Ou si quelque chose ne va pas?!
Je suis preneur pour toute remarque même les fautes d'orthographe (enfin celles du code XD)
Merci à tous!
Bonjour
Je ne suis pas apte à contrôler ta macro.
Une solution par formules
Cordialement
Salut Sym et le forum
Quelqu'un verrait l'erreur du code ? Ou si quelque chose ne va pas ?! Pour dépanner un code, il faut savoir ce qu'il doit faire. Et si le code est "faux"...
Private Sub ComboBox1_Change()
Dim i As Integer
I=17 'le tableau en feuille1 commence en fait en ligne 19
Sheets("Feuil1").Select
Do Until Selection.Cells(i, 1).Formula = "1"
i = i + 1
LoopTout ce que je peux faire, c'est "critiquer" ce bout de code, tant pis pour toi
Tu déclares i en integer => vaut mieux le déclarer en long
tu initialises i à 17 alors qu'il doit commencer à 19 ???
tu sélectionne la feuille "Feuil1" : sert qu'à ralentir ton code
Tu fait une boucle jusqu'à ce qu'elle trouve le chiffre 1 en formule ??? et tu t'étonnes qu'excel ne trouve pas l'égalité ?
Sur une boucle comme ça : utiliser une égalité ... si excel ne la voit pas, il va jusqu'à la fin de la feuille (ou, comme tu as déclaré ta variable ligne en entier, jusqu'au dépassement de valeur d'un entier = 32767). c'est pour ça que je n'utilise pas les boucles infinies (do, while).
en sachant ce qu'est supposé faire ta macro, on ne devrait pas avoir de difficulté à la corriger.
A+
Bonsoir!
A vrai dire cela ne me dérange pas de recevoir des critiques, mais en l'occurrence, excuse moi de trouver répliques à quasi toutes
je te remercie cependant pour le long à la place de l'integer ; à vrai dire je connais pas trop la difference
Sinon, pour le i commençant à 17, c'est jusque que lorsque j'ai commencé la macro, je voulais juste savoir comment évoluait le bazar, (je rappel que je débute
Ensuite, j'active la feuille 1 d'abord car le tableau se trouve en feuille 1 alors que la liste déroulante (le comboBox1) se trouve en feuille 2.. Si c'est bien çà que tu avais compris, je veux bien plus d'explications
Enfin, pour les boucles while et until, çà fait pas longtemps que je maitrise et j'aime beaucoup ; çà change des for-next et des if &Cie
Private Sub ComboBox1_[b]Click[/b]()
ComboBox1.Clear
Dim i As [b]Long[/b] ';-)
[b]I=19 [/b] 'le tableau en feuille1 commence en fait en ligne 19
Sheets("Feuil1").Select
Do Until [b]ActiveSheet[/b].Cells(i, 1).Formula = "1"
[b] If i = 22 then 'une petite marge quand même au cas où
MsgBox "çà marche pas!"
Exit Do
Else[/b]
i = i + 1
[b]End If[/b]
Loop
i = i + 1 ' pour ajuster le tir...
Do While [b]ActiveSheet[/b].Cells(i, 1).Fomula = "1"
[b] If i = 34 then '22+12 ;-)
MsgBox "çà marche pas!"
Exit Do
Else[/b]
ComboBox1.AddItem(ActiveSheet.Cells(i, 2).FormulaLocal)
i = i + 1.
[b] End If [/b]
Loop
End Sub
voilà
Sinon, pour Amadeus, le fichier que tu as donné est quasiment çà, à part que par nombre en colonne A, il n'y aura jamais plus que 12 nombres en colonne B et ils commencent tous par 1 et sont dans l'ordre...
Quant à la feuille 2, c'est exactement çà mais en liste déroulante
Sur ce, merci pour vos réponses,
J'attend vos remarques avec impatience
-- 07 Juil 2011, 22:06 --
Je me permet de dire ce problème Résolu mais j'attend toutefois vos éventuelles remarques =)
Salut Sym et le forum
hors de question que je t'excuse : si je critique ton travail, il me semble normal que tu puisses critiquer le mien ! Si je n'accepte pas que tu me rendes la pareille, je n'ai rien à faire ici, sur ce forum (n'espère pas, je compte m'incruster longtempsA vrai dire cela ne me dérange pas de recevoir des critiques, mais en l'occurrence, excuse moi de trouver répliques à quasi toutes
integer : 2 octets pour définir un nombre de -32768 à +32767je te remercie cependant pour le long à la place de l'integer ; à vrai dire je connais pas trop la difference
Long : 4 octets pour définir un nombre de -2147483648 à +-2147483647
D'après une discussion sur un forum, de toute façon, Excel ne calcule que sur des longs. Pour un gain ridicule (2 octets en RAM), on risque un dépassement de capacité en cas de fausse manip. Pour éviter tout risque, je déclare mes variables nombres entiers en Long.
Se donner une marge de manœuvre est loin d'être idiot. Ça permet de rajouter un titre par exemple.Sinon, pour le i commençant à 17, c'est jusque que lorsque j'ai commencé la macro, je voulais juste savoir comment évoluait le bazar
On a tous commencé par les macros "apprentissage" (nouvelle macro). Le code que fournit Excel est le reflet exact des opérations que tu as effectuées.Ensuite, j'active la feuille 1 d'abord car le tableau se trouve en feuille 1 alors que la liste déroulante (le comboBox1) se trouve en feuille 2.. Si c'est bien çà que tu avais compris, je veux bien plus d'explications
Tu inscrit 1 en A1 Feuil1, puis 2 en C1 Feuil2. Excel te donne :
Sheets("Feuil1").Select
ActiveCell.FormulaR1C1 = "1"
Range("A2").Select
Sheets("Feuil2").Select
Range("C1").Select
ActiveCell.FormulaR1C1 = "2"
Range("C2").SelectLe même résultat, avec un code qui ne comporte pas de lignes "parasites" :
Sheets("Feuil1").Range("A1") = 1
Sheets("Feuil2").Range("C1") = 2C'est plus concis, plus clair, mais surtout, le temps de traitement n'est pas du tout le même. Sur une (ou dix) instruction(s), ce n'est pas significatif. Mais le traitement de 10000 lignes de données et on a un traitement en minutes, contre un traitement en secondes.
Faut être réaliste : un code est purement personnel ! C'est pour ça qu'il y a souvent plusieurs réponses à une question donnée.Enfin, pour les boucles while et until, çà fait pas longtemps que je maitrise et j'aime beaucoup ; çà change des for-next et des if &Cie. Mais j'avais pensé à leur faire une porte de sortie (genre i = 12 tu sors) jusqu'à ce que...
Je trouve la solution!
Je préfère les boucles For...Next, parce qu'elles sont finies. Mais quand je navigue dans l'inconnu, j'utilise aussi des Do...Loop. Mais je cherche toujours un moyen d'en sortir, si ce que j'avais prévu ne fonctionne pas comme je m'y attends. Ce qui fait beaucoup plus d'instructions qu'un simple For...Next.
Dim I As Long
ComboBox1.Clear
I = 19
With Sheets("Feuil1")
Do Until .Cells(I, "A") = 1
If I = 22 Then
MsgBox "ça marche pas!"
Exit Sub
Else
I = I + 1
End If
Loop
I = I + 1
Do While .Cells(I, 1) = 1
If I = 34 Then
MsgBox "ça marche pas!"
Exit Sub
Else
ComboBox1.AddItem (.Cells(I, 2))
I = I + 1
End If
Loop
End WithTon code, tel que je le conçois, donc, avec quelques petites différences
Les déclarations sont en tête de la macro : Je les mets juste sous la ligne de titre : quelque soit l'endroit, VBA fait un premier passage pour les déclarer si elles ne le sont pas.
Mes variables commencent toujours par une majuscule : je tape tout en minuscule. À la validation de la ligne de code, comme la variable est déclarée, si VBA ne me met pas la majuscule, c'est que j'ai une erreur. Pas besoin d'attendre le début de l'exécution pour qu'Excel m'avertisse (je m'oblige à déclarer mes variables - Option Explicit)
With Sheets("Feuil1") : mettre Sheets("Feuil1") en préfixe. Si VBA rencontre un terme commençant par un caractère de liaison, il met le préfixe devant. ainsi ComboBox1.AddItem (.Cells(I, 2)) se lit :
ComboBox1.AddItem (Sheets("Feuil1").Cells(I, 2))
Do Until .Cells(I, "A") = 1 : continuer la boucle jusqu'à ce que la valeur (propriété par défaut) de la cellule A ligne I soit égale à 1
J'évite autant que possible les 1 quand j'utilise des I : une erreur est si vite arrivée, et tard dans le dépannage, ils ont tendance à se confondre (pour moi
Ce n'est pas la formule de A qui t'intéresse, mais son contenu. même si dans ce cas c'est la même chose.
Exit Do : sortir de la boucle Do. Dans ce code, on a pas trouvé de 1 dans les cellules 19, 20, 21, pourquoi continuer la macro ? Je sais, ta deuxième boucle nous fait la même chose, et le résultat est le même. Mais il faut rester logique quand on fait un code : imagine que derrière tu ais un traitement qui doit te couper des données importantes et les mettre ailleurs => si tu ne fais que sortir de ta boucle, tu peux avoir des pertes d'information.
N'hésite jamais à me critiquer . Je me permets souvent de critiquer et j'attends la même chose de tout lecteur d'un de mes postes (seulement de manière constructive, dire c'est nul, n'importe quel imbécile peut le faire sur tout code, mais ça n'apporte rien
Si dans ce que je tentes d'expliquer je m'y prends de manière incompréhensible, demande.
A+
Bonjour!
Alors là plus de remarques ^^ je voudrais juste être clair..
lorsqu'il trouve un i qui se balade dans le code alors que tu as définis un I, il va le changer tout seul? Comme il fait déjà avec des mots connus comme until, cells, sheet, range etc.? Mais donc pourquoi il ne le ferait pas? Seulement si j'ai justement oublié de le déclarer?
Sinon pour le With Sheet("feuil1") c'est super cool, je conaissais pas =)
mais pour les histoires de long et de integer, si c'est juste une question de place ; autant prendre un integer, quite à faire bugger le système autant que ce soit tout de suite XD perso, dans ce cas la, je n'aurais jamais i>100... mais vaut mieux prendre le réflexe tout de suite
Sinon pour l'histoire de sortie, tu voudrais que je mette ma deuxième boucle dans le 1er If de la 1ère boucle? Mais si c'est la deuxième qui plante? En plus ça nous fera une mega imbrication du style :
With
Do until
If
Else
Do while
If
Ellse
End if
Loop
End if
Loop Vous allez me dire... Pk pas?
Salut Sym et le forum
lorsqu'il trouve un i qui se balade dans le code alors que tu as définis un I, il va le changer tout seul ?
Oui, s'il est déclaré.
- Comme il fait déjà avec des mots connus comme until, cells, sheet, range etc.?
Tout à fait. et comme pour mes variables, si la majuscule n'apparaît pas, tu sais que tu as fait une faute de frappe, tout de suite, sans attendre de lancer la macro por qu'Excel te le révèle.
- Seulement si j'ai justement oublié de le déclarer ?
2 solutions : soit il ne se passe rien, soit tu à coché "Déclaration des variables obligatoires" dans le menu Option (ou tu as en tête du module Option Explicit) et Excel te prévient qu'il ne peut pas exécuter ton code au lancement de la macro, parce qu'il y a une variable non définie.
La déclaration des variables est une petite contrainte, mais ça fait gagner un temps fou en dépannage.
- mais pour les histoires de long et de integer, si c'est juste une question de place ; autant prendre un integer
Comme je l'ai dit : un code est personnel. Quand à la question de la place, il faut se remettre dans le contexte : on avait un maximum de 640 ko. 1 octet (Byte) ou 4 (Long) pouvait avoir une répercution sur la RAM et sur le traitement. Maintenant, la RAM est de l'ordre du Gigaoctet...
- mais vaut mieux prendre le réflexe tout de suite
C'est la décision que j'ai prise...
- Sinon pour l'histoire de sortie, tu voudrais que je mette ma deuxième boucle dans le 1er If de la 1ère boucle ?
Non ! Je dis simplement que si la bonne réponse à une boucle n'est pas trouvée, pourquoi continuer l'exécution de la macro ?
Dans ta macro, ce n'est pas très important : si I atteint 22, on lui ajoute 1 et on passe à la boucle suivante qui comme A23 ne contient pas de 1, finira la deuxième boucle avant de l'avoir commencée.
Cependant sur un code conséquent, le fait de ne pas trouver une variable essentielle au déroulement correct de l'algorithme, si tu n'arrêtes pas la macro, continue le code de manière erronée.
C'est pour ça que je conseille d'arrêter le code, et de déclarer les variables dans le type pour lequel elles sont prévues. Variant ne devant être réservé que quand la variable doit recevoir plusieurs types.
Moins tu laisses de possibilités à Excel, moins tu risques l'application de la Loi de Murphy !
Mais c'est une conception personnelle, due à l'arrachage de quelques cheveux pour avoir chercher pendant des heures, pourquoi j'avais perdu des données, alors que ça semblait correct pendant les tests.
A+