Share via

Formula or VBA Function to List Unique values from a range of three columns

Anonymous
2014-03-18T15:40:16+00:00

Hi,

Is there a formula or function to list the Unique Values in a range of three columns?

Trying to create a List in Column E of the Unique Values (Product-Lot nos.) in Range B3:D50 as shown above.  There are blank

spaces in some cells.  The list in Col. E does not have to be sorted in order.   Column A is just for demo.  Not needed in formula.

I found a VBA custom Function that words for one Column but I can't get it to work for 3 Columns.  Tried other formula

suggestions but with no success.

Tried to explain this as simply as I could.

Thank-you in advance,

Amy

Microsoft 365 and Office | Excel | For home | Windows

Locked Question. This question was migrated from the Microsoft Support Community. You can vote on whether it's helpful, but you can't add comments or replies or follow the question.

0 comments No comments
Answer accepted by question author
  1. Anonymous
    2014-03-18T18:50:37+00:00

    If Jeeped's solution works for you, definitely go with it - native worksheet functions are generally faster than VBA code.  But if you want/decide you need a VBA solution, here is one you could use.  It goes into a regular code module:

    http://www.contextures.com/xlvba01.html#Regular

    It could be set up to work every time you made one or more changes to the defined range but since it's clearing/refilling the column E data, that might be a little distracting.  But if you want to try that also, I'll post that code following this post.  Here's the code you have to call when you wanted to get the list of unique items from either the [View] or [Developer] tabs (or set up a button to click to call it).

    Be sure to save the workbook as a macro enabled workbook, type .xlsm or .xlsb to preserve the code.

    Sub ExtractUniqueEntries()

      Const ProductSheetName = "Sheet1" ' change as appropriate

      Const ProductRange = "B3:D50"

      Const ResultsCol = "E"

      Dim productWS As Worksheet

      Dim uniqueList() As String

      Dim productsList As Range

      Dim anyProduct

      Dim LC As Integer

      ReDim uniqueList(1 To 1)

      Set productWS = Worksheets(ProductSheetName)

      Set productsList = productWS.Range(ProductRange)

      Application.ScreenUpdating = False

      For Each anyProduct In productsList

        If Not IsEmpty(anyProduct) Then

          If Trim(anyProduct) <> "" Then

            For LC = LBound(uniqueList) To UBound(uniqueList)

              If Trim(anyProduct) = uniqueList(LC) Then

                Exit For ' found match, exit

              End If

            Next

            If LC > UBound(uniqueList) Then

              'new item, add it

              uniqueList(UBound(uniqueList)) = Trim(anyProduct)

              'make room for another

              ReDim Preserve uniqueList(1 To UBound(uniqueList) + 1)

            End If

          End If

        End If

      Next ' end anyProduct loop

      If UBound(uniqueList) > 1 Then

        'remove empty element

        ReDim Preserve uniqueList(1 To UBound(uniqueList) - 1)

      End If

      'clear out any previous entries in results column

      If productWS.Range(ResultsCol & Rows.Count).End(xlUp).Row > 1 Then

        productWS.Range(ResultsCol & 2 & ":" & _

         productWS.Range(ResultsCol & Rows.Count).Address).ClearContents

      End If

      'list the unique items found

      For LC = LBound(uniqueList) To UBound(uniqueList)

        productWS.Range(ResultsCol & Rows.Count).End(xlUp).Offset(1, 0) = _

         uniqueList(LC)

      Next

      'housekeeping cleanup

      Set productsList = Nothing

      Set productWS = Nothing

    End Sub

    4 people found this answer helpful.
    0 comments No comments
Answer accepted by question author
  1. Anonymous
    2014-03-18T16:11:21+00:00

    You only have three columns and a limited number of rows to return so I would recommend this nested array formula.

    The array formula in E3 is,

    =IFERROR(INDEX($B$3:$B$99, MATCH(0, IF(LEN($B$3:$B$99), COUNTIF(E$2:E2, $B$3:$B$99),1),0)),IFERROR(INDEX($C$3:$C$99, MATCH(0, IF(LEN($C$3:$C$99), COUNTIF(E$2:E2, $C$3:$C$99),1),0)),IFERROR(INDEX($D$3:$D$99, MATCH(0, IF(LEN($D$3:$D$99), COUNTIF(E$2:E2, $D$3:$D$99),1),0)),"")))

    This requires Ctrl+Shift+Enter rather than just Enter to finalize. It is essentially three 'gather unique' formulas that are nested within IFERROR() functions.

    If you have much more than this sample data in your actual worksheet, a VBA routine using a scripting dictionary may be the best alternative.

    Hyperlink Description
    INDEX function Uses an index to choose a value from a reference or array
    MATCH function Looks up values in a reference or array
    IFERROR function Returns a value you specify if a formula evaluates to an error; otherwise, returns the result of the formula
    LEN function Returns the number of characters in a text string
    COUNTIF function Counts the number of cells within a range that meet the given criteria
    IFERROR function Returns a value you specify if a formula evaluates to an error; otherwise, returns the result of the formula
    0 comments No comments

27 additional answers

Sort by: Most helpful
  1. Anonymous
    2014-03-18T19:21:26+00:00

    Thanks JL.

    Code is awesome!   I'm using this on a number of different spreadsheets.

    Amy

    0 comments No comments
  2. Anonymous
    2014-03-18T19:06:09+00:00

    As promised, here's a variation of my previous code that will update the list in column E each time you make any change to the specified range.  This is worksheet code and it's easy to put in place:

    Choose the worksheet, right-click on its name tab and choose [View Code] from the popup list.  Copy the code and paste it into the module presented to you.  Press [Alt]+[Q] to return to the workbook.

    Save the workbook as a macro enabled workbook, type .xlsm or .xlsb and give it a try.

    The code

    Private Sub Worksheet_Change(ByVal Target As Range)

      Const ProductRange = "B3:D50"

      Const ResultsCol = "E"

      Dim uniqueList() As String

      Dim productsList As Range

      Dim anyProduct

      Dim LC As Integer

      Set productsList = ActiveSheet.Range(ProductRange)

      If Application.Intersect(Target, productsList) Is Nothing Then

        Set productsList = Nothing

        Exit Sub

      End If

      ReDim uniqueList(1 To 1)

      Application.ScreenUpdating = False

      For Each anyProduct In productsList

        If Not IsEmpty(anyProduct) Then

          If Trim(anyProduct) <> "" Then

            For LC = LBound(uniqueList) To UBound(uniqueList)

              If Trim(anyProduct) = uniqueList(LC) Then

                Exit For ' found match, exit

              End If

            Next

            If LC > UBound(uniqueList) Then

              'new item, add it

              uniqueList(UBound(uniqueList)) = Trim(anyProduct)

              'make room for another

              ReDim Preserve uniqueList(1 To UBound(uniqueList) + 1)

            End If

          End If

        End If

      Next ' end anyProduct loop

      If UBound(uniqueList) > 1 Then

        'remove empty element

        ReDim Preserve uniqueList(1 To UBound(uniqueList) - 1)

      End If

      'clear out any previous entries in results column

      If ActiveSheet.Range(ResultsCol & Rows.Count).End(xlUp).Row > 1 Then

        ActiveSheet.Range(ResultsCol & 2 & ":" & _

         ActiveSheet.Range(ResultsCol & Rows.Count).Address).ClearContents

      End If

      'list the unique items found

      For LC = LBound(uniqueList) To UBound(uniqueList)

        ActiveSheet.Range(ResultsCol & Rows.Count).End(xlUp).Offset(1, 0) = _

         uniqueList(LC)

      Next

      'housekeeping cleanup

      Set productsList = Nothing

    End Sub

    0 comments No comments
  3. Anonymous
    2014-03-18T18:50:50+00:00

    Thank-you Jeeped.

    Just what I was looking for and works perfect.

    Amy

    0 comments No comments