ListBox Affiche Cellule si
Bonjour Le Forum !
Je cherche à afficher dans une ListBox une cellule si une autre cellule est égale à 5.
Ceci dit pour Beaucoup de Ligne.
Voir mon fichier joint.
Bonjour,
Sub afficher()
Dim aa, lst(), i%, n%
aa = Feuil2.Range("A1").CurrentRegion
For i = 2 To UBound(aa)
If aa(i, 2) = 5 Then
ReDim Preserve lst(n): lst(n) = aa(i, 1): n = n + 1
End If
Next i
With Feuil1.OLEObjects("ListBox1").Object
Select Case n
Case 0
Case 1: .AddItem lst(0)
Case Else: .List = lst
End Select
End With
End SubNB- Ce code utilise une ListBox (ActiveX)... Je n'ai vu qu'après que tu avais placé un contrôle de formulaire, mais tu as tout intérêt à remplacer la zone de liste par une ListBox.
Cordialement.
Je suis désolé j'ai essayé mais je ne comprend pas ça ne fonctionne toujours pas.
Tu modifies ce qui était prévu, et ensuite tu te demandes pourquoi cela ne fonctionne pas !
La procédure initiale afficher n'est pas un procédure d'évènement ListBox_Click !
Pour une raison simple, c'est que pour cliquer, il faut quelque chose sur quoi cliquer ! Un clic sur une ListBox ce n'est pas un clic sur l'objet, c'est un clic sur un élément de la liste... La ListBox étant vide, le clic n'a aucun effet.
Une fois ta ListBox alimentée, tu pourras cliquer dans la liste... ! Mais il te faut alimenter de l'extérieur et non de l'intérieur de ta ListBox.
Modifie également cette ligne :
Case 1: .Clear: .AddItem lst(0)car avec un seul élément à retenir, tu le mettrais plusieurs fois...
Cordialement.
Okey, c'est que je poussais que ça pouvais ce mettre à jour tout seul sans avoir besoins de cliquer sur un bouton ^^
Parfait le clear ça me remet à jour à chaque click.
Merci !
Par contre si tu veux bien que je t'embête encore, peux-tu m'expliquer le code ?
Sub B_Click()
Dim aa, lst(), i%, n%
aa = Feuil2.Range("A1").CurrentRegion
For i = 2 To UBound(aa)
If aa(i, 2) = 5 Then
ReDim Preserve lst(n): lst(n) = aa(i, 1): n = n + 1
End If
Next i
With Feuil1.OLEObjects("ListBox1").Object
Select Case n
Case 0
Case 1: .Clear: .AddItem lst(0)
Case Else: .List = lst
End Select
End With
End SubCurrentRegion permet de rechercher dans toute la colonne A ?
UBound permet d'aller jusqu'à la dernière ligne. (Néanmoins entre trois lignes celle du milieux est vide il ne prendra en compte que la première ligne du coup non ?)
La suite avec lst() est encore plus dure à comprendre :/
J'ai un petit soucis inexplicable, après modification de mon classeur dès que je clic sur mon bouton ma ListBox se met correctement à jour mais en plus elle grandit constamment...
Sub B_Click()
Dim aa, lst(), i%, n%
aa = Feuil2.Range("C2").CurrentRegion
For i = 2 To UBound(aa)
If aa(i, 5) = 5 Then
ReDim Preserve lst(n): lst(n) = aa(i, 3): n = n + 1
End If
Next i
With Feuil1.OLEObjects("ListBox1").Object
Select Case n
Case 0
Case 1: .Clear: .AddItem lst(0)
Case Else: .List = lst
End Select
End With
End SubGrandir, ça ne devrait pas avec List... Il y a par contre un risque d'erreur 70...
Formule ainsi la fin :
With Feuil1.OLEObjects("ListBox1").Object
.Clear
Select Case n
Case 0
Case 1: .AddItem lst(0)
Case Else: .List = lst
End Select
End WithOn efface la liste antérieure dans tous les cas, ce qui couvre aussi le cas 0 et cela élimine l'erreur que j'avais semble-t-il !
Pour ce qui est du code :
CurrentRegion renvoie une plage rectangulaire à partir d'une plage de référence. Appliquée à A1, elle renvoie donc toute la zone occupée dans les colonnes A et B. La colonne C étant vide interrompt l'extension à droite, et la première ligne où A et B sont vides interrompt l'extension vers le bas.
J'ignore pourquoi tu as remplacé A1 par C2 ? De toute façon cela n'a pas d'incidence, les cellules contiguës en B étant occupées, la région courante incluera A et B... ainsi que la ligne 1 qui n'est pas vide. On peut le cas échéant la redimensionner si cela devait aboutir à allonger le parcours sur une zone dépourvue de données... mais c'est vers le bas que cela pourrait se passer.
On affecte la zone de données à parcourir à un tableau : plus exactement (ce qu'il est utile de savoir pour utiliser la méthode), on affecte la plage à une variable de type Variant, ce qui produit un tableau à 2 dimensions dont les indices de départ sont 1.
En parcourant le tableau aa de 1 à UBound(aa) [indice le plus élevé dans la 1re dimension] on parcourt les lignes (ici on partira de 2 puisque la ligne 1 comporte des en-têtes).
Il est plus rapide de parcourir un tableau qu'une plage de cellule.
On teste la condition sur chaque ligne (Ah ! je vois que tu testes la 5e colonne et récupères la 3e !)
Si la condition est satisfaite, on redimensionne un tableau dynamique et on y affecte la valeur à prélever.
Détails : lst() déclarée ainsi déclare une variable tableau dynamique, c'est à dire non préalablement dimensionné et dont la dernière dimension pourra varier en conservant le contenu du tableau si on utilise le mot-clé Preserve.
n est déclarée comme variable de type Integer [% = As Integer]. Dès lors qu'une variable est déclarée, elle acquiert une valeur par défaut. Pour une variable numérique, cette valeur par défaut est naturellement 0.
Hors du cas spécifique de tableau résultant de l'affectation des valeurs d'une plage à une variable de type Variant (vu plus haut), les tableaux sont par défaut indicés à partir de 0 [on peut changer cela, mais je conseillerais de garder une façon de faire homogène pour éviter de se mélanger, ainsi si on n'indique pas d'indice mini, c'est 0, si on en indique un, c'est celui qu'on indique et que l'on voit donc...]
Note que l'on dimensionne le tableau à la valeur de la variable n, soit 0 au démarrage, et que l'on incrémente ensuite la variable pour le tour éventuel suivant...
Il s'ensuit que la valeur de n correspondra à tout moment au nombre d'éléments placés dans notre tableau.
Ce qui t"explique les cas distingués dans le Select Case... : 0 = rien à mettre dans la Listbox, 1 = un seul élément [on ne peut utiliser List pour affecter un seul élément, on utilise donc AddItem, et l'élément est celui d'indice 0 dans le tableau : lst(0)], Else = plusieurs éléments [on affecte donc le tableau lst en bloc à la propriété List de la ListBox].
Je crois qu'il n'y a plus rien à expliquer, sauf peut-être OLEObjects... Microsoft a pas mal compliqué la gestion des formes depuis l'origine, autrefois on couvrait tout avec DrawingObjects (il est vrai qu'il y en avait beaucoup moins), maintenant c'est Shapes (avec quelques particularités qui font que certaines n'y appartiennent qu'après leur création et non tant qu'elle est en cours...) Ce qu'il faut savoir c'est que les contrôles ActiveX appartiennent à une collection d'objets OLE lorsqu'ils sont placés sur une feuille, collection qui doit être invoquée pour accéder aux propriétés de contrôles de ces objets et en utilisant de surcroît le mot-clé Object : feuille.OLEObject("NomObjet").Object
En parallèle, lorsqu'il s'agit de contrôles de formulaires, on accède aux propriétés de contrôles par : feuille.Shapes("NomObjet").ControlFormat
Cordialement.
Bonjour,
Je ne m'attendais pas à une si belle explication, avant tout Merci beaucoup d'avoir pris de ton temps.
Pour ce qui est de Grandir, malgré le fait d'avoir déplacé ".clear" elle s'agrandit toujours en largeur.
Le soucis c'est que je ne peux plus sélectionner la listbox pour la supprimer. Elle est énorme en largeur à force et je ne peux pas la redimensionner...
CurrentRegion permet donc la création d'un "tableau" évolutif. C'est une commande très intéressante.
J'ai remplacé A1 par C2 car en ligne 1 j'ai une en-tête et les colonnes qui m’intéressaient c'était la C et la E. Donc la colonne A et B ne met pas utile.
Si j'ai bien compris, le fait d'avoir remplacé par C2 n'a servi a rien car ça prend tout de même en compte jusqu'en A1 étant donne que ce n'est pas vide ?
D'accord !! Tu dimensionne ton tableau donc (aa) puis tu lui dit ou il commence donc i=2 jusqu'à UBound (du tableau aa)
Si je comprend bien, Preserve permet d'enregistrer les contenues des colonnes 5 et 3 ?
Du coup à partir de "select case n" ne sont jamais sensé changer.. car ceci permet tous les cas. 0 éléments, 1 éléments ou encore plusieurs..
OLE est très clair je n'ai aucune question c'est bien compris !
Merci encore.
Du coup, en comprenant les lignes d'écriture je ne vois pas pourquoi ma listbox s'élargi à chaque fois que je click sur le bouton et qu'il y a de nouvelle valeur.
Un peut dans le même principe pour savoir si j'avais bien compris j'ai voulu essayer de faire quelque chose dans le même genre..
Ça ne fut malheureusement pas concluant.
Si tu peux me dire ce que j'ai fait de mal s'il te plait. ^^
Pour ce qui est de Grandir, malgré le fait d'avoir déplacé ".clear" elle s'agrandit toujours en largeur.
Le soucis c'est que je ne peux plus sélectionner la listbox pour la supprimer. Elle est énorme en largeur à force et je ne peux pas la redimensionner...
Bon concernant ce point j'ai réussi à avancer.
Grace à "Mode Création" je peux le redimensionner.
Néanmoins, dès qu'il y a un nouvel ajout dans la listbox de par elle même, elle s'agrandit en largeur mais également en hauteur..
Nouveau test sans résultat.
J'ai pourtant la sensation de ne pas être loin.. ^^
Concernant ma ListBox qui s'agrandit d'elle même à chaque nouveau ajout de Produit, je suis aller dans
"Format de Contrôle"
On peut dimensionner cette ListBox mais il n'y a pas un moyen de la fixer ?
Bon je me tape mon MonoLogue mais bon, j'ai toujours espoir que quelqu'un sache m'aider.
Je viens d'avoir une idée pour la ListBox au lieu d'une ListBox est-il possible de rentrer les produits en Cellule B15.
Ma cellule sera énorme mais ce n'est pas grave.
Sub Mail()
Dim aa, lst(), i%, n%
aa = Feuil2.Range("C2").CurrentRegion
For i = 2 To UBound(aa)
If aa(i, 5) = 5 Then
ReDim Preserve lst(n): lst(n) = aa(i, 3): n = n + 1
End If
Next i
With Feuil1.Range("B15")
.Clear
Select Case n
Case 0
Case 1: .AddItem lst(0)
Case Else: Feuil1.Range("B15") = lst
End Select
End With
End SubSeulement si j'ai plusieurs Produit = 5 ça ne m'en affiche qu'un seul en B15 tout de même...
Après ça peut me les afficher de A15 à D60...
Je croyais t'avoir répondu mais je ne vois pas ma réponse !
Place la propriété IntegralHeight sur False, et vois si elle grossit toujours.
Cordialement.
Je ne comprend pas Désolé..
j'ai essayé ceci:
Sub B_click()
Dim aa, lst(), i%, n%
aa = Feuil2.Range("C2").CurrentRegion
For i = 2 To UBound(aa)
If aa(i, 5) = 5 Then
ReDim Preserve lst(n): lst(n) = aa(i, 3): n = n + 1
End If
Next i
With Feuil1.OLEObjects("ListBox1.IntegralHeight").Object
.Clear
Select Case n
Case 0
Case 1: .AddItem lst(0)
Case Else: .List = lst
End Select
End With
End SubMais c'est pareil..
Que ne comprends-tu pas ?
Tu ouvres la fenêtre de propriétés des contrôles (ActiveX), tu sélectionnes ta ListBox (en mode Création).
Dans la fenêtre tu cherches la propriété IntegralHeight et tu passes sa valeur à False (elle prend une valeur True ou False).
Cordialement.
Ahah
Je suis vraiment débutant..
Ça fonctionne au TOP ça y est !!
Par contre, il n'est pas possible de sélectionner le produit à l'intérieur. C'est juste une "affiche" ?
J'en profite pour te demander concernant ce fichier:
Mon Principe de code est-il bon ? Le code provient du bouton "Valider" de l'userform
Private Sub CommandButton1_Click()
Dim aa, i%
aa = Feuil2.Range("A1").CurrentRegion
For i = 2 To UBound(aa)
If aa(i, 1) = TextBox1 And aa(i, 2) = TextBox2 Then
If Feuil2.Cells(i, 3) = "Première" Then
Feuil2.Range(i, 3) = 2
Else
If Feuil2.Cells(i, 3) = 1 Then
Feuil2.Range(i, 3) = 2
Else
If Feuil2.Cells(i, 3) = 2 Then
Feuil2.Range(i, 3) = 3
Else
If Feuil2.Cells(i, 3) = 3 Then
Feuil2.Range(i, 3) = 4
Else
If Feuil2.Cells(i, 3) = 4 Then
Feuil2.Range(i, 3) = 5
Else
If Feuil2.Cells(i, 3) = 5 Then
Feuil2.Range(i, 3) = 1
Else
MsgBox "Le Produit n'existe pas."
End If
End If
End If
End If
End If
End If
Else
End If
Next
Feuil2.Select
Unload Me
End SubPar contre, il n'est pas possible de sélectionner le produit à l'intérieur. C'est juste une "affiche" ?
Si tu places une liste dans un ListBox, tu peux sélectionner un élément, bien sûr, ou plusieurs si tu active la propriété Multiselect...
Pas le temps de regarder ton autre code maintenant, mais cela ne concerne plus la ListBox ?
C'est bon j'arrive à les sélectionner, j'aurai voulu les extraites mais je crois que je vais oublier l'idée ça m'agace d'être perdu..
Non l'autre code ne concerne plus la listBox c'était pour essayer de comprendre correctement les lignes d'écritures et être capable des les réutiliser surtout. Mais sans résultat ahah ^^
Mais en soit ça concerne un autre sujet certainement.
En tout cas merci bien pour ton aide !
Re,
J'ai regarde... Je ne vois pas bien l'intérêt de ce que tu veux faire, mais ça peut être utile pour voir comment améliorer...
D'abord, tu indenterais systématiquement ton code, il deviendrait plus facilement lisible et directement interprétable à la lecture :
Private Sub CommandButton1_Click()
Dim aa, i%
aa = Feuil2.Range("A1").CurrentRegion
For i = 2 To UBound(aa)
If aa(i, 1) = TextBox1 And aa(i, 2) = TextBox2 Then
If Feuil2.Cells(i, 3) = "Première" Then
Feuil2.Range(i, 3) = 2
Else
If Feuil2.Cells(i, 3) = 1 Then
Feuil2.Range(i, 3) = 2
Else
If Feuil2.Cells(i, 3) = 2 Then
Feuil2.Range(i, 3) = 3
Else
If Feuil2.Cells(i, 3) = 3 Then
Feuil2.Range(i, 3) = 4
Else
If Feuil2.Cells(i, 3) = 4 Then
Feuil2.Range(i, 3) = 5
Else
If Feuil2.Cells(i, 3) = 5 Then
Feuil2.Range(i, 3) = 1
Else
MsgBox "Le Produit n'existe pas."
End If
End If
End If
End If
End If
End If
Else
End If
Next
Feuil2.Select
Unload Me
End SubOn peut voir rapidement les défauts qu'il présente :
- Tu passes ta plage en tableau, très bien mais au lieu d'utiliser le tableau tu reviens à la feuille ! Ce qui n'est pas cohérent.
- Une cascade de If imbriqués ainsi, on évite !
Tu disposes de ElseIf pour les conditions alternatives, qui ne crée pas d'imbrications... Et quand on n'a pas besoin de Else, on ne l'utilise pas. - D'autre part une petite réflexion sur tes conditions t'aurait fait parvenir à un mode de calcul homogène évitant la plupart des If !
- Range attend une référence de plage fournie sous forme texte, type :
....Range("C2"). Il est toujours souhaitable de respecter la syntaxe. - TextBox1 : ainsi écrit on fait appel à la propriété par défaut du contrôle, cependant l'expérience montre que contrairement aux propriétés par défaut des objets Excel, VBA est moins sûr lorsqu'il s'agit de contrôles de ce type (qui ne sont pas des objets Excel). Il paraît donc préférable de préciser .Value ou .Text (équivalent pour une TextBox, l'un ou l'autre c'est question de goût).
En ce qui concerne l'autre TextBox, il ne faudra pas te gourer sur la frappe, car une comparaison d'égalité est sensible à la casse...
- Pas important mais je préfère que l'on me dise Next i plutôt que Next seul, car quand j'en ai plusieurs imbriquées, je vois plus facilement de laquelle il retourne... Et pour avoir l'habitude de faire d'une façon qui arrange, il faut faire de même systématiquement...
Mais voyons aussi au-delà de la procédure, il était plus simple d'utiliser des ComboBox pour lister les valeurs cherchées
Je reviens... Cordialement.
Etudie ce code :
Private Sub CommandButton1_Click()
Dim d As Date, p$, n%, i%
If ComboBox1.ListIndex >= 0 Then
p = Split(ComboBox1.Value, " - ")(0)
d = DateValue(Split(ComboBox1.Value, " - ")(1))
With Feuil2.Range("A1").CurrentRegion
For i = 2 To .Rows.Count
If .Cells(i, 1) = p And .Cells(i, 2) = d Then
n = IIf(.Cells(i, 3) = "Première", 1, .Cells(i, 3))
.Cells(i, 3) = n Mod 5 + 1
End If
Next i
End With
End If
Feuil2.Activate
Unload Me
End Sub
Private Sub UserForm_Initialize()
Dim d As Object, aa, k, i%
Set d = CreateObject("Scripting.Dictionary")
aa = Feuil2.Range("A1").CurrentRegion.Value
For i = 2 To UBound(aa)
k = aa(i, 1) & " - " & Format(aa(i, 2), "dd/mm/yyyy")
d(k) = ""
Next i
ComboBox1.List = d.keys
End SubCordialement.