How to approach the need for "nested" dropdowns (2nd dropdown depends on 1st dropdown value selected)

OaklandJim

Well-known Member
Joined
Nov 29, 2018
Messages
869
Office Version
  1. 365
Platform
  1. Windows
This is a classic. I have a list of insurance providers and a list of corresponding plan types for the providers, both in a sheet named Drug Plans. In another worksheet (named Drug Comparison) I have a data validation dropdown listing all providers (based on the values in the Drug Plans worksheet). When user selects a provider I need a second data validation that only lists the relevant plan types (based on the values in the Drug Plans worksheet) for the provider selected.

Providers are listed in a range named Providers (range B5:B24) and the plan types are listed in a range named Plans (range C5:C24), both in a sheet named Drug Plans.

es.xlsm
ABC
3
4ProviderPlan
51AnthemBasic
62AnthemPlus
73Blue ShieldPlus
84Blue ShieldEnhanced
95HumanaValue RX
106HumanaPremier
117SilverScriptsChoice
128WellcareValue Script
139WellcareClassic
1410WellcareValue Plus
1511CignaSaver Rx
1612CignaAssurance
1713CignaExtra
1814UHCPreferred
1915UHCSaver
2016
2117
2218
2319
2420
Drug Plans


Might you suggest an approach to setting up the second dropdown to include just the relevant plan type(s)?

Jim
 
Point your second dropdown to a list generated with a LOOKUP/FILTER function based on the value selected in the first dropdown. This secondary list can be hidden on a different sheet or far enough out of the way so it's not visible too if that is desired.
 
Upvote 0
I have several of these so I was hoping for a way to specify the array of plan types directly in the data validation Source field.

I wrote a simple UDF (below) that returns the array of plan types desired. But when I try to use the UDF with data validation (in Source field) an error is generated, something like a named range cannot be found. So, instead of feeding a named range into the function I use a cell reference. That generates the same error message even though I am not using a named range for the parameter.

VBA Code:
Option Explicit
Option Base 1

Function PlansList(psProvider As String) As Variant

    Dim rProviders As Range

    Dim rPlans As Range

    Dim rCell As Range

    Dim iPlanIndex As Long

    Dim iArrayIndex As Long

    Dim asPlansList() As String

    Set rProviders = [DrugPlans].Range("Providers")

    Set rPlans = [DrugPlans].Range("Plans")
    
    For Each rCell In rProviders

        iPlanIndex = iPlanIndex + 1

        If rCell.Value = psProvider _
         Then
            iArrayIndex = iArrayIndex + 1

            ReDim Preserve asPlansList(iArrayIndex)

            asPlansList(iArrayIndex) = rPlans.Cells(iPlanIndex)

        End If

    Next rCell
    
    PlansList = WorksheetFunction.Transpose(asPlansList())
    
End Function

I guess a UDF cannot be used for the Source in data validation?

Jim
 
Upvote 0
Not as the source, no. But you should be able to use the cell range where the UDF is returning its list as the source. I essentially suggested the same thing, but instead of a UDF, I suggested LOOKUP/FILTER to create the plan list. I've done this once or twice so I'm not sure what error you are getting when trying to use a cell reference. Could you try it with the cell reference and screen shot the error?
 
Upvote 0
First, I really appreciate the assistance. It means a lot to me.

The error occurred when I tried to use my UDF as the source for data validation.

Error_UseFormulaAsSource.png


If I use the UDF in the RefersTo range of a defined name and try to use the name in the Source field I get a different error.

Error_WithFunctionInRefersTo.png


I found another issue with the approach where I use my UDF (or your formula suggestion) to generate the list of plan types in a range of cells. The problem is that there is a variable number of possible values (plan types) for the the dropdown although I need to define the ranges so they are sized to contain the maximum number of plan types so sometimes I'll get a drop down (data validation) with blanks.

I guess that I need to go down the road of generating the Source list as a csv list for data validation source using vba and event handler. More work than I had hoped and not very satisfying.

Jim
 
Upvote 0
Potential fix: Try wrapping the named range in an indirect function . So =PlansList(INDEX(INDIRECT("Providers"),1)). I've had issues before with using named ranges in data validation formulas and this has fixed it in the past.
 
Upvote 0
Thanks for the reply. I had already gone down the road of using change event handler and a call to a sub to accomplish this. Maybe there is an Excel enhancement involving use of a function that returns an array.

VBA Code:
Option Explicit

Private Sub Worksheet_Change(ByVal Target As Range)

    Dim rProviders As Range

    Set rProviders = Me.Range("Providers")

'   The following code calls a sub that sets the data validation list for
'   the cell just below the changed cell, if the changed cell is a provider
'   name (i.e., changed cell is in the range named Providers that contains
'   the list of providers).
    If Not Application.Intersect(Target, rProviders) Is Nothing _
     Then
        Call FillPlanTypes(Target)
    End If
    
End Sub

VBA Code:
Option Explicit

' ----------------------------------------------------------------
' Procedure Name: FillPlanTypes
' Purpose: Fill plan types cell for cell below the one that contains provider name.
' Procedure Kind: Sub
' Procedure Access: Public
' Parameter rProviderCell (Range): The single celled range that is the Target from event handler.
' Author: Jim
' Date: 2/21/2025
' ----------------------------------------------------------------
Sub FillPlanTypes(ByVal rProviderCell As Range)

'   Array containg the list
    Dim avPlansList() As Variant

'   Holds csv list of plan types for the respective provider to specify
'   the list of plans for data validation.
    Dim sList As String
    
'   Used to access array elements.
    Dim iIndex As Long
    
    sList = ""

'   Use function PlansList to gather the plans list (for a provider)
'   and put the array returned into the local array variable.
    avPlansList = PlansList(rProviderCell.Value)

'   Loop all array elements.
    For iIndex = 1 To UBound(avPlansList)

'       Add the current plan type to the string containing the csv list
'       for data validation.
        sList = sList & avPlansList(iIndex)

'       Add comma if not the final plan type in the list.
        If iIndex < UBound(avPlansList) _
         Then
            sList = sList & ","
        End If

    Next

'   Must unprotect to change validation off to add data validation list.
    rProviderCell.Parent.Unprotect
    
'   Put list into the data validation dropdown for the respective plan types cell.
    With rProviderCell.Offset(1).Validation
        .Delete
        .Add Type:=xlValidateList, _
             AlertStyle:=xlValidAlertStop, _
             Operator:=xlBetween, _
             Formula1:=Trim(sList)
        .IgnoreBlank = True
        .InCellDropdown = True
        .InputTitle = ""
        .ErrorTitle = ""
        .InputMessage = ""
        .ErrorMessage = ""
        .ShowInput = True
        .ShowError = True
    End With
    
    rProviderCell.Parent.Protect UserInterfaceOnly:=True
    
End Sub
 
Upvote 0
Solution

Forum statistics

Threads
1,226,848
Messages
6,193,316
Members
453,790
Latest member
yassinosnoo1

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