ComboBox en cascade

melissa64 -  
cs_Le Pivert Messages postés 8437 Statut Contributeur -
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. melissa64
     
    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
  2. cs_Le Pivert Messages postés 8437 Statut Contributeur 730
     
    Bonjour,

    Voici un exemple:

    http://www.cjoint.com/data3/3CvossSb0GZ.htm
    0
  3. melissa64
     
    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. melissa64
       
      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
  4. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  5. via55 Messages postés 14393 Date d'inscription   Statut Membre Dernière intervention   2 759
     
    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
  6. melissa64
     
    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
  7. cs_Le Pivert Messages postés 8437 Statut Contributeur 730
     
    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
  8. melissa64
     
    Avec votre code, ça affiche : "erreur d'exécution '70':accès refusé"...
    0
    1. melissa64
       
      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
  9. cs_Le Pivert Messages postés 8437 Statut Contributeur 730
     
    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
  10. melissa64
     
    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
  11. cs_Le Pivert Messages postés 8437 Statut Contributeur 730
     
    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
  12. melissa64
     
    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
  13. cs_Le Pivert Messages postés 8437 Statut Contributeur 730
     
    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
  14. melissa64
     
    Ca ne fonctionne toujours pas. Mais tant pis. Merci beaucoup pour votre aide.
    0
  15. via55 Messages postés 14393 Date d'inscription   Statut Membre Dernière intervention   2 759
     
    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
  16. cs_Le Pivert Messages postés 8437 Statut Contributeur 730
     
    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