Se connecter avec
S'enregistrer | Connectez-vous

Filtrage de données listbox

Dernière réponse : dans Programmation

Me revoilà u_u


Bon, j'ai un nouveau problème excel, d'un autre genre il me semble mais tout aussi embêtant pour moi !

J'ai un listbox sur un userform qui récupère des données (une colonne) sur ma feuille de données. Le "problème" c'est que cette plage de données n'est jamais complètement remplie, de par sa finalité elle a bien plus de vide que de contenu !

Avec mon code actuel, je récupère tout ce vide dans ma listbox, ce qui donne un truc inutilisable au possible. Je n'arrive pas à masquer les cellules vides, en parcourant les forum il m'a semblé comprendre que c'était impossible dans un listbox ? :??: 

Bref, j'aimerais un coup de pouce pour m'aider soit à mettre en place un moyen de filtrage, soit un moyen de masquer ce vide, ou tout autre méthode qui me ferait arriver à mes fins !

Mon code actuel :

  1. Private Sub UserForm_Initialize()
  2.  
  3. Dim cell As Range
  4.  
  5. ListBox1.ColumnHeads = True
  6. For Each cell In Range("U2:U100")
  7. If cell.Value Then
  8. ListBox1.RowSource = "Feuil1!U2:U100"
  9.  
  10. End If
  11. Next
  12.  
  13. End Sub


Merci d'avance !

Autres pages sur : filtrage donnees listbox

Lassé par la pub ? Créez un compte

Meilleure solution

Bonjour !


Je viens avec des bonnes nouvelles pour moi, j'ai réussi à faire ce que je voulais ! \o/

Je mets ici le code propre et commenté, si jamais ça peut servir à quelqu'un ! Il fonctionne mais si vous voyez une erreur de convention ou une méthode un peu aléatoire, merci de me le signaler !

Ce code permet donc de créer une listbox par rapport à une plage de données dynamique dans un premier temps, puis de lier les autres données de la ligne excel à laquelle appartient la donnée sélectionnée dans la listbox dans des labels.

  1. Private Sub UserForm_Initialize()
  2. '
  3. 'LISTE DÉROULANTE
  4. '
  5. 'Déclaration des variables
  6. Dim cell As Range
  7. 'On vide la liste
  8. pdates.Clear
  9.  
  10. 'Boucle sur les dates de prochaine visite
  11. For Each cell In Range("U2:U100")
  12. 'Affichage de toutes les cellules <> 0 dans la liste déroulante
  13. If cell.Value <> "" Then
  14. pdates.AddItem cell.Value
  15. pdates.List(pdates.ListCount - 1, 1) = cell.Row
  16. End If
  17. Next
  18. End Sub


  1. Private Sub pdates_Click()
  2.  
  3. 'Déclaration des variables
  4. Dim IntCurrentRow As Variant
  5. Dim NuLigne As Integer
  6.  
  7. 'On lie chaque ligne de la listbox aux autres
  8. 'lignes correspondantes de la feuille de calcul
  9.  
  10. 'Boucle
  11. For IntCurrentRow = 0 To pdates.ListCount - 1
  12. If pdates.Selected(IntCurrentRow) Then
  13. NuLigne = IntCurrentRow
  14. Exit For
  15. End If
  16. Next IntCurrentRow
  17.  
  18. 'Affichage de l'entreprise dans le label correspondant
  19. Nom_Entreprise.Caption = cells(pdates.List(pdates.ListIndex, 1), 2)
  20.  
  21. 'Affichage de l'adresse dans le label correspondant
  22. Adresse_Entreprise.Caption = cells(pdates.List(pdates.ListIndex, 1), 3) & " " & vbCrLf & _
  23. cells(pdates.List(pdates.ListIndex, 1), 4) & " " & _
  24. cells(pdates.List(pdates.ListIndex, 1), 5)
  25.  
  26. 'Affichage des besoins dans le label
  27.  
  28. 'On exclue de l'affichage les cellules vides ou contenant la valeur 0
  29. 'pour les p1
  30. If cells(pdates.List(pdates.ListIndex, 1), 7) = "" _
  31. Or cells(pdates.List(pdates.ListIndex, 1), 7) = 0 _
  32. Then
  33. 'pour les p2
  34. If cells(pdates.List(pdates.ListIndex, 1), 8) = "" _
  35. Or cells(pdates.List(pdates.ListIndex, 1), 8) = 0 _
  36. Then
  37. 'pour les p3
  38. If cells(pdates.List(pdates.ListIndex, 1), 9) = "" _
  39. Or cells(pdates.List(pdates.ListIndex, 1), 9) = 0 _
  40. Then
  41. 'pour les p4
  42. If cells(pdates.List(pdates.ListIndex, 1), 10) = "" _
  43. Or cells(pdates.List(pdates.ListIndex, 1), 10) = 0 _
  44. Then
  45. 'pour les p5
  46. If cells(pdates.List(pdates.ListIndex, 1), 11) = "" _
  47. Or cells(pdates.List(pdates.ListIndex, 1), 11) = 0 _
  48. Then
  49. besoins.Caption = "Aucun"
  50. 'On affiche les besoins <> 0 dans le label correspondant
  51. Else: besoins.Caption = cells(pdates.List(pdates.ListIndex, 1), 11) & " " & "p5"
  52. End If
  53. Else: besoins.Caption = cells(pdates.List(pdates.ListIndex, 1), 10) & " " & "p4" & vbCrLf & _
  54. cells(pdates.List(pdates.ListIndex, 1), 11) & " " & "p5"
  55. End If
  56. Else: besoins.Caption = cells(pdates.List(pdates.ListIndex, 1), 9) & " " & "p3" & vbCrLf & _
  57. cells(pdates.List(pdates.ListIndex, 1), 10) & " " & "p4" & vbCrLf & _
  58. cells(pdates.List(pdates.ListIndex, 1), 11) & " " & "p5"
  59. End If
  60. Else: besoins.Caption = cells(pdates.List(pdates.ListIndex, 1), 8) & " " & "p2" & vbCrLf & _
  61. cells(pdates.List(pdates.ListIndex, 1), 9) & " " & "p3" & vbCrLf & _
  62. cells(pdates.List(pdates.ListIndex, 1), 10) & " " & "p4" & vbCrLf & _
  63. cells(pdates.List(pdates.ListIndex, 1), 11) & " " & "p5"
  64. End If
  65. Else: besoins.Caption = cells(pdates.List(pdates.ListIndex, 1), 7) & " " & "p1" & vbCrLf & _
  66. cells(pdates.List(pdates.ListIndex, 1), 8) & " " & "p2" & vbCrLf & _
  67. cells(pdates.List(pdates.ListIndex, 1), 9) & " " & "p3" & vbCrLf & _
  68. cells(pdates.List(pdates.ListIndex, 1), 10) & " " & "p4" & vbCrLf & _
  69. cells(pdates.List(pdates.ListIndex, 1), 11) & " " & "p5"
  70. End If
  71.  
  72.  
  73. End Sub




Avant de crier définitivement victoire, j'ai encore un petit contretemps, le dernier je pense. J'aimerais que les données de la listbox (ce sont des dates) soient triées par ordre croissant. Or, la propriété sorted n'existe malheureusement pas en vba d'après ce que j'ai compris, et je doute qu'un order by ne daigne fonctionner ! :lol: 
Une idée, une piste ?


En tous les cas merci beaucoup pour ton aide précieuse et ta disponibilité zeb, si toi ou un autre peut m'éclairer sur ce dernier point je lui en serai gré ! :) 
Expert Programmation

Salut,

Mais qu'est-ce que c'est que ça ?!

Le test de la ligne 7 ne sert à rien.
Et tu fais 99 fois la même chose !

RowSource n'accepte que des plages contiguës, donc s'il y a des "trous", ils seront visibles dans la liste.

Reprends ton For Each, ça, c'est bon, mets un vrai test à la ligne 7 et ligne 8, ajoute un par un les éléments différents de vide que tu trouves grâce à la méthode AddItem.

Pardon si je n'ai pas bien compris : tu me demandes d'ajouter les valeurs manuellement avec AddItem, mais il s'avère que ces données apparaissent dans la colonne "U" en fonction d'autres critères, ils ne sont pas fixes !

Je pense que j'ai raté un épisode là, parce qu'en relisant la définition de AddItem je sais pas vraiment quoi en faire :\
Expert Programmation

Si ces valeurs changent, ils faut les recharger à bon escient, toujours avec AddItem.

Comment ça tu n'as pas compris comment fonctionne AddItem ?!
  1. Dim cell As Range
  2.  
  3. ListBox1.Clear
  4. For Each cell In Range("U2:U100")
  5. If cell.Value <> "" Then
  6. ListBox1.AddItem cell.Value
  7. End If
  8. Next


Quoi de plus simple ?!

zeb a dit :
Si ces valeurs changent, ils faut les recharger à bon escient, toujours avec AddItem.

Comment ça tu n'as pas compris comment fonctionne AddItem ?!
  1. Dim cell As Range
  2.  
  3. ListBox1.Clear
  4. For Each cell In Range("U2:U100")
  5. If cell.Value <> "" Then
  6. ListBox1.AddItem cell.Value
  7. End If
  8. Next


Quoi de plus simple ?!




Mon dieu, je suis ridicule...

Désolé, j'ai un bouquin de vba excel sous la main mais les exemples qu'il donnait reprenaient de la saisie entre guillemets directement, donc j'ai pas percuté en effet :\

Merci de ton intervention, j'imagine bien pour quoi je passe quand tu me lis :lol: 


J'ai une nouvelle question en suite directe, donc je la pose ici même, j'espère que ça va relever le niveau !

J'ai des labels que j'aimerais remplir par rapport à la ligne que je sélectionne dans la listbox que j'ai créée, le problème pour moi étant que je ne peux pas m'inspirer de ce que tu viens de me donner puisque ces labels contiendront des données d'autres colonnes qui elles sont pleines.

Comment je peux faire pour dire que si je sélectionne la ligne x de ma listbox, alors les données y contenues dans la même ligne du tableur que la source de ma ligne de listbox devront aller dans le label z ?

J'espère que j'ai été clair, j'en ai pas l'impression...

Expert Programmation

Citation :
Mon dieu, ...
Désolé, ...
Merci ...
... relever le niveau !

Merci pour ton état d'esprit ;) 

Tu as été très clair.
Le modèle objet de VBA est un peu mal fini, alors il va falloir ruser. C'est assez Sioux, et donc très moche, mais on ne peut pas faire autrement.

  1. ' // Ajout d'une ligne dans la liste. Par défaut, à la fin.
  2. ListBox1.AddItem cell.Value
  3. ' // On récupère l'indice de la nouvelle ligne : la dernière donc.
  4. i = ListBox1.ListCount - 1
  5. ' // Une ligne est constituée de plusieurs colonnes, affichable par une liste multi-colonne.
  6. ' // Dans notre liste mono-colonne, on ne les verra pas, mais on pourra le récupérer au besoin
  7. ListBox1.List(i, 1) = cell.Row


En condensé :
  1. ListBox1.AddItem cell.Value
  2. ListBox1.List(ListBox1.ListCount - 1, 1) = cell.Row


En concentré :
  1. With ListBox1
  2. .AddItem cell.Value
  3. .List(.ListCount - 1, 1) = cell.Row
  4. En With


T'as tout compris ? Alors maintenant, c'est facile d'écrire dans ton label en récupérant cette valeur ;) 

Rebonjour !

Merci pour l'aide, j'ai retravaillé dessus et farfouillé un peu sur le net pour me dépêtrer, mais je crois m'être fourvoyé (rien que ça) !

Voilà où j'en suis du code :


nous avons notre première partie à l'initialisation :

  1. Private Sub UserForm_Initialize()
  2. Dim cell As Range
  3. ListBox1.Clear
  4. For Each cell In Range("U2:U100")
  5. If cell.Value <> "" Then
  6. ListBox1.AddItem cell.Value
  7. ListBox1.List(ListBox1.ListCount - 1, 1) = cell.Row
  8.  
  9. End If
  10. Next
  11.  
  12. End Sub


Et nous avons ce que j'ai bricolé par la suite :

  1. Private Sub ListBox1_Click()
  2.  
  3. For intCurrentRow = 0 To ListBox1.ListCount - 1
  4. If ListBox1.Selected(intCurrentRow) Then
  5. NuLigne = intCurrentRow
  6. Exit For
  7. End If
  8. Next intCurrentRow
  9.  
  10. Label7.Caption = ListBox1.Column(2, 1)
  11.  
  12. End Sub


Je pensais que les arguments de listbox1.column étaient modifiables, mais lorsque j'essaye de naviguer en abscisses et en ordonnées VBE ne m'offre que des erreurs d'objet ou de propriété null ! :lol: 

Je n'ai donc pas perçu la subtilité ? Ou c'est mon code qui ne ressemble à rien ?

Autre chose, je n'arrive pas à séparer chaque ligne de la listbox, il m'affiche la même valeur pour toute la listbox... je dois utiliser quelque chose comme "for each" ?

Merci d'avance !
Expert Programmation

Dis donc, t'es sûr qu'il ne manque pas un intCurrentRow quelque part à la ligne 10 ?

D'ailleurs, où est la déclaration de intCurrentRow ?
Aurais-tu oublié de mettre la directive Option Explicit dans ton code ?
Si tu as oublié, corrige-toi. Si tu ne veux pas, j'te cause plus.
Si tu ne sais pas ce que c'est ni à quoi ça sert, renseigne-toi !

Euh, et puis c'est quoi ces conventions de nommage Java en VB ?
[:diabolo]

J'aime beaucoup ton code pour recréer ListBox1.ListIndex.
Décidément, j'aime bien ton état d'esprit.
;) 

Relis la ligne 7 de mon code, puis la ligne 10 du tien. Je crois que ce n'est pas Column pour accéder aux colonnes.
:o 

Ces quelques éléments devraient te permettre de trouver tout seul, non ?

Solution:
Spoiler
Label7.Caption = ListBox1.List(ListBox1.ListIndex, 1)
Chercher par soi-même avant de lire la soluce !
Expert Programmation

Et non, pas moyen de trier facilement ta liste. En fait, ce n'est pas VBA qui pose problème, mais le composant Liste par défaut proposé par Excel. Ben oui, ils ont oublié la méthode Sort. C'est pas grave, tu peux le faire à la main.

Soit :
  • A l'établissement de ta liste.
    Relis l'aide de la méthode AddItem. T'as vu ? Il y a un paramètre pour dire à quelle place ajouter l'élément.

  • A posteriori.
    Un petit tri à bulle, sur ta liste et voilà !


    Bonjour,

    Le problème des tris sur la liste c'est que je veux garder la structure générale de mon tableau, je ne veux pas que tout soit retrié en fonction de cette date ! :\

    Du coup j'a fouiné un peu et j'ai sorti des combles de l'internet et de mes pensées profondes une double boucle avec variable de transition :

    1. 'pvdates est le nom de ma listbox
    2. 'Les déclarations sont faites au début de la procédure
    3. For x = 0 To pvdates.ListCount - 1
    4. For y = x To pvdates.ListCount - 1
    5. If pvdates.List(x) > pvdates.List(y) Then
    6. Valeur = pvdates.List(x)
    7. pvdates.List(x) = pvdates.List(y)
    8. pvdates.List(y) = Valeur
    9. End If
    10. Next
    11. Next


    Par contre mes données sont des dates (forme [jj/mm/aaaa]), et le tri ne marche que sur les jours ! :'( 
    J'ai beau déclarer x et y comme étant des dates, rien n'y fait !
    Je suppose que ce coup-ci je suis coincé avec cette méthode...

    Dans l'hypothèse où ce serait effectivement le cas, j'ai regardé les propriétés de AddITem, et notamment varIndex qui permet comme tu as dit zeb de spécifier la position d'insertion de l'élément. Ma plage de données est dynamique, et le champ varIndex n'aime pas trop les calculs ou les boucles à rallonge on dirait ; comment me débrouiller ?


    Décidément, c'est rageant d'arriver au bout et d'être retenu par ce genre de détails... grrrrr !


    Merci d'avance !
    Expert Programmation

    Eh, tu as oublié d'échanger les valeurs des autres colonnes !

    1. Dim x As Integer
    2. Dim y As Integer
    3. Dim i As Integer
    4. Dim Valeur As Variant
    5.  
    6. For x = 0 To pvdates.ListCount - 1
    7. For y = x To pvdates.ListCount - 1
    8. If CDate(pvdates.List(x, 0)) > CDate(pvdates.List(y, 0)) Then
    9. For i = 0 To 1
    10. Valeur = pvdates.List(x, i)
    11. pvdates.List(x, i) = pvdates.List(y, i)
    12. pvdates.List(y, i) = Valeur
    13. Next
    14. End If
    15. Next
    16. Next

    Pour caster ( = imposer un type à une variable, c'est du jargon neo-angliciste-informaticien-programmeur-en-C) en date, on utilise CDate. C'est tout.

    Alors, toujours grrrrrrrrrrrr ?

    Bonjour !

    Ça y est, c'est plus grrrrrrr du tout ! Merci beaucoup !
    J'ai donc découvert une nouvelle formule magique, le CDate :p 

    La question est donc réglée pour de bon ce coup-ci, j'attaque maintenant le programme suivant qui risque de vite me faire revenir dans les parages ! :lol: 


    Encore merci et à plus tard !
    Lassé par la pub ? Créez un compte