Résolu Filtrage de données listbox

  • Auteur de la discussion thierry234
  • Date de début

thierry234

Nouveau membre
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 :

Code:
Private Sub UserForm_Initialize()

Dim cell As Range

ListBox1.ColumnHeads = True
        For Each cell In Range("U2:U100")
            If cell.Value Then
                ListBox1.RowSource = "Feuil1!U2:U100"
            
            End If
        Next

End Sub

Merci d'avance !
 

zeb

Modérateur
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.
 

thierry234

Nouveau membre
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 :\
 

zeb

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

Comment ça tu n'as pas compris comment fonctionne AddItem ?!
Code:
Dim cell As Range

ListBox1.Clear
For Each cell In Range("U2:U100")
    If cell.Value <> "" Then
        ListBox1.AddItem cell.Value
    End If
Next

Quoi de plus simple ?!
 

thierry234

Nouveau membre




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...

 

zeb

Modérateur
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.

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

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

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

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

thierry234

Nouveau membre
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 :

Code:
Private Sub UserForm_Initialize()
Dim cell As Range
ListBox1.Clear
    For Each cell In Range("U2:U100")
        If cell.Value <> "" Then
            ListBox1.AddItem cell.Value
            ListBox1.List(ListBox1.ListCount - 1, 1) = cell.Row

        End If
    Next
    
End Sub

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

Code:
Private Sub ListBox1_Click()

For intCurrentRow = 0 To ListBox1.ListCount - 1
If ListBox1.Selected(intCurrentRow) Then
NuLigne = intCurrentRow
Exit For
End If
Next intCurrentRow

Label7.Caption = ListBox1.Column(2, 1)

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 !
 

zeb

Modérateur
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:
Label7.Caption = ListBox1.List(ListBox1.ListIndex, 1)
Chercher par soi-même avant de lire la soluce !
 

thierry234

Nouveau membre
Meilleure réponse
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.

Code:
Private Sub UserForm_Initialize()
'
'LISTE DÉROULANTE
'
'Déclaration des variables
Dim cell As Range
'On vide la liste
pdates.Clear

'Boucle sur les dates de prochaine visite
    For Each cell In Range("U2:U100")
        'Affichage de toutes les cellules <> 0 dans la liste déroulante
        If cell.Value <> "" Then
            pdates.AddItem cell.Value
            pdates.List(pdates.ListCount - 1, 1) = cell.Row
        End If
    Next
End Sub

Code:
Private Sub pdates_Click()

'Déclaration des variables
Dim IntCurrentRow As Variant
Dim NuLigne As Integer

'On lie chaque ligne de la listbox aux autres
'lignes correspondantes de la feuille de calcul

'Boucle
For IntCurrentRow = 0 To pdates.ListCount - 1
If pdates.Selected(IntCurrentRow) Then
NuLigne = IntCurrentRow
Exit For
End If
Next IntCurrentRow

'Affichage de l'entreprise dans le label correspondant
Nom_Entreprise.Caption = cells(pdates.List(pdates.ListIndex, 1), 2)

'Affichage de l'adresse dans le label correspondant
Adresse_Entreprise.Caption = cells(pdates.List(pdates.ListIndex, 1), 3) & "  " & vbCrLf & _
                             cells(pdates.List(pdates.ListIndex, 1), 4) & "  " & _
                             cells(pdates.List(pdates.ListIndex, 1), 5)

'Affichage des besoins dans le label

'On exclue de l'affichage les cellules vides ou contenant la valeur 0
'pour les p1
If cells(pdates.List(pdates.ListIndex, 1), 7) = "" _
Or cells(pdates.List(pdates.ListIndex, 1), 7) = 0 _
Then
    'pour les p2
    If cells(pdates.List(pdates.ListIndex, 1), 8) = "" _
    Or cells(pdates.List(pdates.ListIndex, 1), 8) = 0 _
    Then
        'pour les p3
        If cells(pdates.List(pdates.ListIndex, 1), 9) = "" _
        Or cells(pdates.List(pdates.ListIndex, 1), 9) = 0 _
        Then
            'pour les p4
            If cells(pdates.List(pdates.ListIndex, 1), 10) = "" _
            Or cells(pdates.List(pdates.ListIndex, 1), 10) = 0 _
            Then
                'pour les p5
                If cells(pdates.List(pdates.ListIndex, 1), 11) = "" _
                Or cells(pdates.List(pdates.ListIndex, 1), 11) = 0 _
                Then
                    besoins.Caption = "Aucun"
'On affiche les besoins <> 0 dans le label correspondant
                Else: besoins.Caption = cells(pdates.List(pdates.ListIndex, 1), 11) & "   " & "p5"
                End If
            Else: besoins.Caption = cells(pdates.List(pdates.ListIndex, 1), 10) & "   " & "p4" & vbCrLf & _
                                    cells(pdates.List(pdates.ListIndex, 1), 11) & "   " & "p5"
            End If
        Else: besoins.Caption = cells(pdates.List(pdates.ListIndex, 1), 9) & "   " & "p3" & vbCrLf & _
                                cells(pdates.List(pdates.ListIndex, 1), 10) & "   " & "p4" & vbCrLf & _
                                cells(pdates.List(pdates.ListIndex, 1), 11) & "   " & "p5"
        End If
    Else: besoins.Caption = cells(pdates.List(pdates.ListIndex, 1), 8) & "   " & "p2" & vbCrLf & _
                            cells(pdates.List(pdates.ListIndex, 1), 9) & "   " & "p3" & vbCrLf & _
                            cells(pdates.List(pdates.ListIndex, 1), 10) & "   " & "p4" & vbCrLf & _
                            cells(pdates.List(pdates.ListIndex, 1), 11) & "   " & "p5"
    End If
Else: besoins.Caption = cells(pdates.List(pdates.ListIndex, 1), 7) & "   " & "p1" & vbCrLf & _
                        cells(pdates.List(pdates.ListIndex, 1), 8) & "   " & "p2" & vbCrLf & _
                        cells(pdates.List(pdates.ListIndex, 1), 9) & "   " & "p3" & vbCrLf & _
                        cells(pdates.List(pdates.ListIndex, 1), 10) & "   " & "p4" & vbCrLf & _
                        cells(pdates.List(pdates.ListIndex, 1), 11) & "   " & "p5"
End If


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é ! :)
 

aprentizorrrr

Habitué
salut, tu peux essaye d'avoir ce resultat en utilisant l'enregistreur de macro, il m'a permit d'avoir le code général que j'ai modifier pour trier par ordre decroissant
 

zeb

Modérateur
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à !
 

thierry234

Nouveau membre
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 :

Code:
'pvdates est le nom de ma listbox
'Les déclarations sont faites au début de la procédure
For x  = 0 To pvdates.ListCount - 1
    For y = x To pvdates.ListCount - 1
        If pvdates.List(x) > pvdates.List(y) Then
            Valeur = pvdates.List(x)
            pvdates.List(x) = pvdates.List(y)
            pvdates.List(y) = Valeur
        End If
    Next
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 !
 

zeb

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

Code:
Dim x As Integer
Dim y As Integer
Dim i As Integer
Dim Valeur As Variant

For x = 0 To pvdates.ListCount - 1
    For y = x To pvdates.ListCount - 1
        If CDate(pvdates.List(x, 0)) > CDate(pvdates.List(y, 0)) Then
            For i = 0 To 1
                Valeur = pvdates.List(x, i)
                pvdates.List(x, i) = pvdates.List(y, i)
                pvdates.List(y, i) = Valeur
            Next
        End If
    Next
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 ?
 

thierry234

Nouveau membre
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 !
 
Vous devez vous inscrire ou vous connecter pour répondre ici.
Derniers messages publiés
Statistiques globales
Discussions
730 128
Messages
6 717 845
Membres
1 586 373
Dernier membre
https://forum.tomshardwar
Partager cette page
Haut