Você está na página 1de 4

Returning Distinct Items In A Range

http://www.cpearson.com/excel/GetDistinct.aspx

PLC Automation
Software
Award Winning
Automation
System. PLC
Whitepapers &
Case Studies.

Listing Distinct Items From A Range

Free-Resource-Center.Plex.com

This page describes code that you can use to get a list of the
distinct elements in an range.

Introduction
Most every application written for Excel makes use of list in one way or another, and Excel provides
a number of functions (VLOOKUP, HLOOKUP, and the D data functions. However, there is no formula
function that allows you to get a list of the distinct elements. That is, a list with all duplicates
removed. Excel's Advanced Filter can do this, but it has two significant shortcomings: First, the list of
distinct values must be placed on the same worksheet as the original data. Second, the list created
by Advanced Filter is static. If you add new elements to the list, the filter list of distinct values is no
updated. You have to apply the filter manually.
The code on this page describes a VBA procedure called GetDistinct that returns an array
containing the distinct values from a range. The function declaration is:
Public Function GetDistinct(RR As Range) As Variant()
where RR is the range from which the distinct values are to be extracted. There result in an array of
Variants. This will return the values the values oriented as a single row spanning several columns. To
get the result oriented as a column, one column spanning several rows, use the TRANPOSE function
to transpose the array: =TRANSPOSE(GetDistict(A1:A10)).
This is an array formula, so you must first select the range cell cells into which the distinct values are
to be written, enter the formula, and press CTRL SHIFT ENTER rather than just ENTER when you
first enter the formula and whenever you edit it later. If you do this properly, Excel will display the
formula in the formula bar enclosed in curly braces { }.
The code can optionally resize the array to the size of the range from which it was called. Normally, if
you enter an array function into more cells than the size of the returned array, Excel files the empty
cell with #N/A errors. As written, the code will automatically resize itself so that it fills the entire
range with data, so no #N/A errors will appear. The values of the array that lie outside the distinct
elements are filled with empty strings so they will appear blank. See the nodes in the comments of
the code marked with '<<<<< OPTIONAL for details about this part of the code.

The GetDistinct Code


You can download a workbook with all the example code and examples on this
page.

The code for the GetDistinct procedure is shown below:


Option Explicit
Option Compare Text
Public Function GetDistinct(RR As Range) As Variant()
'============================================================================
' GetDistinct
' By Chip Pearson, chip@cpearson.com, www.cpearson.com, 1-August-2010

1 de 4

17/05/2011 09:44 a.m.

Returning Distinct Items In A Range

http://www.cpearson.com/excel/GetDistinct.aspx

'
' This creates an array containing all the distinct items
' from the range RR. The result array is row oriented (one row spanning
' several columns) so use TRANSPOSE if you want the values column
' oriented (one column spanning several rows). The array returned
' by this function is suitable for use within other array formulas.
' Array enter (CTRL SHIFT ENTER) the formula into as many rows
' or columns as there will be distinct elements. You can use
' Redim Arr(1 to RR.Cells.Count) to ensure you have enough room,
' and the array will be Redim Preserved to the actual use size
' before it is returned.
'
' You should take into consideration the size of the array. Using a
' range RR = A1:A5000 containing 100 distinct items, the code took
' approximately 3 seconds. Multiple uses of GetDistinct with very
' large ranges may have unacceptable calculation times.
' This procedures has two advantages of the Excel Advanced Filter. First,
' Filter requires that the list of distinct values be created on the
' same worksheet as the original data. GetDistinct has no such limitation.
' Second, Filter is not automatically updated. You must manually
' cause Filter to refresh the list of distinct items. GetDistinct
' will update its results in real time.
'============================================================================
Dim Arr() As Variant
Dim R As Range
Dim N As Long
Dim Ndx As Long
Dim ArraySize As Long
' If the range RR is completely empty, get out.
If Application.WorksheetFunction.CountA(RR) = 0 Then
ReDim Arr(1 To Application.Caller.Cells.Count)
For N = 1 To Application.Caller.Cells.Count
Arr(N) = vbNullString
Next N
GetDistinct = Arr
Exit Function
End If
' Get the number of distinct values in range RR. Resize the array
' to that many elements. This evaluates the following formula where
' $B$2:$B$11 are replaced by RR.Address
'
=SUM(1/IF($B$2:$B$11="",1,(COUNTIF($B$2:$B$11,$B$2:$B$11))))-COUNTBLANK($B$2:$B$11)
ArraySize = Application.Evaluate("=SUM(1/IF(" & RR.Address & "="""",1,(COUNTIF(" & _
RR.Address & "," & RR.Address & "))))-COUNTBLANK(" & RR.Address & ")")
ReDim Arr(1 To ArraySize)
' loop only in the region of RR that intersects with the UsedRange
' of the sheet. This can cut processing time dramatically.
For Each R In Application.Intersect(RR.Worksheet.UsedRange, RR).Cells
' ignore empty cells
If R.Text <> vbNullString Then
On Error Resume Next
Err.Clear
N = 0
' see if R.Value already exists in the Arr. If so,
' ignore it. If not present, add it.
N = Application.WorksheetFunction.Match(R.Value, Arr, 0)
If Err.Number <> 0 Then
Ndx = Ndx + 1
Arr(Ndx) = R.Value
End If
End If
Next R
'<<<<< OPTIONAL
' The following code is optional. It resizes the array to the
' number of cells from with it was called, so that if there
' are fewer elements than Application.Caller.Cells.Count
' (a condition that is always true unless all cells of
' RR have the same value. This prevents the arrray of cells
' on the worksheet being padded out with values = 0. If
' you don't want this resizing, get rid of the entire
' If/Then/Else/EndIf block of code and replace it with
'
ReDim Preserve Arr(1 To Ndx)
'

2 de 4

17/05/2011 09:44 a.m.

Returning Distinct Items In A Range

http://www.cpearson.com/excel/GetDistinct.aspx

If Application.Caller.Cells.Count > Ndx Then


ReDim Preserve Arr(1 To Application.Caller.Cells.Count)
For N = Ndx + 1 To Application.Caller.Cells.Count
Arr(N) = vbNullString
Next N
Else
ReDim Preserve Arr(1 To Ndx)
End If
GetDistinct = Arr
End Function

This page last updated: 9-August-2010.

Created by Chip Pearson at Pearson Software Consulting, LLC


Email: chip@cpearson.com Before emailing me, please read this page.
http://www.cpearson.com/excel/GetDistinct.aspx
Copyright 1997 - 2011, Charles H. Pearson
Submit bug information or errors on the Bug And Error Report Page.

Essential Tools For Developers

Essential Tools For Financial Analysts And Accounting Professionals

Ready

Advertise Your Product On This Site

Compare Excel tables - Powerful and handy add-on for


Excel 2000-2007 files comparison. www.office-excel.com
Ads by Google

3 de 4

17/05/2011 09:44 a.m.

Returning Distinct Items In A Range

4 de 4

http://www.cpearson.com/excel/GetDistinct.aspx

17/05/2011 09:44 a.m.

Você também pode gostar