UserForm / Liaisons TextBox/Label/ListBox

Bonjour,

Je me permets de poster ici car je n'ai pas trouvé de solution sur internet.

Merci pour le temps que vous me consacrez.

J'utilise un UserForm. Mon problème est le suivant, j'ai :

  • Une TextBox
  • Un ListBox
  • Un Label

qui sont liés par vba.

Les liaisons sont comme suit :

Liaisons principales

TextBox_Change -> Aide à la sélection dans la liste (La liste est beaucoup plus grande dans le programme complet)

ListBox_Change -> Copie les éléments sélectionnés dans le label

Il y a d'autres liaisons pour valider les 2 exigences suivant ce que l'utilisateur fait

J'aimerai que lorsque je choisisse un champ, TextBox.Value="" et ListBox.List = Liste complète avec les éléments présents dans le label sélectionnés. (Sans supprimer des liaisons).

Par exemple : Lancr la macro / taper m dans la TextBox / sélectionner Mathématiques

(C'est réalisé par la combinaison des touches espace et delete dans la Textbox par l'utilisateur mais j'aimerai que ce soit automatisé.)

Le problème est que ListBox_Change s'appelle de façon récursive. Avec l'utilisation d'un booléen en variable globale, ce serait sensé marcher mais la ligne

  Me.ListBox1.List = v

de TextBox_Change ne s'éxécute pas correctement (pas du tout en fait mais sans faire d'erreur) ce qui bloque tout le code qui suit. Pour tester, enlever la lignes b=false de

Private Sub ListBox1_Change()
  If b Then
    b = False
    Me.TextBox1.Value = ""
    b = True
    UserForm_ActualiseL
    UserForm_ActualiseReverseL
  End If
End Sub

et éxécutez pas à pas.

J'ai pensé à utiliser une autre méthode : ListBox1_Click() mais elle ne marche apparemment pas pour les listes à choix multiples...

Auriez vous une solution à me proposer SVP.

163classeur2.xlsm (22.49 Ko)

Bonjour,

Le problème est que ListBox_Change s'appelle de façon récursive

Alors, utilises l'événement Click() de la ListBox plutôt que Change()

Bonjour

J'ai pensé à utiliser une autre méthode : ListBox1_Click() mais elle ne marche apparemment pas pour les listes à choix multiples...

Bonjour,

Testes si le TextBox est vide ou pas :

Private Sub TextBox1_Change()

    If b Then

        Dim Inc As Long, s As String

        If TextBox1.Text = "" Then Exit Sub '<--- ICI tester si vide ou pas !

        ' Initialiser l'incrément
        Inc = 0
        s = Me.TextBox1.Value
        Me.ListBox1.List = v          'Ligne qui fonctionne mais qui n'affecte pas l'affichage quand on enleve b=false

        '(ListBox.Selected(x) renvoie donc une erreur (basé sur l'affichage)
        'quand x dépasse l'indice le plus élévé affiché (fonction UserForm_ActualiseL)
        ' Pour chaque ligne
        If Not s = "" Then
            Do While Inc <= Me.ListBox1.ListCount - 1
                ' S'il n'existe pas de correspondance
                If Not UCase(Me.ListBox1.List(Inc)) Like "*" & UCase(s) & "*" Then
                    ' Supprimer la ligne de la combobox
                    Me.ListBox1.RemoveItem (Inc)
                Else                                        '''''''''''''''
                    ' Sinon incrémenter                     '   Partie    '
                    Inc = Inc + 1                           ' Suggestions '
                End If                                      '   ListBox1  '
            Loop                                            '''''''''''''''

            'Coche les cases en fonction du label1
            UserForm_ActualiseReverseL

        End If

    End If

End Sub

Bonjour,

Le fait de dupliquer le problème avec un if Textbox est vide et un else ne changera rien puisqu'il faudra tout de même modifier la liste et c'est sur ce point que ça bloque. La ligne

        Me.ListBox1.List = v

Surtout qu'il y a le if textbox est non vide dans le code que tu as copié.

Le problème est en gros que j'aimerai changer la liste de Listbox à l'intérieur de la méthode ListBox_Change ce qui n'est apparemment pas possible. Je ne peux pas utiliser ListBox_Click ya aucune solution du coup ?

Je rappelle que le but est que quand on sélectionne une ligne, la TextBox change de valeur et devient vide, la liste réapparaisse en entier en gardant cochée chaque ligne précédemment cochée. (label)

Bonjour,

Mets tout ton code actuel en commentaire et colles le code ci-dessous dans le module de la Form puis testes pour voir si le résultat correspond à tes attentes. Les commentaires sont dans le code mais si tu ne comprends pas quelque chose, reviens (ou si c'est moi qui est mal compris ta demande !) :

Dim Plage As Range
Dim Tbl() 'utilisation d'un tableau à deux dimensions (la 1 des Booléens et la 2 des chaines)
Dim Suspendre As Boolean

Private Sub UserForm_Initialize()

    Dim I As Integer

    Set Plage = Range("A1:A11")

    'quand on veux supprimer, par la suite, des éléments dans une ListBox, il est préférable de la charger avec AddItem
    For I = 1 To Plage.Count: ListBox1.AddItem Plage(I, 1).Value: Next I

    ReDim Tbl(1 To 2, 1 To ListBox1.ListCount)

    For I = 1 To UBound(Tbl, 2)

        Tbl(1, I) = False: Tbl(2, I) = Plage(I, 1).Value

    Next I

End Sub

Private Sub ListBox1_Change()

    Dim I As Integer
    Dim J As Integer

    'si l'appel vient de l'événement "Change()" du TextBox saute au mot fin
    If Suspendre = True Then GoTo Fin

    With ListBox1

        'si la liste est complète, mémorise l'état de chaque élément (coché ou non coché)
        If .ListCount = UBound(Tbl, 2) Then

            Tbl(1, .ListIndex + 1) = .Selected(.ListIndex)

        Else

            'dans le cas contraire (suppression dans la liste), effectue une recherche pour mémoriser l'état correspondant
            For I = 0 To ListBox1.ListCount - 1: For J = 1 To UBound(Tbl, 2)

                If Tbl(2, J) = ListBox1.List(I) Then Tbl(1, J) = ListBox1.Selected(I): Exit For

            Next J, I

        End If

    End With

'saut ici
Fin:

    'rempli le Label de toutes manières
    RemplirLabel

End Sub

Private Sub TextBox1_Change()

    Dim I As Integer
    Dim J As Integer

    ListBox1.Clear

    If TextBox1.Text <> "" Then

        For I = 1 To Plage.Count

            If UCase(Plage(I, 1)) Like "*" & UCase(TextBox1.Text) & "*" Then ListBox1.AddItem Plage(I, 1)

        Next I

    Else

        For I = 1 To Plage.Count: ListBox1.AddItem Plage(I, 1).Value: Next I

    End If

    'évite d'exécuter la procédure événementielle "Change()" de la ListBox...
    Suspendre = True

    'puis coche les éléments
    For I = 0 To ListBox1.ListCount - 1: For J = 1 To UBound(Tbl, 2)

        If Tbl(2, J) = ListBox1.List(I) And Tbl(1, J) = True Then ListBox1.Selected(I) = True

    Next J, I

    Suspendre = False

End Sub

Sub RemplirLabel()

    Dim I As Integer
    Dim J As Integer

    'vide tout d'abords...
    Label1.Caption = ""

    'puis concatène
    For I = 0 To ListBox1.ListCount - 1

        If ListBox1.Selected(I) = True Then Label1.Caption = Label1.Caption & ListBox1.List(I) & " - "

    Next I

    'si vide (tout à été décoché), fin !
    If Label1.Caption = "" Then Exit Sub

    'supprime le dernier tiret avec les deux espaces
    Label1.Caption = Left(Label1.Caption, Len(Label1.Caption) - 3)

End Sub

Bonjour,

Merci pour ta réponse.

Merci pour les améliorations que tu as apportées.

Ce n'est pas ce que je cherche mais l'utilisation du tableau Tbl en variable globale est une très bonne idée.

Je vais travailler là dessus et si j'arrive à avoir ce que je cherche, je le posterai.

Ce que je cherche c'est que lorsque l'on sélectionne un item dans la liste après avoir réduit la liste (en ayant écrit 1 caractère dans la text box par exemple), c'est que ça supprime le contenu de la text box et que la liste redevienne la plage A1:A11 avec les items précédemment sélectionnés (présents dans le label) sélectionnés.

Un problème qui n'était pas sur le classeur initial (je ne sais pas si tu pensais que c'était ça le problème) c'est que lorsqu'on sélectionne un item, puis réduit la liste et enfin resélectionne un item, le premier item sélectionné disparaît du label.

Théo

Bonjour,

Ce que je cherche c'est que lorsque l'on sélectionne un item dans la liste après avoir réduit la liste (en ayant écrit 1 caractère dans la text box par exemple), c'est que ça supprime le contenu de la text box et que la liste redevienne la plage A1:A11 avec les items précédemment sélectionnés (présents dans le label) sélectionnés.

Dans ce cas, il y a récursivité dans les événements "Change()" des deux objets et pour gérer ça, le code va devenir une usine à gaz alors que la suppression manuelle du caractère saisi dans le TextBox permet de faire ce que tu demandes (avec le code que je t'ai donné) à savoir afficher toute la liste en gardant les éléments sélectionnés !

D'accord,

C'est ça que je voulais savoir : si c'était possible à faire automatiquement.

J'en conclus donc que ce n'est pas possible.

Merci.

Théo

J'en conclus donc que ce n'est pas possible.

Non, c'est possible mais avec des variables interrupteur qui empêche les procédures "Change()" de se produire mais ça va alourdir et compliquer le code maintenant, si tu le veux vraiment, je peux me pencher dessus sachant toutes fois que je suis en congé ce soir et donc, moins devant le PC pour les 15 jours qui viennent !

Rechercher des sujets similaires à "userform liaisons textbox label listbox"