Moteur de recherche et barre de défilement d'une ListBox dans un UserForm

Bonsoir à toutes et tous,

Je travaille actuellement sur un outil qui intègre un formulaire permettant de paramétrer des requêtes pour extraire les données d'une API. Un des paramètres possibles est de choisir parmi une liste de sites géographiques un ou plusieurs éléments. Ils sont chargés dans une ListBox pour être ensuite sélectionné par l'utilisateur.

image

Le souci est qu'il y a plusieurs centaines de sites et donc que la navigation n'est pas évidente pour retrouver ceux que l'on souhaite. J'ai intégré un premier filtrage pour réduire les possibilités mais ce n'est pas forcément ce que je veux. L'idéal d'après moi serait d'avoir une TextBox permettant de rechercher le nom d'un site à partir d'une chaine de caractère saisie par l'utilisateur et d'afficher le premier résultat en haut de la ListBox en jouant sur la barre de défilement. Mieux encore, il pourrait passer aux résultats suivants en appuyant de nouveau sur la touche Entrée.

Je n'ai cependant aucune idée de comment jouer sur la position de la barre de défilement à partir d'un élément d'une ListBox (et c'est plutôt important pour réussir à faire ça). Est-ce que c'est possible d'après vous et, si oui, comment faire ?

Bonne soirée.

Bonjour,

Voici un essai avec un code adapté d'un problème similaire...

La première macro gère l'évènement change de la textbox1. A chaque changement, elle appelle (exécute) la seconde macro (à mettre dans un module normal de préférence) qui dépend de la nouvelle valeur de la textbox. L'opération de filtrage se fait grâce à l'opérateur like, assez simplement. Pour l'instant, on respecte la casse et on contraint la recherche sur une seule colonne (ici, la deuxième, définie en dur) de la base d'où sont tirées les infos de la listbox.

Il faudra adapter tous les noms d'objets pour qu'ils correspondent à ceux de votre projet.

Private sub textbox1_change()
Recherche textbox1.value, 2 '2 est la colonne de la base dans laquelle on recherchera le mot-clé (textbox1.value)
end sub

Sub Recherche(Motcle$, Colonne&)

With sheets("feuilledelabase").Range("BASE") '<<<adapter noms
    t = .Resize(, .Columns.Count).value
    ReDim tfiltre(1 To UBound(t, 2), 1 To UBound(t))
    For i = LBound(t) To UBound(t)
        If CStr(t(i, Colonne)) Like "*" & Motcle & "*" Then
            n = n + 1
            For j = LBound(t, 2) To UBound(t, 2)
                tfiltre(j, n) = t(i, j)
            Next j
        End If
    Next i
End With

With Userform1.Listbox1 '<<<< adapter noms
    .Clear
    If n > 0 Then
        .ColumnCount = UBound(t, 2)
        ReDim Preserve tfiltre(1 To UBound(t, 2), 1 To n)
        If n = 1 Then .Column = tfiltre Else .List = Application.Transpose(tfiltre)
    End If
End With

End Sub

Cdlt,

Merci de votre réponse.

Je voulais jouer sur la barre de défilement justement pour éviter d'avoir à réinitialiser la ListBox pour la recherche. Un cas possible est que l'utilisateur sélectionne un ou plusieurs sites puis en cherche un troisième grâce au moteur de recherche. A ce moment-là, les deux précédents doivent continuer à être mémorisés et, surtout, pouvoir être désélectionnés. Pareil si l'utilisateur efface tout contenu de la barre de recherche : tous les sites doivent réapparaître en resélectionnant les sites qui l'ont été.

Me conseillez-vous du coup de plutôt chercher une solution pour mémoriser les sites (dans une feuille Excel masquée par exemple) en parallèle pour gérer ces cas ?

Re,

Malheureusement, je n'y connais pas assez en ListBox pour faire mieux sans fichier...

Edit : Modification après essais

Voici un nouvel essai pour conserver la sélection malgré les filtres successifs :

''**************************************
'DANS LE MODULE DE L'USERFORM
'***************************************
Private Sub ListBox1_Change()
If Application.EnableEvents Then Set dico = MAJSELECTION
End Sub

Private Sub TextBox1_change()
Recherche TextBox1.Value, 3
End Sub

'***************************************
'DANS UN MODULE NORMAL
'***************************************
Public dico As Object

Sub Recherche(Motcle$, Colonne&)

If dico Is Nothing Then Set dico = CreateObject("Scripting.Dictionary")
t = Range("BASE").Value
ReDim tfiltre(1 To UBound(t, 2), 1 To UBound(t))
With UserForm1.ListBox1
    For i = LBound(t) To UBound(t)
        cle = ""
        For k = LBound(t, 2) To UBound(t, 2)
            cle = cle & "_" & t(i, k)
        Next k
        If CStr(t(i, Colonne)) Like "*" & Motcle & "*" Or dico.exists(cle) Then
            n = n + 1
            For j = LBound(t, 2) To UBound(t, 2)
                tfiltre(j, n) = t(i, j)
            Next j
        End If
    Next i
    .Clear
    If n > 0 Then
        .ColumnCount = UBound(t, 2)
        ReDim Preserve tfiltre(1 To UBound(t, 2), 1 To n)
        If n = 1 Then .Column = tfiltre Else .List = Application.Transpose(tfiltre)
        For j = 0 To .ListCount - 1
            cle = ""
            For k = .BoundColumn - 1 To .ColumnCount - 1
                cle = cle & "_" & .List(j, k)
            Next k
            If dico.exists(cle) Then
                Application.EnableEvents = False
                .Selected(j) = True
                Application.EnableEvents = True
            End If
        Next j
    End If
End With

End Sub

Function MAJSELECTION() As Object
Set temp = CreateObject("Scripting.Dictionary")
With UserForm1.ListBox1
    For j = 0 To .ListCount - 1
        cle = ""
        If .Selected(j) Then
            For k = .BoundColumn - 1 To .ColumnCount - 1
                cle = cle & "_" & .List(j, k)
            Next k
            temp(cle) = ""
        End If
    Next j
End With
Set MAJSELECTION = temp
End Function

C'est largement améliorable mais ça marche de mon côté.

Cdlt,

Ca marche parfaitement de mon côté aussi, merci beaucoup ! :) Je marque comme résolu

Bonne soirée,

Maxime

Rechercher des sujets similaires à "moteur recherche barre defilement listbox userform"