Combobox en cascade avec saisie intuitive semie automatique

Bonjour à tous !

Je suis tout nouveau dans le monde du VBA, et je m'arrache les cheveux sur un petit problème

Mes connaissances en VBA sont encore très faible, mais j'ai réussi à bien avancer tout de même ^^

J'ai dans un classeur, plusieurs onglets contenant dans chacun d'eux une base de donnée relatifs aux prix d'entreprises différentes avec :

en A : Une catégorie de travaux

en B : La désignation des travaux

en C : Prix pour une zone 1

en D : Prix pour une zone 2

etc ...

Mon But pour l'instant est d'avoir une liste déroulante pour choisir l'entreprise (ça c'est fait)

Un liste déroulante pour choisir la région (C'est fait)

Un comboBox qui contient toutes les grandes catégories des travaux (la colone A des bases de données sans doublon) , relatif à l'entreprise choisit (C'est fait ! )

Pour ça j'ai créé une fonction matricielle pour créé une colonne "Catégorie sans doublon", maintenant je vois que c'est possible de le faire directement dans la ComboBox, je le ferais plus tard car cela fonctionne très bien pour le moment.

Avec saisie semi automatique et recherches des lettres nimporte où, pas juste en début de phrase.

Et la où je bloque :

Un ComboBox2 qui va, en fonction de l'entrerise choisi, et de la catégorie de travaux choisis, faire la liste des désignation des travaux possibles (Colone B lorsque colone A = Combobox1)

J'y suis presque arrivé, mais il y a un problème dès que j’essaie de mettre la saisie semie automatique !

Voici la code de la page au complet : (je suis VRAIMENT débutant, de quelques jours ^^, toutes remarques sera bien prise )

Dim a()
Dim b()

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  If Not Intersect(Range("Tableau7[Categorie]"), Target) Is Nothing And Target.Count = 1 Then

    If Cells(Target.Row, Target.Column - 2).Value = "Ent1" Then
    a = Application.Transpose(Sheets("Ent1").Range("Tableau16"))
    ElseIf Cells(Target.Row, Target.Column - 2).Value = "Ent2" Then
    a = Application.Transpose(Sheets("Ent2").Range("N1FMB"))
    ElseIf Cells(Target.Row, Target.Column - 2).Value = "Ent3" Then
    a = Application.Transpose(Sheets("Ent3").Range("Tableau5"))
    ElseIf Cells(Target.Row, Target.Column - 2).Value = "Ent4" Then
    a = Application.Transpose(Sheets("Ent4").Range("Tableau6"))
    Else
    Exit Sub
    End If

    Me.ComboBox1.List = a
    Me.ComboBox1.Height = Target.Height + 3
    Me.ComboBox1.Width = Target.Width
    Me.ComboBox1.Top = Target.Top
    Me.ComboBox1.Left = Target.Left
    Me.ComboBox1 = Target
    Me.ComboBox1.Visible = True
    Me.ComboBox1.Activate
    'Me.ComboBox1.DropDown ' ouverture automatique au clic dans la cellule
  Else
    Me.ComboBox1.Visible = False
  End If

    If Not Intersect(Range("Tableau7[Designation]"), Target) Is Nothing And Target.Count = 1 Then

    ComboBox2.Clear

    Dim FL1 As Range, NoCol As Integer
    Dim NoLig As Long, Var As Variant, Var2 As Variant
    Set FL1 = Sheets("Ent1").Range("Tableau11")
    NoCol = 1 'lecture de la colonne 1
    iii = 0
    jjj = 0
    For NoLig = 1 To Split(FL1.Address, "$")(4)
        Var = FL1.Cells(NoLig, NoCol)
        Var2 = FL1.Cells(NoLig, NoCol + 1)
        If Cells(Target.Row, Target.Column - 1) = Var Then
        ComboBox2.AddItem Var2
        End If
    Next

    Set FL1 = Nothing

    Me.ComboBox2.Height = Target.Height + 3
    Me.ComboBox2.Width = Target.Width
    Me.ComboBox2.Top = Target.Top
    Me.ComboBox2.Left = Target.Left
    Me.ComboBox2 = Target
    Me.ComboBox2.Visible = True
    Me.ComboBox2.Activate
    'Me.ComboBox1.DropDown ' ouverture automatique au clic dans la cellule
  Else
    Me.ComboBox2.Visible = False
  End If

End Sub

Private Sub ComboBox1_Change()
  If Me.ComboBox1 <> "" And IsError(Application.Match(Me.ComboBox1, a, 0)) Then
    Set d1 = CreateObject("Scripting.Dictionary")
    tmp = "*" & UCase(Me.ComboBox1) & "*"
    For Each c In a
      If UCase(c) Like tmp Then d1(c) = ""
    Next c
    Me.ComboBox1.List = d1.keys
    Me.ComboBox1.DropDown
  End If
  ActiveCell.Value = Me.ComboBox1
End Sub

Private Sub ComboBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
  Me.ComboBox1.List = a
  Me.ComboBox1.Activate
  Me.ComboBox1.DropDown
End Sub

Private Sub ComboBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
  If KeyCode = 13 Then ActiveCell.Offset(1).Select
End Sub

Private Sub ComboBox2_Change()
  If Me.ComboBox2 <> "" And IsError(Application.Match(Me.ComboBox2, Me.ComboBox2.List, 0)) Then
    Set d1 = CreateObject("Scripting.Dictionary")
    tmp = "*" & UCase(Me.ComboBox1) & "*"
    For Each c In Me.ComboBox2.List 
      If UCase(c) Like tmp Then d1(c) = ""
    Next c
    Me.ComboBox2.List = d1.keys
    Me.ComboBox2.DropDown
  End If
  ActiveCell.Value = Me.ComboBox2
End Sub

Private Sub ComboBox2_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
  Me.ComboBox2.Activate
  Me.ComboBox2.DropDown
End Sub

Private Sub ComboBox2_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
  If KeyCode = 13 Then ActiveCell.Offset(1).Select
End Sub

Voila Voila, je triture ça depuis un moment, mais j'ai toujours un bug avec

Private Sub ComboBox2_Change()

Je pense que c'est

Me.ComboBox2.List qui pose problème dans tout le Sub, mais je ne sais pas pourquoi.

Me.ComboBox2.List = d1.keys > autorisation denied

Soit j'arrive à afficher la bonne liste combobox2, mais la saisie auto ne fonctionne pas.

Soit j'arrive à la faire fonctionner, mais dès que je choisi un élément de la liste, ça plante

Je ,e pourrai répondre que ce soir

A+ !

Et merci !

Bonjour,

Exemple avec 3 niveaux intuitifs

Boisgontier

Merci pour ta réponse rapide !

En effet, dans le tableur en exemple, j'y arrive ^^

Mais le soucis est qu'il faut nommer chaque xsous-zones" ! Ma BD est bien trop grande pour cela :-/

D'où le fait que j'utilise une boucle For avec AddItem pour remplir ma combobox2, ce qui résous une partie du problème.

Mais du coup, je n'arrive pas à faire, comme dans ton exemple :

Choix2 = transpose.application (Range(xxx).Value)

Puisqu'il n'y a pas de range definit.

Je pense que le problème vient de la, mais je bloque :-/

Il ne faut pas utiliser AddItem qui est lent mais .List ou .Column

J'ai un pgm de recherche intuitif sur 36.000 communes.

http://boisgontierjacques.free.fr/fichiers/Formulaire/CommunesCP.zip

Boisgontier

Merci ,

J'ai modifié pas mal mon code, je n'utilise plus les .addItem ni les fonctions matricielles d'ailleurs pour supprimer les doublons

Il me reste un dernier (j’espère) bug lorsque j'utilise Application.Transpose, et que certaines cellules contiennent plus de 256 caractères.

D'ailleurs, j'ai eu un mal de chien à identifier le problème

Je vois que le sujet a été abordé à divers endroit sur internet, mais je n'arrive à faire fonctionner aucunes des solutions pour le moment, je continu de chercher ^^

Mais si quelqu'un a la solution, je suis preneur

Bonjour,

Si c'est Transpose qui est le problème,il suffit de ne pas l'utiliser.

Boisgontier

Bonjour Merwis, Bonjour Jacques Boisgontier,

A toutes fins utiles, une proposition qui compile certainement plusieurs codes prélevés à droite et à gauche, il doit y avoir un zeste puissant de JacquesBoigintier, du Quicksort, du Scripting.Dictionary, et du ListObjects (tableaux) ... donc rapide (charge le tableau d'un seul coup), supprime les doublons avec dico, et trie la liste

La présentation est un userform mais je pense avoir aussi travaillé directement sur la feuille excel comme JacquesBoigontier le propose.

L'autre version ... ce ne sont pas des combobox ici mais des listes de validation.

Const nbZones = 8

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim data() As Variant
Dim choix() As Variant
Dim dico As Object
Dim i&, iData&, iZone&, plus&

    If Target.Count <> 1 Then Exit Sub
    plus = Target.Row - 1
    If plus = 0 Then Exit Sub

    ReDim choix(1 To nbZones)
    For i = 1 To nbZones
        choix(i) = Range("zone" & i).Offset(plus, 0).Value
        If Not Intersect(Range("zone" & i).Offset(plus, 0), Target) Is Nothing Then
            data = [TabData].Value
            Set dico = CreateObject("Scripting.Dictionary")
            For iData = 1 To UBound(data)
                flag = True
                If i > 1 Then
                    For iZone = 1 To i - 1
                        If choix(iZone) <> CStr(data(iData, iZone)) Then flag = False
                    Next
                End If
                If flag Then dico(CStr(data(iData, i))) = ""
            Next iData
            If dico.Count > 0 Then
                Target.Validation.Delete
                Target.Validation.Add xlValidateList, Formula1:=Join(dico.keys, ",")
            End If
            Exit For
        End If
    Next i
End Sub

Private Sub Worksheet_Change(ByVal Target As Range)

    If Target.Count <> 1 Then Exit Sub
    plus = Target.Row - 1
    If plus = 0 Then Exit Sub

    For i = 1 To nbZones
        If Not Intersect(Range("zone" & i).Offset(plus, 0), Target) Is Nothing Then
            If i < nbZones Then
                Application.EnableEvents = False
                For iZone = i + 1 To nbZones
                    With Range("zone" & iZone).Offset(plus, 0)
                        .Value = ""
                        .Validation.Delete
                    End With
                Next
                Application.EnableEvents = True
            End If
            Exit For
        End If
    Next

End Sub

C'est complètement paramétré.

Le tableau de base doit s'appeler TabData

Une constante en début de macro définit le nombre de colonnes, ici 8

Les en-têtes de colonnes de la page dans laquelle s'affichent les listes déroulantes doivent s'appeler zone1, zone2 etc ...

Voir l'exemple ci-après

Et bonjour ^^

J'ai réglé le soucis avec le .transpose, enfin, je l'ai simplement esquivé en réduisant le nombre de caractères à moins de 255 par cellule

J'ai maintenant un beau "Erreur d’exécution 70 : Permission refusée"

avec une erreur sur Me.ComboBox2.List = d2.keys

Et cette fois je sèche complétement, le code semble correcte par rapport à tout ce que vous m'avez envoyé.

De plus, l'erreur se produit sur Me.ComboBox2.List = d2.keys mais pas sur Me.ComboBox1.List = d1.keys ... Bizarre

J'ai essayé de changer le nom des variables, au cas ou ... mais je ne vois pas :/

De plus, lorsque j'efface Me.ComboBox2.List = d2.keys (pour tester), on voit que la ComboBox2 se remplit bien avec les bons éléments (mais plus de recherche intuitive du coup)

Dim a()
Dim b()
Dim AddN1 As Range
Dim AddN2 As Range

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
  If Not Intersect(Range("Tableau7[Categorie]"), Target) Is Nothing And Target.Count = 1 Then

    If Cells(Target.Row, Target.Column - 2).Value = "ent1" Then
    Set AddN1 = Sheets("ent1").Range("Tableau11[N1]")

    ElseIf Cells(Target.Row, Target.Column - 2).Value = "ent2" Then
    Set AddN1 = Sheets("ent2").Range("Tableau1[N1]")

    ElseIf Cells(Target.Row, Target.Column - 2).Value = "ent3" Then
    Set AddN1 = Sheets("ent3").Range("Tableau3[N1]")

    ElseIf Cells(Target.Row, Target.Column - 2).Value = "ent4" Then
    Set AddN1 = Sheets("Ent4").Range("Tableau4[N1]")
    Else
    Exit Sub
    End If

     Set MonDico = CreateObject("Scripting.Dictionary")
 On Error Resume Next
  For Each C In AddN1
    If C <> "" Then
    MonDico.Add C.Value, C.Value
    End If
  Next C
  Tablo = Application.Transpose(MonDico.items)
    a = Tablo

    Me.ComboBox1.List = a
    Me.ComboBox1.Height = Target.Height + 3
    Me.ComboBox1.Width = Target.Width
    Me.ComboBox1.Top = Target.Top
    Me.ComboBox1.Left = Target.Left
    Me.ComboBox1 = Target
    Me.ComboBox1.Visible = True
    Me.ComboBox1.Activate
    'Me.ComboBox1.DropDown ' ouverture automatique au clic dans la cellule
  Else
    Me.ComboBox1.Visible = False
  End If

    If Not Intersect(Range("Tableau7[Designation]"), Target) Is Nothing And Target.Count = 1 Then

    If Cells(Target.Row, Target.Column - 3).Value = "ent1" Then
    Set AddN1 = Sheets("ent1").Range("Tableau11[N1]")

    ElseIf Cells(Target.Row, Target.Column - 3).Value = "ent2" Then
    Set AddN1 = Sheets("Fent2").Range("Tableau1[N1]")

    ElseIf Cells(Target.Row, Target.Column - 3).Value = "ent3" Then
    Set AddN1 = Sheets("ent3").Range("Tableau3[N1]")

    ElseIf Cells(Target.Row, Target.Column - 3).Value = "ent4" Then
    Set AddN1 = Sheets("ent4").Range("Tableau4[N1]")
    Else
    Exit Sub
    End If

     Set MonDico2 = CreateObject("Scripting.Dictionary")

  For Each C In AddN1
    If C.Value = Target.Offset(O, -1).Value Then
    MonDico2.Add C.Offset(0, 1).Value, C.Offset(0, 1).Value
    End If
  Next C

  Tablo = Application.Transpose(MonDico2.items)

    b = Tablo

    Me.ComboBox2.List = b
    Me.ComboBox2.Height = Target.Height + 3
    Me.ComboBox2.Width = Target.Width
    Me.ComboBox2.Top = Target.Top
    Me.ComboBox2.Left = Target.Left
    Me.ComboBox2 = Target
    Me.ComboBox2.Visible = True
    Me.ComboBox2.Activate

  Else
    Me.ComboBox2.Visible = False
    End If

End Sub
Private Sub ComboBox1_Change()
  If Me.ComboBox1 <> "" And IsError(Application.Match(Me.ComboBox1, a, 0)) Then
    Set d1 = CreateObject("Scripting.Dictionary")
    tmp = "*" & UCase(Me.ComboBox1) & "*"
    For Each C In a
      If UCase(C) Like tmp Then d1(C) = ""
    Next C
    Me.ComboBox1.List = d1.keys
    Me.ComboBox1.DropDown
  End If
  ActiveCell.Value = Me.ComboBox1
End Sub
Private Sub ComboBox1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
  Me.ComboBox1.List = a
  Me.ComboBox1.Activate
  Me.ComboBox1.DropDown
End Sub

Private Sub ComboBox2_Change()
  If Me.ComboBox2 <> "" Then
    Set d2 = CreateObject("Scripting.Dictionary")
    cle = "*" & UCase(Me.ComboBox2) & "*"
    For Each C In b
      If UCase(C) Like cle Then d2(C.Value) = ""
    Next C
   Me.ComboBox2.List = d2.keys
    Me.ComboBox2.DropDown
  End If
  ActiveCell.Value = Me.ComboBox2
End Sub
Private Sub ComboBox2_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
  Me.ComboBox2.List = b
  Me.ComboBox2.Activate
  Me.ComboBox2.DropDown
End Sub

Bonjour,

Quelqu'un aurrait une idée de ce qui pourrait causer "Erreur d’exécution 70 : Permission refusée" ?

Même juste une piste, je tourne en rond

Je peux poster le fichier Excel en question si besoin

MonDico.Add C.Value, C.Value

Essaie plutôt :

MonDico(C.Value)=""

sinon prend le code que je t'ai proposé...

Rechercher des sujets similaires à "combobox cascade saisie intuitive semie automatique"