Create a drop down list containing only unique distinct alphabetically sorted text values using excel array formula
Question:
How do I create a drop down list with unique distinct alphabetically sorted values?
Answer:
Table of contents
Sort values using array formula
Array formula in cell B2
How to create an array formula
- Select cell B2
- Type above array formula
- Press and hold Ctrl + Shift
- Press Enter once
- Release all keys
How to copy array formula
- Select cell B2
- Copy (Ctrl + c)
- Select cell range B3:B6
- Paste (Ctrl + v)
Explaining array formula in cell B2
=INDEX(List, MATCH(0, IF(MAX(NOT(COUNTIF($B$1:B1, List))*(COUNTIF(List, ">"&List)+1))=(COUNTIF(List, ">"&List)+1), 0, 1), 0))
Step 1 - Convert text to numbers
=INDEX(List, MATCH(0, IF(MAX(NOT(COUNTIF($B$1:B1, List))*(COUNTIF(List, ">"&List)+1))=(COUNTIF(List, ">"&List)+1), 0, 1), 0))
COUNTIF(range,criteria) counts the number of cells within a range that meet the given condition
COUNTIF(List, ">"&List)+1
becomes
COUNTIF({"DD";"EE";"FF";"EE";"GG";"BB";"FF";"GG";"DD";"TT";"FF";"VV";"VV";"FF"}, ">"&{"DD";"EE";"FF";"EE";"GG";"BB";"FF";"GG";"DD";"TT";"FF";"VV";"VV";"FF"})+1
becomes
{11;9;5;9;3;13;5;3;11;2;5;0;0;5}+1
becomes
{12;10;6;10;4;14;6;4;12;3;6;1;1;6}
Step 2 - Identify previous unique text values above current cell
=INDEX(List, MATCH(0, IF(MAX(NOT(COUNTIF($B$1:B1, List))*(COUNTIF(List, ">"&List)+1))=(COUNTIF(List, ">"&List)+1), 0, 1), 0))
COUNTIF(range,criteria) counts the number of cells within a range that meet the given condition
NOT(COUNTIF($B$1:B1, List))
becomes
NOT(COUNTIF("Unique list sorted alpabetically", {"DD";"EE";"FF";"EE";"GG";"BB";"FF";"GG";"DD";"TT";"FF";"VV";"VV";"FF"}))
becomes
NOT({0;0;0;0;0;0;0;0;0;0;0;0;0;0})
becomes
{1;1;1;1;1;1;1;1;1;1;1;1;1;1}
Step 3 - Calculate maximum number in array
=INDEX(List, MATCH(0, IF(MAX(NOT(COUNTIF($B$1:B1, List))*(COUNTIF(List, ">"&List)+1))=(COUNTIF(List, ">"&List)+1), 0, 1), 0))
MAX(NOT(COUNTIF($B$1:B1, List))*(COUNTIF(List, ">"&List)+1))
becomes
MAX({1;1;1;1;1;1;1;1;1;1;1;1;1;1}*({12;10;6;10;4;14;6;4;12;3;6;1;1;6})
and returns 14.
Step 4 - Convert maximum number into Boolean value
=INDEX(List, MATCH(0, IF(MAX(NOT(COUNTIF($B$1:B1, List))*(COUNTIF(List, ">"&List)+1))=(COUNTIF(List, ">"&List)+1), 0, 1), 0))
IF(MAX(NOT(COUNTIF($B$1:B1, List))*(COUNTIF(List, ">"&List)+1))=(COUNTIF(List, ">"&List)+1), 0, 1)
becomes
IF(14={12;10;6;10;4;14;6;4;12;3;6;1;1;6}, 0, 1)
and returns this array:
{1;1;1;1;1;0;1;1;1;1;1;1;1;1}
Step 4 - Return the relative position of an item in an array
=INDEX(List, MATCH(0, IF(MAX(NOT(COUNTIF($B$1:B1, List))*(COUNTIF(List, ">"&List)+1))=(COUNTIF(List, ">"&List)+1), 0, 1), 0))
MATCH(lookup_value;lookup_array; [match_type]) returns the relative position of an item in an array that matches a specified value
MATCH(0, IF(MAX(NOT(COUNTIF($B$1:B1, List))*(COUNTIF(List, ">"&List)+1))=(COUNTIF(List, ">"&List)+1), 0, 1), 0)
becomes
MATCH(0, {1;1;1;1;1;0;1;1;1;1;1;1;1;1}, 0)
and returns value 6.
Step 5 - Return a value of the cell at the intersection of a particular row and column
INDEX(array,row_num,[column_num]) returns a value or reference of the cell at the intersection of a particular row and column, in a given range
=INDEX(List, MATCH(0, IF(MAX(NOT(COUNTIF($B$1:B1, List))*(COUNTIF(List, ">"&List)+1))=(COUNTIF(List, ">"&List)+1), 0, 1), 0))
becomes
=INDEX(List, 6)
becomes
=INDEX({"DD";"EE";"FF";"EE";"GG";"BB";"FF";"GG";"DD";"TT";"FF";"VV";"VV";"FF"}, 6)
and returns value BB.
Create a dynamic named range
- Click "Formulas" tab
- Click "Name Manager"
- Click List
- Type =OFFSET(Sheet1!$A$2, 0, 0, COUNT(IF(Sheet1!$A$2:$A$1000="", "", 1)), 1) in "Refers to:" field.
- Click "Close" button
Named range
List (dynamic)
What is named ranges?
How to create a drop down list with values updated dynamically in excel 2007
- Click Data tab
- Click Data validation button
- Click "Data validation..."
- Select List in the "Allow:" window. See picture below.
- Type =OFFSET($B$2, 0, 0, COUNT(IF($B$2:$B$1000="", "", 1)), 1) in the "Source:" window
- Click OK!
Download example workbook
Create-a-drop-down-list-containing-only-unique.xls
(Excel 97-2003 Workbook *.xls)
Functions in this article:
IF(logical_test;[value_if:true];[value_if_false])
Checks whether a condition is met, and returns one value if TRUE, and another value if FALSE
INDEX(array,row_num,[column_num])
Returns a value or reference of the cell at the intersection of a particular row and column, in a given range
SMALL(array,k) returns the k-th smallest row number in this data set.
ROW(reference) returns the rownumber of a reference
MATCH(lookup_value;lookup_array; [match_type])
Returns the relative position of an item in an array that matches a specified value
COUNTIF(range,criteria)
Counts the number of cells within a range that meet the given condition
COUNT(value1;[value2])
Counts the number of cells in a range that contain numbers
OFFSET(reference,rows,cols, [height],[width])
Returns a reference to a range that is a given number of rows and columns from a given reference
Sort values using vba
Array formula in cell B2:B8000:
How to create array formula
- Select cell range B2:B8000
- Type array formula above
- Press and hold Ctrl + Shift
- Press Enter once
- Release all keys
VBA code
You can find the selectionsort function here: Using a Visual Basic Macro to Sort Arrays in Microsoft Excel
Function FilterUniqueSort(rng As Range)
Dim ucoll As New Collection, Value As Variant, temp() As Variant
ReDim temp(0)
On Error Resume Next
For Each Value In rng
If Len(Value) > 0 Then ucoll.Add Value, CStr(Value)
Next Value
On Error GoTo 0
For Each Value In ucoll
temp(UBound(temp)) = Value
ReDim Preserve temp(UBound(temp) + 1)
Next Value
ReDim Preserve temp(UBound(temp) - 1)
SelectionSort temp
FilterUniqueSort = Application.Transpose(temp)
End Function
Function SelectionSort(TempArray As Variant)
Dim MaxVal As Variant
Dim MaxIndex As Integer
Dim i, j As Integer
' Step through the elements in the array starting with the
' last element in the array.
For i = UBound(TempArray) To 0 Step -1
' Set MaxVal to the element in the array and save the
' index of this element as MaxIndex.
MaxVal = TempArray(i)
MaxIndex = i
' Loop through the remaining elements to see if any is
' larger than MaxVal. If it is then set this element
' to be the new MaxVal.
For j = 0 To i
If TempArray(j) > MaxVal Then
MaxVal = TempArray(j)
MaxIndex = j
End If
Next j
' If the index of the largest element is not i, then
' exchange this element with element i.
If MaxIndex < i Then
TempArray(MaxIndex) = TempArray(i)
TempArray(i) = MaxVal
End If
Next i
End FunctionWhere to copy vba code?
- Press Alt + F11
- Insert a module into your workbook
- Copy (Ctrl + c) above code into the code window
Download excel 97-2003 *,xls file
Create-a-drop-down-list-containing-only-unique_vba.xls
Related blog posts
- Create unique distinct list sorted based on text length using array formula in excel
- Create a drop down list containing alphabetically sorted values in excel
- Create a unique distinct alphabetically sorted list, extracted from a column in excel
- Unique distinct list from a column sorted A to Z using array formula in excel
- Filter unique distinct list sorted based on sum of adjacent values using array formula in excel











December 10th, 2009 at 3:30 am
I encountered an issue when using Excel 2007 where upon saving the workbook as an Excel Workbook (not 97-2003) the embedded count(if( ...)) formula causes only the first item in the drop down list to appear. This only happens upon opening the workbook and if you select data validation on the cell the issue is resolved. However, upon saving and reopening the problem reappears. The only workaround if to either remove the function or keep the workbook in 97-2003 format.
December 15th, 2009 at 8:47 pm
Josh, thanks for bringing this to my attention. I´ll try to solve this issue.
March 26th, 2010 at 10:29 pm
I want the drop down box to be on a different worksheet. But EXCEL won't allow OFFSET without having it all on one worksheet.
Is there some other way to have the lists on one sheet, get unique values and sort them, then reference them from a drop down on another worksheet? To make matter more fun, I need the ranges to be dynamic as the user may be adding new records.
Thanks!
Dianne
April 9th, 2010 at 1:55 pm
I have re-created the above formula but would like to create a range that is larger than the current data so that the unique list picks up all new data. Currently my unique list repeats the last line of data several times because the range name extends beyond it. Can this be done?
Thanks
Keels
April 9th, 2010 at 8:18 pm
Dianne,
I want the drop down box to be on a different worksheet. But EXCEL won't allow OFFSET without having it all on one worksheet.
It is not OFFSET, it is Data Validation that won´t allow having it all on one worksheet.
But there is a workaround, if you create another named range (for example, named unique) and type =OFFSET(Sheet1!$B$2, 0, 0, COUNT(IF(Sheet1!$B$2:$B$1000="", "", 1)), 1).
Create a drop down box on another sheet and type =unique in "source:"
To make matter more fun, I need the ranges to be dynamic as the user may be adding new records.
I have updated the post, the named range is now dynamic.
April 9th, 2010 at 8:35 pm
Keels,
I have re-created the above formula but would like to create a range that is larger than the current data so that the unique list picks up all new data. Currently my unique list repeats the last line of data several times because the range name extends beyond it. Can this be done?
I have updated this post, the named range is now dynamic.
March 15th, 2011 at 4:21 pm
This is almost exactly what I have been looking for. The only shortcoming is that I need it to work with spaces (empty cells) in the source list and able to handle a source list that is only one item. I want the person to begin to fill out a column (the source list) filling in names and as they go they can instead pick from a drop down menu so they do not have to type the name (and so the name is always the same). When they type the first name in, it does not appear in the list. Only when they type the second name, then both names appear. Can this be fixed? They are allowed to skip rows filling out the table, so handling blank cells is important too. Thank you.
March 17th, 2011 at 9:36 am
Peter,
Array formula to remove blanks in blog post example:
=INDEX(List, MATCH(0, IF(MAX((COUNTIF($B$1:B1, $A$2:$A$15)=0)*(($A$2:$A$15<>"")*(COUNTIF($A$2:$A$15, ">"&$A$2:$A$15)+1)))=(IF(($A$2:$A$15<>""), COUNTIF($A$2:$A$15, ">"&$A$2:$A$15)+1, "")), 0, ""), 0)) + CTRL + SHIFT + ENTER
I dont´t understand this:
I want the person to begin to fill out a column (the source list) filling in names and as they go they can instead pick from a drop down menu so they do not have to type the name (and so the name is always the same). When they type the first name in, it does not appear in the list. Only when they type the second name, then both names appear. Can this be fixed?
March 17th, 2011 at 8:42 pm
That revised formula worked perfectly. It solved both the problem with spaces interspersed in the source list and the diminutive situation with only one item in the source list (yielding a one item menu). I can't see any reason someone would not prefer this revised equation over the original. I would update your example above to use this formula instead.
As for my explanation as to what I am doing..... sorry that was clear as mud....
I want a column of data entry cells on a form that allows either free form text entry or a dynamic drop down menu of the items the person already typed into that same column. This way they don't have to "type" the same name twice (can pick it from the menu the second time). It makes data entry faster and increases the likely hood that multiple duplicate entries will be the exact same. To allow text entry at the same time as menu selection, I just turn off the data validation error message.
Over time I may build a dynamic list of names from past times the form was filled out so that this drop down menu does not start out blank each time. But right now this is still helpful to the user (and me).
Thank you very much.... I have yet to figure out how all these complex array formulas work. Right now you are the magician and I am the kid in awe.
March 21st, 2011 at 8:13 am
Peter,
Maybe you can use these instructions:
Excel Data Validation -- Hide Previously Used Items in Dropdown and modify formulas to only show previously used items in a drop down list.
March 22nd, 2011 at 10:12 pm
Thanks Oscar,
That might come in handy some day. In the process of scoping that out I stumbled on a bunch of other potentially useful data validation methods including selecting multiple items from a menu.
"If God didn't invent Excel, I bet that's where he spends most of his time." - Peter V.
May 28th, 2011 at 3:40 pm
This is really good; thanks for posting.
May 30th, 2011 at 7:45 am
Chris,
thank you!
July 19th, 2011 at 10:47 pm
may i ask the maximum limit on the amount of records you can have in a dropdown list?
thanks.
July 20th, 2011 at 7:13 pm
Juna,
I can´t enter more than 32767 values in a drop down list in excel 2007.
Maybe someone else can shed some light on this, I can´t find anything about this (google).
September 20th, 2011 at 9:52 pm
tnx oscar for this formula
but i have a problem with that.
it has to calculate about 8000 cells and it slows down my pc badly.
any suggestions?
September 21st, 2011 at 10:39 am
luka,
I have updated this article with a vba function. Download the attached file!
October 15th, 2011 at 3:08 am
Hi
The dropdown unique listing is really helpful and i appreciate that.
October 17th, 2011 at 9:47 am
Eddy Stanley,
Thanks!
January 17th, 2012 at 2:07 pm
Hi,
I have a requirement (read problem). I have created a drop down list with following items:
1.Above
2.Below
3.At par
I want if someone choose Above, a formula for escalation of value is executed, if Below a formula for Degradation of value, if At par is used no change in the value.
I am unable to link the chosen field in formula.
Kindly help.
Thanks
January 20th, 2012 at 6:49 pm
DJ,
I am not sure that is possible. What is the formula for escalation of a value?
I would suggest a spin button (form control) and link the control to a cell.