ComboBox en cascade

Bonjour,

J'aimerais faire une combobox en cascade dans un formulaire à partir de données d'une autre feuille. Est-ce possible?
J'ai un bouton "valider" à la fin du formulaire? Par conséquent, est-ce que je dois taper le code pour faire la combobox en cascade dans l'espace dédié au bouton valider?
Je donnerai plus d'information dès que je recevrais une réponse.
Merci d'avance

17 réponses

  1. Ok. Donc j'ai créé un formulaire pour faire l'inventaire d'achats d'ingrédients sur une année. Dans ce formulaire, on peut rentrer :
    -la date d'achat
    -le fournisseur (son numéro)
    -l'ingrédient
    -la quantité
    -le coût du transport
    Le fournisseur(numéro) et l'ingrédient sont en combobox.
    Il y a un bouton "valider" et un bouton "quitter" la fin.

    Sur une autre feuille, j'ai dans un tableau :
    -en colonne I le numéro du fournisseur
    -en colonne J son ingrédient
    Comme un fournisseur peut vendre plusieurs ingrédients, il y a plusieurs fois le même numéro de fournisseur en I.
    Aussi, comme un ingrédient peut avoir plusieurs fournisseurs, le même ingrédient peut être répété plusieurs fois en J mais avec des num de fournisseurs en I différents.

    Par conséquent, lors d'un achat, j'aimerais pouvoir d'abord choisir le fournisseur dans la 1ère combobox. Puis, dans la 2è combobox, j'aimerais que s'affichent SEULEMENT les ingrédients que ce fournisseur livre.

    Jusqu'à présent, je taper la majorité du code dans :Private Sub CmdValider_Click(). J'avais juste une petite partie à part pour le bouton "quitter". J'ai lu plusieurs tutos sur internet à propos des combobox en cascade, mais je n'arrive pas à les adapter à mon cas.

    Pouvez-vous m'aider s'il vous plait? J'espère que vous avez pu comprendre même si je sais que mes explications ne sont pas très claires.
    0
    1. Contributeur
      Bonjour,

      Voici un exemple:

      http://www.cjoint.com/data3/3CvossSb0GZ.htm
      0
      1. Merci pour votre réponse mais je ne parviens toujours pas à coder. De plus, il faudrait d'abord que quand je choisisse mon fournisseur, il ne soit pas proposé plusieurs fois. En effet, vu que dans mon tableau, les fournisseurs apparaissent plusieurs fois, c'est le cas aussi dans la combobox.
        Que faire?
        J'ai chercher plusieurs astuces sur internet : elles partent toutes de Private Sub Userform_Initialize(). Sauf qu'il n'apparaît nulle part dans mon code et quand je le tape il détecte une erreur de validation des données.
        0
        1. Voici mon code actuel :
          Private Sub CmdValider_Click()

          Dim ctrl As Control, ctrlerr As Control
          Dim erreur As Boolean

          For Each ctrl In frmAchats.Controls
          erreur = False
          If TypeOf ctrl Is MSForms.TextBox Then
          If ctrl.Text = "" Then
          erreur = True
          Set ctrlerr = ctrl
          Exit For
          End If
          End If
          Next ctrl

          If erreur = True Then
          MsgBox "Vous n'avez pas rempli toutes les zones"
          ctrlerr.SetFocus
          Set ctrlerr = Nothing
          Else

          If txtDateAchat.Value <> "" Then
          If Not IsDate(txtDateAchat.Value) Then
          MsgBox "Date incorrecte.", vbCritical + vbOKOnly, "Erreur"
          txtDateAchat.Value = ""
          txtDateAchat.SetFocus
          frmAchats.Hide
          frmAchats.Show

          Else
          txtDateAchat.Value = Format(txtDateAchat.Value, "dd/mm/yyyy")
          End If
          End If

          With frmAchats

          Dim nblig As Integer
          Dim nbcol As Integer
          nbcol = 1
          nblig = 9
          Do Until IsEmpty(Cells(nblig, nbcol))
          nblig = nblig + 1
          Loop

          Dim dernière_ligne As Integer
          dernière_ligne = Range("A1").End(xlDown).Row
          Dim TabAchats()
          ReDim TabAchats(dernière_ligne + 1, 0)

          feuille.Range("Achats!A" & nblig).Value = .txtDateAchat.Value
          feuille.Range("Achats!B" & nblig).Value = .ComboBoxIngrédientAchat.Value
          feuille.Range("Achats!D" & nblig).Value = .txtQuantité.Value
          feuille.Range("Achats!E" & nblig).Value = .ComboBoxFournisseur.Value
          feuille.Range("Achats!H" & nblig).Value = .txtCoûtTransport.Value

          End With
          frmAchats.Hide
          End If

          End Sub
          0
      2. Bonsoir à tous

        @Melissa
        Ce serait plus simple si au lieu de morceaux de codes tu envoyais un fichier complet comme demandé
        Ceci dit il te faut 2 macros :
        - l'une qui à l'initialisation de l'Userform alimente le 1er combo avec les fournisseurs à partir de la colonne I de ta feuille de donnée (que j'ai nommée BASE dans la macro)
        Private Sub UserForm_Initialize()
        '*** A INITIALISATION DE UF
        '**** ETABLIT LA LISTE DES ITEMS DE COMBOBOX1
            Dim j As Integer
            Dim Ligne As Long
            'derniere ligne rempli en colonne I de BASE
        Ligne = Sheets("BASE").Columns(9).Find("*", , , , xlByColumns, xlPrevious).Row
            'Récupère les données de la colonne Ide BASE
            For j = 2 To Ligne 'on commence en ligne 2 car titre
                ComboBox1 = Sheets("BASE").Range("I" & j)
                '...et filtre les doublons
                If ComboBox1.ListIndex = -1 Then ComboBox1.AddItem Sheets("BASE").Range("I" & j)
            Next j
        End Sub
        

        - l'autre qui à chaque modification de choix dans le Combobox 1 alimente le 2eme combo avec les ingrédients pris en colonne J si correspondance de fournisseur en colonne I . J'ai adaptée celle de Le Pivert (que je salue au passage) dans ce sens :
        Private Sub ComboBox1_Change()
        '*** A CHAQUE CHANGEMENT DE CHOIX DANS COMBOBOX1
        '*** ETABLIT LA LISTE DES ITEMS DE LA COMBOBOX2
        ' fournisseur choisi
        f = ComboBox1.Value
            NoAction = True
            ComboBox2.Clear
            Dim Ligne As Long
            'derniere ligne rempli en colonne Ide BASE
        Ligne = Sheets("BASE").Columns(9).Find("*", , , , xlByColumns, xlPrevious).Row
         'Boucle sur les lignes de BASE
            For i = 2 To Ligne
            ' si fournisseur choisi on ajoute l'ingredient de cette ligne à combobox2
            If Sheets("BASE").Range("I" & i) = f Then
                ComboBox2.AddItem Sheets("BASE").Range("J" & i)
                End If
            Next i
            
            ComboBox2.ListIndex = 0
            SendKeys "^(F4)"
            NoAction = False
          
        End Sub


        Dans l'editeur VBA Clic droit sur l'Userform dans l'arborescence et Code pour afficher la page où coller les macros (en les adaptant si nécessaire)

        Cdlmnt
        0
        1. Bonjour,

          Merci pour votre dévouement.
          J'ai essayé la première partie du code que vous avez posté en l'adaptant à mes données, ce qui donne :

          Private Sub UserForm_Initialize()

          '*** A INITIALISATION DE UF
          '**** ETABLIT LA LISTE DES ITEMS DE COMBOBOX1
          Dim j As Integer
          Dim Ligne As Long
          Dim ComboBoxFournisseur As Object
          Ligne = Sheets("Fournisseurs").Columns(9).Find("J4:J" & Range("J10000").End(xlUp).Row)
          'Récupère les données de la colonne Ide BASE
          For j = 1 To Ligne 'on commence en ligne 1 car titre en J3
          ComboBoxFournisseur = Sheets("Fournisseurs").Range("I" & j)
          '...et filtre les doublons
          If ComboBoxFournisseur.ListIndex = -1 Then ComboBoxFournisseur.AddItem Sheets("Fournisseurs").Range("I" & j)
          Next j

          End Sub

          MAIS il y a un problème : lorsque j'exécute, un message d'erreur s'affiche : "Erreur d'exécution '91': Variable objet ou variable de bloc With non définie". Je n'arrive pas à trouver ce qu'il manque dans le code, pouvez-vous m'aider ?
          0
          1. Contributeur
            Tu n'as pas bien recopier l'exemple de via 55. Ce n'est quand même pas trop compliqué!

            Private Sub UserForm_Initialize()
            Dim j As Integer
             Dim Ligne As Long
               'derniere ligne rempli en colonne I de Fournisseurs
            Ligne = Sheets("Fournisseurs").Columns(9).Find("*", , , , xlByColumns, xlPrevious).Row
             'Boucle sur les lignes de Fournisseurs
            For j = 2 To Ligne 'on commence en ligne 2 car titre en I1
             ComboBoxFournisseur = Sheets("Fournisseurs").Range("I" & j)
             '...et filtre les doublons
             If ComboBoxFournisseur.ListIndex = -1 Then ComboBoxFournisseur.AddItem Sheets("Fournisseurs").Range("I" & j)
             Next j
             ComboBoxFournisseur.ListIndex = 0
            End Sub
            


            On attend la suite!
            0
            1. Avec votre code, ça affiche : "erreur d'exécution '70':accès refusé"...
              0
              1. Non c'est bon! merci beaucoup, ça marche pour la première partie ! je vais tester la deuxième partie du code. Seulement, pour la première partie, j'aimerai rajouter une condition : ne pas prendre la case lorsqu'il y a marqué "Nom et Prénom"(titre de la colonne), mais aussi lorsqu'il y a marqué "Fournisseur inexistant". Est-il possible de rajouter du code pour ça ? Merci d'avance !!
                0
            2. Contributeur
              Pour supprimer les 2 items:

              Option Explicit
              Private Sub deleteitem(monnom As String)
              Dim i As Integer
              Dim nom As String
               For i = 0 To ComboBoxFournisseur.ListCount - 1
                nom = ComboBoxFournisseur.List(i)
              If nom = monnom Then
               ComboBoxFournisseur.removeitem (i)
              Exit Sub
              End If
                  Next i
              End Sub
              Private Sub UserForm_Initialize()
              Dim j As Integer
               Dim Ligne As Long
                 'derniere ligne rempli en colonne I de Fournisseurs
              Ligne = Sheets("Fournisseurs").Columns(9).Find("*", , , , xlByColumns, xlPrevious).Row
               'Boucle sur les lignes de Fournisseurs
              For j = 2 To Ligne 'on commence en ligne 2 car titre en I1
               ComboBoxFournisseur = Sheets("Fournisseurs").Range("I" & j)
               '...et filtre les doublons
               If ComboBoxFournisseur.ListIndex = -1 Then ComboBoxFournisseur.AddItem Sheets("Fournisseurs").Range("I" & j)
               Next j
               ComboBoxFournisseur.ListIndex = 0
               deleteitem ("Fournisseur inexistant")
              deleteitem ("Nom et Prénom")
              End Sub
              

              0
              1. Trop cool ça marche! Vous êtes un génie!
                Par contre, la 2ème partie du code ne fonctionne pas. J'ai essayé avec votre code, ça ne fonctionnait pas. Du coup, je l'ai modifié comme ceci :

                Private Sub ComboBoxFournisseur_Change()

                '*** A CHAQUE CHANGEMENT DE CHOIX DANS COMBOBOX1
                '*** ETABLIT LA LISTE DES ITEMS DE LA COMBOBOX2
                ' fournisseur choisi

                Dim f
                Dim i As Integer
                Dim NoAction As Action

                f = ComboBoxFournisseur.Value
                NoAction = True
                ComboBoxIngrédientAchat.Clear

                Dim Ligne As Long
                'derniere ligne rempli en colonne Ide BASE
                Ligne = Sheets("Fournisseurs").Columns(10).Find("*", , , , xlByColumns, xlPrevious).Row
                'Boucle sur les lignes de BASE
                For i = 4 To Ligne
                ' si fournisseur choisi on ajoute l'ingredient de cette ligne à combobox2
                If Sheets("Fournisseurs").Range("J" & i) = f Then
                ComboBoxIngrédientAchat.AddItem Sheets("Fournisseurs").Range("K" & i)
                End If
                Next i

                ComboBoxIngrédientAchat.ListIndex = 0
                SendKeys "^(F4)"
                NoAction = False

                End Sub

                mais il y a un problème au niveau de "NoAction=True)
                0
                1. Contributeur
                  Il faudrait quand même connaître les bases. La déclaration des variables.
                  NoAction = True
                  Quand une variable renvoie True ou False, c'est une variable Booleenne, il faut donc la déclarer en tant que tel. Et non pas la déclarer avec un nom fantaisiste:
                  Dim NoAction As Action

                  Un petit rappel:

                  https://silkyroad.developpez.com/VBA/LesVariables/
                  0
                  1. J'ai remplacé le code par:

                    Private Sub ComboBoxFournisseur_Change()

                    '*** A CHAQUE CHANGEMENT DE CHOIX DANS COMBOBOX1
                    '*** ETABLIT LA LISTE DES ITEMS DE LA COMBOBOX2
                    ' fournisseur choisi

                    Dim f
                    Dim i As Integer
                    Dim NoAction As Boolean

                    f = ComboBoxFournisseur.Value
                    NoAction = True
                    ComboBoxIngrédientAchat.Clear

                    Dim Ligne As Long
                    'derniere ligne rempli en colonne Ide BASE
                    Ligne = Sheets("Fournisseurs").Columns(10).Find("*", , , , xlByColumns, xlPrevious).Row
                    'Boucle sur les lignes de BASE
                    For i = 4 To Ligne
                    ' si fournisseur choisi on ajoute l'ingredient de cette ligne à combobox2
                    If Sheets("Fournisseurs").Range("J" & i) = f Then
                    ComboBoxIngrédientAchat.AddItem Sheets("Fournisseurs").Range("K" & i)
                    End If
                    Next i

                    ComboBoxIngrédientAchat.ListIndex = 0
                    SendKeys "^(F4)"
                    NoAction = False

                    End Sub

                    Mais il y a maintenant un problème au niveau de ComboBoxIngrédientAchat.Clear. Je reçois un message "erreur non répertoriée".
                    0
                    1. Contributeur
                      As-tu sur ton UserForm une comboBox nommée ComboBoxIngrédientAchat?

                      Attention aux accents.

                      Regarde l'exemple que je t'ai envoyé sur c-joint. En respectant les données dans les colonnes, tu arriveras à faire ce que tu veux. Il suffit de suivre, il y a très peu de code. Analyse bien cet exemple.

                      Avec ce code tu ajoutes un item seulement, je ne pense pas que ce soit ce que tu veux!
                      0
                      1. Ca ne fonctionne toujours pas. Mais tant pis. Merci beaucoup pour votre aide.
                        0
                        1. Bonjour

                          On t'as déjà demandé plusieurs fois de poster un exemple de ton fichier, tant qu'on ne l'aura pas on ne pourra pas t'aider plus !

                          Cdlmnt
                          0
                          1. Contributeur
                            Voilà un exemple adapter à ta feuille et tes combobox, il te suffit de changer les données:

                            http://www.cjoint.com/data3/3Cxsmrp1UDh.htm
                            0