3 or More Dependent Data Validation, with VBA, easy to set up

Akuini

Well-known Member
Joined
Feb 1, 2016
Messages
4,982
Office Version
  1. 365
Platform
  1. Windows
I want to share a macro to set up multi dependent data validation with vba. Some versions of dependent data validation use formulas to set them up, usually with indirect functions. For 2 or 3 dependent data validation & small data set, it's pretty easy to set it up, but for more than 3, it might be difficult to maintain as it requires lots of tables & lots of helper columns. This version uses vba, you only need 1 table, 1 helper column & 1 named range. The code is a bit complicated but easy to set up and maintain.

This is an example of 3 dependent data validation, with VBA. You can easily set up more than 3 dependent data validations as needed.
Notes:
1. You only need 1 table as data validation source, 1 helper column, 1 named range & 1 simple formula in data validation (ie =xName).
2. The columns where data validation reside may or may not be contiguous.
3. The list in the table may have duplicate, empty & unsorted, but the code will make the list in data validation unique, sorted & non-empty. The list is also dynamic, you can add more data as needed.
4. In the range with data validation, changing or deleting cell contents will delete cells in the next column with data validation.
5. But one caveat of using macro is when macro changes/writes something on sheet it will delete Undo Stack, so at that time you can't use UNDO. In this case it happens every time you put the cursor in a cell with data validation.

The File:

dhee - multiple data validation non adjacent column 2.jpg


The code:
VBA Code:
Option Explicit
'=================================================================================================
'=============== ADJUST THE CODE IN THIS PART: ===================================

'sheet's name where the list for data validation is located. [in the example: sheet "sheet2"]
Private Const sList As String = "sheet2"

'table's name where the list for data validation is located. [in the example: "Table1"]
Private Const sTable As String = "Table1"

'sDT & sDV must be in correct order (in this example 'STATE > CITY > REP).
'You can add number of columns as needed.
'Column number on the table "Table1": 'STATE > CITY > REP
Private Const sDT As String = "1,2,4"

'Column where data validation is located 'STATE > CITY > REP
Private Const sDV As String = "B:B,D:D,G:G"

'the helper column, first cell
Private Const xH As String = "H1"

'the name range as the source of data validation
Private Const xN As String = "xName"
'==================================================================================================
'==================================================================================================
Private xOld As String

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

If Target.Cells.CountLarge > 1 Then Exit Sub
    
If Not Intersect(Target, Range(sDV)) Is Nothing Then
    If isValid(Target) Then     'if activecell has data validation type 3
       If Target.Validation.Formula1 = "=" & xN Then 'its formula is "=xName"
       
       Dim d As Object, va, flag As Boolean, z, q, vb, x
       Dim i As Long, y As Long, w As Long
       
       Application.CutCopyMode = False 'prevent paste to the range with the DV
       xOld = Target.Value
       Set d = CreateObject("scripting.dictionary"):  d.CompareMode = vbTextCompare
       'columns with data validation:  sDV = "B:B,D:D,G:G"
       z = Application.Transpose(Application.Transpose(Split(sDV, ","))) ''create 1D array, variant/string type, Lbound = 1
       
       For i = 1 To UBound(z)
           If Target.Column = Range(z(i)).Column Then w = i: Exit For
       Next
  
       'reset xName to blank
'       ThisWorkbook.Names(xN).RefersTo = Sheets(sList).Range(xH)
       Sheets(sList).Range(xH).Name = xN  'blank cell

       If w > 1 Then 'if previous col with DV is empty then exit sub (with xName is blank)
           If ActiveSheet.Cells(Target.Row, z(w - 1)) = "" Then Exit Sub
       End If

          
           'Column number on the source table: sDT = "1,2,4"
            q = Evaluate("{" & sDT & "}") 'create 1D array, variant/double type, Lbound = 1
      
        'populate data from Table1,
        '"Application.Max(q)" is to limit the column range as needed for populating the list.
        va = Sheets(sList).ListObjects(sTable).DataBodyRange.Resize(, Application.Max(q)).Value
   
       For i = 1 To UBound(va, 1)
           flag = True
           
           If w = 1 Then 'if target is in first data validation column
               d(va(i, q(w))) = Empty
           Else
               'apply criteria from all previous column
               For y = 1 To w - 1
                   If UCase(va(i, q(y))) <> UCase(ActiveSheet.Cells(Target.Row, z(y))) Then flag = False: Exit For
               Next
               'if all criteria are met
               If flag = True Then d(va(i, q(w))) = Empty
           End If
       Next

            If d.Exists("") Then d.Remove ""
            If d.Count > 0 Then
                Dim c As Range
                Application.EnableEvents = False
                Application.ScreenUpdating = False
                    'populate d.keys to helper column & sort it
                    With Sheets(sList)
                        .Columns(.Range(xH).Column).ClearContents
                        Set c = .Range(xH).Resize(d.Count, 1).Offset(1)
                        c = Application.Transpose(Array(d.Keys))
                        c.Sort Key1:=c.Cells(1), Order1:=xlAscending, Header:=xlNo
                    End With
                   'populating range to xName
                    c.Name = xN
        
                Application.ScreenUpdating = True
                Application.EnableEvents = True
            End If
        End If
    End If
End If

End Sub

Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Cells.CountLarge > 1 Then Exit Sub
    
If Not Intersect(Target, Range(sDV)) Is Nothing Then
    
    If isValid(Target) Then     'if activecell has data validation type 3
       If Target.Validation.Formula1 = "=" & xN Then 'if its formula is "=xName"
            If xOld <> Target.Value Then
            
                Dim i As Long, w As Long, z
            
                Application.EnableEvents = False
                'columns with data validation:  "B:B,D:D,G:G"
                z = Application.Transpose(Application.Transpose(Split(sDV, ",")))
                
                For i = 1 To UBound(z)
                    If Target.Column = Range(z(i)).Column Then w = i: Exit For
                Next
                     
                    'if it's not the last column with DV then clear all next column with DV
                    If w < UBound(z) Then
                        For i = w + 1 To UBound(z)
                            ActiveSheet.Cells(Target.Row, Range(z(i)).Column) = ""
                        Next
                    End If
                Application.EnableEvents = True
            End If
        End If
    End If
End If
    
End Sub

Sub toEnableEvent()
Application.EnableEvents = True
End Sub

Function isValid(f As Range) As Boolean
    Dim v
    On Error Resume Next
        v = f.Validation.Type
    On Error GoTo 0
    isValid = v = 3
End Function
 
@Stenis
Ok, since you are using Excel 365 it is better & easier to use formula than vba.
I have created a 3 column data validation example, you can add more columns as needed.
Following are the criteria:
1. City & Contact depend on Country.
2. Contact does NOT depend on City.

Note:
This data validation is dynamic, you can add more data as needed, but you need to provide extra columns as needed on the right of each helper table, I've added 3 columns (along with the formula in row 4). These extra columns are needed if you are adding a new Country.

Stenis - dependent data validation 365 - 1.xlsx
ABCDEFGHIJKLMNO
1
2COUNTRYCITYCONTACT
3United StatesLos Angeles (CA)GriffinGermanyIndonesiaUnited StatesGermanyIndonesiaUnited States
4United StatesChicago (IL)RomanBERLINJakartaBoston (MA)   AriAkuiniAxl 
5United StatesSan Francisco (CA)ZacharyBonnChicago (IL)ArianDax
6United StatesPhiladelphia (PA)ZaynMünchenDallas (TX)BodeEmiliano
7United StatesMiami (FL)DaxHouston (TX)MazeGriffin
8United StatesDallas (TX)AxlLos Angeles (CA)RolandoHayes
9United StatesBoston (MA)HayesMiami (FL)ZachariahRoman
10United StatesHouston (TX)EmilianoPhiladelphia (PA)ZanderRuben
11United StatesWASHINGTON (DC)RubenSan Francisco (CA)Zachary
12GermanyBERLINAriWASHINGTON (DC)Zayn
13GermanyBonnRolando
14GermanyBonnArian
15GermanyBonnZander
16GermanyBonnBode
17GermanyMünchenZachariah
18GermanyMünchenMaze
19IndonesiaJakartaAkuini
20
Sheet1
Cell Formulas
RangeFormula
E3:G3,L3:N3E3=TRANSPOSE(SORT(UNIQUE(Table1[COUNTRY])))
E4:E6,G4:G12,F4,H4:J4E4=SORT(UNIQUE(FILTER(Table1[CITY],Table1[COUNTRY]=E3,"")))
L4:L10,N4:N12,M4,O4L4=SORT(UNIQUE(FILTER(Table1[CONTACT],Table1[COUNTRY]=L3,"")))
Dynamic array formulas.


Stenis - dependent data validation 365 - 1.xlsx
ABCD
1
2COUNTRYCITYCONTACT
3IndonesiaJakartaAkuini
4United StatesDallas (TX)
5
Sheet2
Cells with Data Validation
CellAllowCriteria
A3:A10List=Sheet1!$E$3#
B3:B10List=XLOOKUP($A3,Sheet1!$E$3:$J$3,Sheet1!$E$4:$J$4)#
C3:C10List=XLOOKUP($A3,Sheet1!$L$3:$Q$3,Sheet1!$L$4:$Q$4)#


Sample workbook:

I got this idea from this tutorial from Mynda Treacy from My Online Training Hub, credit to her:
Easy Dynamic Dependent Data Validation Two Ways
 
Upvote 0

Excel Facts

How to find 2nd largest value in a column?
MAX finds the largest value. =LARGE(A:A,2) will find the second largest. =SMALL(A:A,3) will find the third smallest
@Stenis
Ok, since you are using Excel 365 it is better & easier to use formula than vba.
I have created a 3 column data validation example, you can add more columns as needed.
Following are the criteria:
1. City & Contact depend on Country.
2. Contact does NOT depend on City.

Note:
This data validation is dynamic, you can add more data as needed, but you need to provide extra columns as needed on the right of each helper table, I've added 3 columns (along with the formula in row 4). These extra columns are needed if you are adding a new Country.

Stenis - dependent data validation 365 - 1.xlsx
ABCDEFGHIJKLMNO
1
2COUNTRYCITYCONTACT
3United StatesLos Angeles (CA)GriffinGermanyIndonesiaUnited StatesGermanyIndonesiaUnited States
4United StatesChicago (IL)RomanBERLINJakartaBoston (MA)   AriAkuiniAxl 
5United StatesSan Francisco (CA)ZacharyBonnChicago (IL)ArianDax
6United StatesPhiladelphia (PA)ZaynMünchenDallas (TX)BodeEmiliano
7United StatesMiami (FL)DaxHouston (TX)MazeGriffin
8United StatesDallas (TX)AxlLos Angeles (CA)RolandoHayes
9United StatesBoston (MA)HayesMiami (FL)ZachariahRoman
10United StatesHouston (TX)EmilianoPhiladelphia (PA)ZanderRuben
11United StatesWASHINGTON (DC)RubenSan Francisco (CA)Zachary
12GermanyBERLINAriWASHINGTON (DC)Zayn
13GermanyBonnRolando
14GermanyBonnArian
15GermanyBonnZander
16GermanyBonnBode
17GermanyMünchenZachariah
18GermanyMünchenMaze
19IndonesiaJakartaAkuini
20
Sheet1
Cell Formulas
RangeFormula
E3:G3,L3:N3E3=TRANSPOSE(SORT(UNIQUE(Table1[COUNTRY])))
E4:E6,G4:G12,F4,H4:J4E4=SORT(UNIQUE(FILTER(Table1[CITY],Table1[COUNTRY]=E3,"")))
L4:L10,N4:N12,M4,O4L4=SORT(UNIQUE(FILTER(Table1[CONTACT],Table1[COUNTRY]=L3,"")))
Dynamic array formulas.


Stenis - dependent data validation 365 - 1.xlsx
ABCD
1
2COUNTRYCITYCONTACT
3IndonesiaJakartaAkuini
4United StatesDallas (TX)
5
Sheet2
Cells with Data Validation
CellAllowCriteria
A3:A10List=Sheet1!$E$3#
B3:B10List=XLOOKUP($A3,Sheet1!$E$3:$J$3,Sheet1!$E$4:$J$4)#
C3:C10List=XLOOKUP($A3,Sheet1!$L$3:$Q$3,Sheet1!$L$4:$Q$4)#


Sample workbook:

I got this idea from this tutorial from Mynda Treacy from My Online Training Hub, credit to her:
Easy Dynamic Dependent Data Validation Two Ways
Wow, you´re amazing! Thank you so much for sharing your knowledge. You´re a true excel guru inspiration :D
I'll try to implement your solution to my file, I'll let you know how it goes.

Regards
Stenis
 
Upvote 0
That's a LOT of VB for what's a lot easier in the latest version of Excel.
Dependent_Drop_Down_EveryRow_XelPlus.xlsx
ABCDEFG
1Productivity DivGame DivUtility DivUtility DivCommuta
2WenCaLFightrrCommutaPerinoInfic
3BlendKryptisInficAccord
4VoltagePerinoAccordMisty Wash
5InklyFive LabsMisty WashTwenty20
6SleopsTwistrrTwenty20Tanox
7Kind ApeHackrrTanoxMinor Liar
8Pet FeedPesMinor LiarMosquit
9Right AppBadenMosquitAtmos
10MirrrrJellyfishAtmosScrap
11HalototAviatrrScrapMotocyco
12FlowrrrdeRamblrMotocycoAmplefio
13SilvrrArcadeAmplefioStrex
14DasringStrex
15Rehire
16Didactic
Sheet2
Cell Formulas
RangeFormula
G1:G13G1=INDEX((TableProd[Productivity Div],TableGame[Game Div],TableUtility[Utility Div]),,,MATCH($E$1,$A$1:$C$1,0))
Dynamic array formulas.
Named Ranges
NameRefers ToCells
myList=INDEX((TableProd[Productivity Div],TableGame[Game Div],TableUtility[Utility Div]),,,MATCH(Sheet2!$E$1,Sheet2!$A$1:$C$1,0))G1:G13
Cells with Data Validation
CellAllowCriteria
E1List=$A$1:$C$1
E2List=myList

Note that the 3 blue columns (A, B, and C) are three different tables. They are next to each other so that the formula in G1 works.
The Named Range MyList is the same formula as in G1.
This is not from me, it's from this Video on YouTube, complete with a link to the Blog post where the file can be downloaded.
I realize this is a long overdue post, but hopefully it will help someone with the same question and provide a much simpler answer.
 
Upvote 0
That's a LOT of VB for what's a lot easier in the latest version of Excel.

@jdellasala, thank you for contributing with different method to arrange dependent data validation.
But as I described in post #1, the reason why I use macro is this:
For 2 or 3 dependent data validation & small data set, it's pretty easy to set it up, but for more than 3, it might be difficult to maintain as it requires lots of tables & lots of helper columns. This version uses vba, you only need 1 table, 1 helper column & 1 named range. The code is a bit complicated but easy to set up and maintain.
I think the method you suggested is simpler for 2 level data validation but it's hard for 3 or more level & it's even harder if you have a long list. But I might be wrong, could you provide an example to set up 3 or more level data validation by using your method?
And also in post #21 I've shown a different method for 2 level data validation which is using the new function in Excel 365 and later.

Thank you, it's nice to see different ways to tackle a problem. (y)
 
Upvote 0
hi Akuini,
I would like to use rows instead of columns.
Meaning, the dependent drop-down lists for the data validation are located in the same column but in 3 rows.
Is there a way to rewrite "Column where data validation" to "Row where data validation".

appreciate the help and thanks for this useful macro! :)

'sDT & sDV must be in correct order (in this example 'STATE > CITY > REP).
'You can add number of columns as needed.
'Column number on the table "Table1": 'STATE > CITY > REP
Private Const sDT As String = "1,2,3"

'Column where data validation is located 'STATE > CITY > REP
Private Const sDV As String = "H2,H3,H4"
 
Upvote 0
hi Akuini,
I would like to use rows instead of columns.
Meaning, the dependent drop-down lists for the data validation are located in the same column but in 3 rows.
Is there a way to rewrite "Column where data validation" to "Row where data validation".
Sorry for the late reply, I'm kind of busy this week.
1. How many cell with data validation in each row? just one?
2. Since you're using Excel 365, are you interested in using only formula to set up 3 level dependent data-validation as you need?
In post #21 I shared the formula for 2 level dependent data-validation, if you want I can share the formula for 3 level dependent data-validation.
 
Upvote 0
Sorry for the late reply, I'm kind of busy this week.
1. How many cell with data validation in each row? just one?
2. Since you're using Excel 365, are you interested in using only formula to set up 3 level dependent data-validation as you need?
In post #21 I shared the formula for 2 level dependent data-validation, if you want I can share the formula for 3 level dependent data-validation.
hi akuini,
thanks for the tip. I have used the filter formulas and they work perfectly. :)
Thanks for always following-up :)
 
Upvote 0
Here's an example of 3 level dependent data-validation without VBA but using the new function in Excel 365.
The functions used are: SORT, UNIQUE, FILTER, XLOOKUP & TEXTSPLIT
Note: in the formula I'm using "|" as the separator, so if your data actually has "|" in it then change it to different unique character.

Put your data in an actual table as shown in the example.
This data validation is dynamic, you can add more data, but you need to provide extra columns as needed on the right of each helper table. These extra columns are needed if you plan to add new companies & cities. In this example the extra columns are column N:O & X:Y. To add new data, drag down the blue corner at the bottom of the table.

Base on this example you can amend the formula to set up more than 3 level dependent data-validation.

The idea to set up 2 level dependent data-validation came from this tutorial from Mynda Treacy from My Online Training Hub, credit to her:
Easy Dynamic Dependent Data Validation Two Ways
and I amended the formula in order to set up 3 level dependent data-validation, by adding TEXTSPLIT function.

Akuini - 3 level dependent data validation Excel 365.xlsx
ABCDEFGHI
1DATA
2COMPANYCITYCONTACT
3DATA VALIDATIONGEHoustonRolando
4COMPANYCITYCONTACTFordNYStephen
5ABCHoustonRolandGEChicagoHunter
6FordBostonBlazeGEChicagoRoland
7ABCChicagoRodney
8FordBostonMaze
9ABCHoustonRoland
10GEChicagoLochlan
11ABCNYParker
12FordBostonBlaze
13FordBostonAnson
14ABCNYSutton
15
Sheet1
Cells with Data Validation
CellAllowCriteria
A5:A12List=$K$4#
B5:B12List=XLOOKUP($A5,$K$4:$O$4,$K$5:$O$5)#
C5:C12List=XLOOKUP($A5&"|"&$B5,$Q$4:$X$4,$Q$7:$X$7)#


Akuini - 3 level dependent data validation Excel 365.xlsx
KLMNOPQRSTUVWXY
1
2HELPER TABLE, starting at K4
3
4ABCFordGEABC|ChicagoABC|HoustonABC|NYFord|BostonFord|NYGE|ChicagoGE|Houston
5ChicagoBostonChicago  ABCABCABCFordFordGEGE  
6HoustonNYHoustonChicagoHoustonNYBostonNYChicagoHouston
7NYRodneyRolandParkerAnsonStephenHunterRolando  
8SuttonBlazeLochlan
9MazeRoland
10
11
Sheet1
Cell Formulas
RangeFormula
K4:M4K4=TRANSPOSE(SORT(UNIQUE(Table1[COMPANY])))
Q4:W4Q4=TRANSPOSE(SORT(UNIQUE(CONCATENATE(Table1[COMPANY]&"|"&Table1[CITY]),FALSE,FALSE)))
K5:K7,N5:O5,L5:M6K5=SORT(UNIQUE(FILTER(Table1[CITY],Table1[COMPANY]=K4,"")))
X5:Y5,Q5:W6Q5=IFERROR(TEXTSPLIT(Q4,,"|",1),"")
Q7:R7,U7,W7:X7,V7:V9,T7:T9,S7:S8Q7=SORT(UNIQUE(FILTER(Table1[CONTACT],(Table1[COMPANY]=Q5)*(Table1[CITY]=Q6),"")))
Y7Y7=SORT(UNIQUE(FILTER(Table1[COMPANY],(Table1[CITY]=Y5)*(Table1[CONTACT]=Y6),"")))
Dynamic array formulas.


The workbook:
 
  • Like
Reactions: AOB
Upvote 0

Forum statistics

Threads
1,215,076
Messages
6,122,987
Members
449,093
Latest member
Mr Hughes

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