Excel: How would I make a depleting dropdown list that shows only values that havent been chosen before?

Excel: Can I make a dropdown list that removes the dropdown's selected values from the dropdown list in future iterations & builds a list of previously used values?

List named "USERS" originally contains all available Users.  In my file, the selected user dropdown is used to populate dependent cells which can be verified or corrected.  When completed for that user, the data is copied to another worksheet & I'd pick the next user from the dropdown list.
I would like to have my list of users shrink as I complete the iterations & updates so that the users that I have completed wouldnt appear in my dropdown list, but would be added to the list of completed users.
Michael SpellmanSupervisory Operations Support SpecialistAsked:
Who is Participating?
Mike in ITIT System AdministratorCommented:
To do this I have used some VBA code. To start everything off you will need to add the following to a module in VBA:
Validate: you will have to run this before the others to create and fill the drop down. You might want to run this before copying the others into your module

Sub Validate()
Dim MyList() As String
Dim Users() As String
Dim cellNumber
Dim MyIndex

cellNumber = 6
'removes empty cells in the list of users
Range("B6:B" & Cells(Rows.Count, 2).End(xlUp).Row).Cells.SpecialCells(xlCellTypeBlanks).Delete shift:=xlUp
'counts how many users are left
n = Worksheets("Lists").Range("B6:B19").Cells.SpecialCells(xlCellTypeConstants).Count
ReDim MyList(n)
ReDim Users(n)
'Add user to the list of users MyList
For i = 0 To n Step 1
    MyList(i) = Replace(Range("B" & cellNumber).Value, ",", ";") 'had to change the "," to a ";" so that the list would work correctly
    Range("B" & cellNumber).Value = Replace(Range("B" & cellNumber).Value, ",", ";")
    cellNumber = cellNumber + 1
Next i
'add the MyList of users to the drop down
With Range("F6").Validation
    .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:=xlBetween, Formula1:=Join(MyList, ",")
End With

End Sub

Open in new window

Private Sub Worksheet_Change(ByVal Target As Range)
'This looks for a change in the worksheet and then runs the following code.
'You may need to update based on what you are working on.
Dim MyIndex
Dim Counted
Dim LastRow
If Target.Cells.Count > 1 Then Exit Sub
    On Error GoTo Whoa

    Application.EnableEvents = False 'turn events off so that you don't create an endless loop
    'count the number of users
    n = Worksheets("Lists").Range("B6:B19").Cells.SpecialCells(xlCellTypeConstants).Count
    MyIndex = ValListIndex("F6") 'find out where in the list is the selected user
    'move the selected user to the "Complete" list
    If MyIndex > 0 Then
        Range("B" & (5 + MyIndex)).Select
        LastRow = Cells(Rows.Count, 4).End(xlUp).Row
        Range("D" & (LastRow + 1)).Select
        Call Validate
    End If
    'Turn the event listener back on
    Application.EnableEvents = True
    Exit Sub
    MsgBox Err.Description
    Resume Letscontinue
End Sub

Open in new window

Public Function ValListIndex(ByVal Target As String) As Long
    ' Return the ListIndex of the value in Target
    ' Created by Sisyphus @ ExcelKey von Feb 21, 2012

    Dim Cell As Range
    Dim ValList As String
    Dim ValItem() As String
    Dim LiSep As String
    Dim i As Integer
    On Error GoTo ErrExit
    Set Cell = ActiveSheet.Range(Application.ConvertFormula _
                          (Target, xlA1, xlA1, xlAbsolute)). _
    ValList = Cell.Validation.Formula1
    If Len(ValList) = 0 Then GoTo ErrExit
    LiSep = Application.International(xlListSeparator)
    ValItem = Split(ValList, LiSep)
    For i = UBound(ValItem) To 0 Step -1
        If i >= LBound(ValItem) Then
            If ValItem(i) = Cell.Value Then Exit For
        End If
    Next i
    ValListIndex = i + 1
    Exit Function
    ValListIndex = -1
End Function

Open in new window

You will have to run the sub "Validate" first before you can do anything else as it creates the drop down and fills it. You may need to add a line like `Application.EnableEvents = False` in the beginning and then one that is `Application.EnableEvents = True` at the end so that you don't trigger the event listener, then comment them out once you've run it once. Then the drop down will be filled and selecting a name will move it to the "Completed_Users" column and out of the drop down.

This should be enough to get you started.
Put this code in the worksheet module:
Private Sub Worksheet_Change(ByVal Target As Range)
    Dim rng As Range
    If Not Intersect(Range("F2"), Target) Is Nothing Then
        With ActiveSheet.Range("B:B")
            Set rng = .Find(What:=Range("F2").Value, After:=.Cells(.Cells.Count), LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False)
        End With
        rng.Cut Destination:=Range("D" & ActiveSheet.Columns("D").Cells.Find("*", SearchOrder:=xlByRows, LookIn:=xlValues, SearchDirection:=xlPrevious).Row + 1)
    End If
End Sub

Open in new window

zorvek (Kevin Jones)ConsultantCommented:
Attached is a sample workbook illustrating how to create your depleting dropdown list without using VBA and using only formulas. The idea is to use a second worksheet that has three lists: a master list of names, a filtered list of names that have not been used, and a third list of those unused names in a condensed form. A named formula produces the final "range" that contains only the unused names without any blank entries.

Michael SpellmanSupervisory Operations Support SpecialistAuthor Commented:
Thanks very much.  This makes things much easier!
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.