Excel VBA: Multi-level dependant lists ComboBoxes. some problem in extracting unique lists

talha_ansari

New Member
Joined
Jul 23, 2021
Messages
1
Office Version
  1. 2019
  2. 2016
Platform
  1. Windows
i have a file containing the sample userform of 3 sample combo boxes every next combobox is dependant to the previous.

there is a simple vba behind it, which i think should work correctly.

Option Explicit

Private Sub UserForm_Initialize()
' set worksheet
Dim sh As Worksheet
Set sh = Sheets("Clients")
'declare variable
Dim i As Long
For i = 2 To Application.WorksheetFunction.CountA(sh.Cells(1, 1).EntireColumn)
If Application.WorksheetFunction.CountIf(sh.Range("A2", "A" & i), sh.Cells(i, 1)) = 1 Then
Me.ComboBox1.AddItem sh.Cells(i, 1)
End If
Next i
End Sub
Private Sub ComboBox1_Change()
Me.ComboBox2.Clear

' set worksheet
Dim sh As Worksheet
Set sh = Sheets("Clients")
'declare variable
Dim i As Long
For i = 2 To Application.WorksheetFunction.CountA(sh.Cells(1, 1).EntireColumn)
If sh.Cells(i, 1) = Me.ComboBox1.Value And _
Application.WorksheetFunction.CountIf(sh.Range("B2", "B" & i), sh.Cells(i, 2)) = 1 Then

Me.ComboBox2.AddItem sh.Cells(i, 2)

End If
Next i


End Sub

Private Sub ComboBox2_Change()
Me.ComboBox3.Clear

' set worksheet
Dim sh As Worksheet
Set sh = Sheets("Clients")
'declare variable
Dim i As Long
For i = 2 To sh.Range("A10000").End(xlUp).Row
If sh.Cells(i, 1) = Me.ComboBox1.Value And sh.Cells(i, 2) = Me.ComboBox2.Value And _
Application.WorksheetFunction.CountIf(sh.Range("C2", "C" & i), sh.Cells(i, 3)) = 1 Then

Me.ComboBox3.AddItem sh.Cells(i, 3)

End If
Next i

End Sub


it does work for starting items but not for further. the issue is in
Application.WorksheetFunction.CountIf(sh.Range("B2", "B" & i), sh.Cells(i, 2)) = 1

as well as in
Application.WorksheetFunction.CountIf(sh.Range("C2", "C" & i), sh.Cells(i, 3)) = 1

when it try to get unique items for combobox list.

any solution please.


1627085628024.png


1627085685589.png
 
I tried added it on the end of the new code but get this error:

I want to be able to filter the table based on the selection from a ComboBox individually like "Source" combobox only

or with a combination of multiple selections from the ComboBoxes like "Source", "Name of Project", "Status" and "Client" etc.
That's a different problem, you need to start a new thread.
 
Upvote 0

Excel Facts

Who is Mr Spreadsheet?
Author John Walkenbach was Mr Spreadsheet until his retirement in June 2019.
You're welcome, glad to help & thanks for the feedback.:)
 
Upvote 0
@talha_ansari Welcome to the Forum

Here's an example of 3 dependent combobox in a userform.
Note:
1. Data must be in an actual table (not just in a range)
2. You only need to adjust the code in this part:
'====YOU MAY NEED TO ADJUST THE CODE IN THIS PART:====
'sheet's name where the list is located.
Private Const sList As String = "Sheet1"
'Table name where the list is located
Private Const tbl As String = "Table1"


The sample workbook:

The code
VBA Code:
Dim vList
Dim d As Object

'====YOU MAY NEED TO ADJUST THE CODE IN THIS PART:====
'sheet's name where the list  is located.
Private Const sList As String = "Sheet1"
'Table name where the list  is located
Private Const tbl As String = "Table1"


Private Sub UserForm_Initialize()
vList = Sheets(sList).ListObjects("Table1").DataBodyRange.Columns("A:C")
    Set d = CreateObject("scripting.dictionary")
    d.CompareMode = vbTextCompare
End Sub

Private Sub ComboBox1_Change()
       ComboBox2.Value = ""
       ComboBox3.Value = ""

End Sub

Private Sub ComboBox2_Change()
       ComboBox3.Value = ""

End Sub

Private Sub ComboBox1_DropButtonClick()
Dim i As Long
    d.RemoveAll
    For i = LBound(vList) To UBound(vList)
          d(vList(i, 1)) = Empty
    Next
       ComboBox1.List = d.keys
End Sub


Private Sub ComboBox2_DropButtonClick()
Dim i As Long
    d.RemoveAll
    For i = LBound(vList) To UBound(vList)
    If UCase(vList(i, 1)) = UCase(ComboBox1.Value) Then d(vList(i, 2)) = Empty
    Next
       ComboBox2.List = d.keys
End Sub

Private Sub ComboBox3_DropButtonClick()
Dim i As Long
    d.RemoveAll
    For i = LBound(vList) To UBound(vList)
        If UCase(vList(i, 1)) = UCase(ComboBox1.Value) And UCase(vList(i, 2)) = UCase(ComboBox2.Value) Then
            d(vList(i, 3)) = Empty
        End If
    Next
       ComboBox3.List = d.keys
End Sub
hi
I have just used your 3 depended combo, and it has been a major help. Thanks a lot.

My question is that in my case not ALL the possible options in combobox1 one, have a secondary list for combo2. So too, not all the possible selections in Combo 2 have a third list in combo 3. Is there a possiblity to adapt your software that if in the table an item appearing in coloumn 1 has nothing next to it in coloumn 2, then if that selection would be made in combo 1, combo 2 and three would automaticly be disabled. Same with combo 2?
 
Upvote 0
My question is that in my case not ALL the possible options in combobox1 one, have a secondary list for combo2. So too, not all the possible selections in Combo 2 have a third list in combo 3. Is there a possiblity to adapt your software that if in the table an item appearing in coloumn 1 has nothing next to it in coloumn 2, then if that selection would be made in combo 1, combo 2 and three would automaticly be disabled. Same with combo 2?

Ok, try this:


The code:
VBA Code:
Option Explicit
Dim vList
Dim d As Object

'====YOU MAY NEED TO ADJUST THE CODE IN THIS PART:====
'sheet's name where the list  is located.
Private Const sList As String = "Sheet1"
'Table name where the list  is located
Private Const tbl As String = "Table1"

Private Sub UserForm_Initialize()
vList = Sheets(sList).ListObjects("Table1").DataBodyRange.Columns("A:C")
    Set d = CreateObject("scripting.dictionary")
    d.CompareMode = vbTextCompare
End Sub

Private Sub ComboBox1_Change()
       ComboBox2.Value = ""
       ComboBox3.Value = ""

End Sub

Private Sub ComboBox2_Change()
       ComboBox3.Value = ""

End Sub

Private Sub ComboBox1_DropButtonClick()
Dim i As Long
    d.RemoveAll
    For i = LBound(vList) To UBound(vList)
          d(vList(i, 1)) = Empty
    Next
      If d.Exists("") Then d.Remove ""
       ComboBox1.List = d.keys
       ComboBox2.Enabled = True
       ComboBox3.Enabled = True
End Sub
Private Sub ComboBox2_Enter()
to_list_Cbo2
End Sub

Private Sub ComboBox2_DropButtonClick()
to_list_Cbo2
End Sub


Sub to_list_Cbo2()
Dim i As Long
    d.RemoveAll
    For i = LBound(vList) To UBound(vList)
    If UCase(vList(i, 1)) = UCase(ComboBox1.Value) Then d(vList(i, 2)) = Empty
    Next
       If d.Exists("") Then d.Remove ""
       With ComboBox2
        If d.Count = 0 Then
             .Clear
             .Enabled = False
        Else
             .List = d.keys
             ComboBox3.Enabled = True
        End If
       End With
End Sub

Private Sub ComboBox3_Enter()
to_list_Cbo3
End Sub

Private Sub ComboBox3_DropButtonClick()
to_list_Cbo3
End Sub


Sub to_list_Cbo3()
Dim i As Long
    d.RemoveAll
    For i = LBound(vList) To UBound(vList)
        If UCase(vList(i, 1)) = UCase(ComboBox1.Value) And UCase(vList(i, 2)) = UCase(ComboBox2.Value) Then
            d(vList(i, 3)) = Empty
        End If
    Next
       If d.Exists("") Then d.Remove ""
       With ComboBox3
            If d.Count = 0 Then
                 .Clear
                 .Enabled = False
            Else
                   .List = d.keys
            End If
       End With
End Sub
 
Upvote 1
Thank You again and again. You are a true excel master.

IF IT DOESN'T ENTAIL TO MUCH EFFORT ON YOUR PART, would it be possible to tweak the code, that whenever the combo boxes are disabled they are greyed out.
 
Upvote 0
would it be possible to tweak the code, that whenever the combo boxes are disabled they are greyed out.
Try this one:
VBA Code:
Option Explicit
Dim vList
Dim d As Object

Private Sub UserForm_Initialize()
vList = Sheets("Sheet1").ListObjects("Table1").DataBodyRange.Columns("A:C")
    Set d = CreateObject("scripting.dictionary")
    d.CompareMode = vbTextCompare
End Sub

Private Sub ComboBox1_Change()
       ComboBox2.Value = ""
       ComboBox3.Value = ""
       
       to_disable ("ComboBox2")
       to_disable ("ComboBox3")
       
       If ComboBox1.ListIndex > -1 Then to_list_Cbo2
 
End Sub

Private Sub ComboBox2_Change()
       ComboBox3.Value = ""
       to_disable ("ComboBox3")
       
       If ComboBox2.ListIndex > -1 Then to_list_Cbo3
End Sub

Private Sub ComboBox1_Enter()

Dim i As Long
    d.RemoveAll
    For i = LBound(vList) To UBound(vList)
          d(vList(i, 1)) = Empty
    Next
      If d.Exists("") Then d.Remove ""
       ComboBox1.List = d.keys
End Sub

Sub to_enable(cbo As String)
With Me.Controls(cbo)
    .Enabled = True
    .BackColor = vbWhite
End With
End Sub

Sub to_disable(cbo As String)
With Me.Controls(cbo)
    .Enabled = False
    .BackColor = 14277081
End With
End Sub

Sub to_list_Cbo2()
Dim i As Long
    d.RemoveAll
    
    For i = LBound(vList) To UBound(vList)
        If UCase(vList(i, 1)) = UCase(ComboBox1.Value) Then d(vList(i, 2)) = Empty
    Next
       If d.Exists("") Then d.Remove ""
       With ComboBox2
        If d.Count = 0 Then
            to_disable ("ComboBox2")
        Else
            to_enable ("ComboBox2")
            .List = d.keys
        End If
       End With
End Sub


Sub to_list_Cbo3()
Dim i As Long
    d.RemoveAll
    For i = LBound(vList) To UBound(vList)
        If UCase(vList(i, 1)) = UCase(ComboBox1.Value) And UCase(vList(i, 2)) = UCase(ComboBox2.Value) Then
            d(vList(i, 3)) = Empty
        End If
    Next
       If d.Exists("") Then d.Remove ""
       
        If d.Count = 0 Then
            to_disable ("ComboBox3")
        Else
             to_enable ("ComboBox3")
             ComboBox3.List = d.keys
        End If
       
End Sub
 
Upvote 1
Hi

Sorry for the delay.
It works beautifully. Thank You so Much
 
Upvote 0
You're welcome, glad to help & thanks for the feedback.:)
 
Upvote 0

Forum statistics

Threads
1,223,227
Messages
6,170,848
Members
452,361
Latest member
d3ad3y3

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top