Need to Count unique items in a column with VBA

MikeJP

Board Regular
Joined
Mar 10, 2003
Messages
51
I need to count the number of unique items in a column (excluding blank cells if possible) in VBA. I want to use the number as follows:

For x = 1 to (number of unique items)

To control how many times I pass through a loop.

Thanks
Mike Piles
 

Excel Facts

When did Power Query debut in Excel?
Although it was an add-in in Excel 2010 & Excel 2013, Power Query became a part of Excel in 2016, in Data, Get & Transform Data.
Howdy Mike,

Not sure about the tack-on loop, but you can use the TotUni long integer returned by the following which should respresent the count of unique items in your column of choice:

<font face=Courier New><SPAN style="color:darkblue">Sub</SPAN> CntUnique()
<SPAN style="color:darkblue">Dim</SPAN> Uni <SPAN style="color:darkblue">As</SPAN> Collection, cl <SPAN style="color:darkblue">As</SPAN> Range, LpRange <SPAN style="color:darkblue">As</SPAN> Range
<SPAN style="color:darkblue">Dim</SPAN> clswfrm <SPAN style="color:darkblue">As</SPAN> Range, clswcst <SPAN style="color:darkblue">As</SPAN> Range, myRng <SPAN style="color:darkblue">As</SPAN> Range
<SPAN style="color:darkblue">Dim</SPAN> TotUni <SPAN style="color:darkblue">As</SPAN> <SPAN style="color:darkblue">Long</SPAN>
<SPAN style="color:green"><SPAN style="color:green"><SPAN style="color:green">'*************</SPAN></SPAN></SPAN>
<SPAN style="color:darkblue">Set</SPAN> myRng = Sheets(1).[a:a] <SPAN style="color:green">'define your sheet/range</SPAN>
<SPAN style="color:green"><SPAN style="color:green"><SPAN style="color:green">'*************</SPAN></SPAN></SPAN>
<SPAN style="color:darkblue">On</SPAN> <SPAN style="color:darkblue">Error</SPAN> <SPAN style="color:darkblue">Resume</SPAN> <SPAN style="color:darkblue">Next</SPAN>
<SPAN style="color:darkblue">Set</SPAN> clswfrm = myRng.SpecialCells(xlFormulas)
<SPAN style="color:darkblue">Set</SPAN> clswcst = myRng.SpecialCells(xlConstants)
<SPAN style="color:darkblue">Set</SPAN> myRng = <SPAN style="color:darkblue">Nothing</SPAN> <SPAN style="color:green"><SPAN style="color:green">'free up memory</SPAN></SPAN>
<SPAN style="color:darkblue">On</SPAN> <SPAN style="color:darkblue">Error</SPAN> <SPAN style="color:darkblue">GoTo</SPAN> 0
<SPAN style="color:darkblue">If</SPAN> clswfrm <SPAN style="color:darkblue">Is</SPAN> <SPAN style="color:darkblue">Nothing</SPAN> And clswcst <SPAN style="color:darkblue">Is</SPAN> <SPAN style="color:darkblue">Nothing</SPAN> <SPAN style="color:darkblue">Then</SPAN>
    MsgBox "No Unique Cells"
    <SPAN style="color:darkblue">Exit</SPAN> <SPAN style="color:darkblue">Sub</SPAN>
    <SPAN style="color:darkblue">ElseIf</SPAN> <SPAN style="color:darkblue">Not</SPAN> clswfrm <SPAN style="color:darkblue">Is</SPAN> <SPAN style="color:darkblue">Nothing</SPAN> And <SPAN style="color:darkblue">Not</SPAN> clswcst <SPAN style="color:darkblue">Is</SPAN> <SPAN style="color:darkblue">Nothing</SPAN> <SPAN style="color:darkblue">Then</SPAN>
        <SPAN style="color:darkblue">Set</SPAN> LpRange = Union(clswcst, clswfrm)
    <SPAN style="color:darkblue">ElseIf</SPAN> clswfrm <SPAN style="color:darkblue">Is</SPAN> <SPAN style="color:darkblue">Nothing</SPAN> <SPAN style="color:darkblue">Then</SPAN> <SPAN style="color:darkblue">Set</SPAN> LpRange = clswcst
    Else: <SPAN style="color:darkblue">Set</SPAN> LpRange = clswfrm
<SPAN style="color:darkblue">End</SPAN> <SPAN style="color:darkblue">If</SPAN>
<SPAN style="color:darkblue">Set</SPAN> clswfrm = Nothing: <SPAN style="color:darkblue">Set</SPAN> clswcst = <SPAN style="color:darkblue">Nothing</SPAN> <SPAN style="color:green">'Free up memory</SPAN>
<SPAN style="color:darkblue">Set</SPAN> Uni = <SPAN style="color:darkblue">New</SPAN> Collection
<SPAN style="color:darkblue">On</SPAN> <SPAN style="color:darkblue">Error</SPAN> <SPAN style="color:darkblue">Resume</SPAN> <SPAN style="color:darkblue">Next</SPAN>
<SPAN style="color:darkblue">For</SPAN> <SPAN style="color:darkblue">Each</SPAN> cl <SPAN style="color:darkblue">In</SPAN> LpRange
    Uni.Add cl.Value, <SPAN style="color:darkblue">CStr</SPAN>(cl.Value) <SPAN style="color:green">'assign unique key string</SPAN>
<SPAN style="color:darkblue">Next</SPAN> cl
<SPAN style="color:darkblue">On</SPAN> <SPAN style="color:darkblue">Error</SPAN> <SPAN style="color:darkblue">GoTo</SPAN> 0
<SPAN style="color:darkblue">Set</SPAN> LpRange = <SPAN style="color:darkblue">Nothing</SPAN> <SPAN style="color:green"><SPAN style="color:green">'free up memory</SPAN></SPAN>
TotUni = Uni.Count
<SPAN style="color:darkblue">Set</SPAN> Uni = <SPAN style="color:darkblue">Nothing</SPAN> <SPAN style="color:green">'<SPAN style="color:green"><SPAN style="color:green">'free up memory</SPAN></SPAN></SPAN>
MsgBox TotUni <SPAN style="color:green">'Work with the Unique value total here (replace msgbox)</SPAN>
<SPAN style="color:darkblue">End</SPAN> <SPAN style="color:darkblue">Sub</SPAN>
</FONT>

The proc. may seem a little long, however, I didn't think looping through 65536 cells in a column is a good approach. The initial part of procedure is determining your range in the column that actually holds either cell constants or formulae, which gets us around evaluating blank cells.

Hope this helps.
 
Upvote 0
THanks Nate,

Works great!!! It was a little more complex than I expected!

Regards,
Mike
 
Upvote 0
Another option is a function like this:

<font face=Courier New>
<SPAN style="color:#00007F">Function</SPAN> CountUnique(<SPAN style="color:#00007F">ByVal</SPAN> Rng <SPAN style="color:#00007F">As</SPAN> Range) <SPAN style="color:#00007F">As</SPAN> <SPAN style="color:#00007F">Long</SPAN>
    <SPAN style="color:#00007F">Dim</SPAN> St <SPAN style="color:#00007F">As</SPAN> <SPAN style="color:#00007F">String</SPAN>
    <SPAN style="color:#00007F">Set</SPAN> Rng = Intersect(Rng, Rng.Parent.UsedRange)
    St = "'" & Rng.Parent.Name & "'!" & Rng.Address(False, False)
    CountUnique = Evaluate("SUM(IF(LEN(" & St & "),1/COUNTIF(" & St & "," & St & ")))")
<SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Function</SPAN>
</FONT>

You could use it like

MsgBox CountUnique(Sheets("Sheet1").Range("A:A"))
 
Upvote 0
I'm needing to do a similar task, but from a pivot table looking at a column of text. My original thread is below.

http://www.mrexcel.com/board2/viewtopic.php?t=81625&highlight=

I just want to have this piece:
Code:
' This creates the data fields.
    With ActiveSheet.PivotTables("Unit Response Summary").PivotFields( _
        "Incident Type Class")
        .Orientation = xlDataField
        .Position = 1
        .Caption = "Count"
        '.Function = CountUnique(Sheets("PersonnelResponseData").Range("U:U")) **tried JP's here** 
        .NumberFormat = "#,##0"
    End With
perform the count of unique items.

Thanks,
CountingApples
 
Upvote 0
To create a unique list? Use the advanced filter. Or to count, use the original data set.
 
Upvote 0
Put my original data where? Sorry for being dense, I've been trying so many different variations of countif and the two macros here I can't think straight anymore. :oops:
 
Upvote 0
Change:

Set myRng = Sheets(1).[a:a] 'define your sheet/range

To your original data set (pre P.T.). :)
 
Upvote 0
I have that in and it keeps telling me that there are no unique items. I expect a minimum of 8 items. Just for kicks I tried using the incident number rather than incident category and that had no unique items either. I'm looking at the data in sheet 2.

Any thoughts on what I've done wrong, or where I should look?
 
Upvote 0
I don't know what you've done or what you're looking at based on your posts.

If I want to look at a:d on sheets(2), the constants and functions, the following works as expected for me:

<font face=Courier New><SPAN style="color:darkblue">Sub</SPAN> CntUnique2()
<SPAN style="color:darkblue">Dim</SPAN> Uni <SPAN style="color:darkblue">As</SPAN> Collection, cl <SPAN style="color:darkblue">As</SPAN> Range, LpRange <SPAN style="color:darkblue">As</SPAN> Range
<SPAN style="color:darkblue">Dim</SPAN> clswfrm <SPAN style="color:darkblue">As</SPAN> Range, clswcst <SPAN style="color:darkblue">As</SPAN> Range, myRng <SPAN style="color:darkblue">As</SPAN> Range
<SPAN style="color:darkblue">Dim</SPAN> TotUni <SPAN style="color:darkblue">As</SPAN> <SPAN style="color:darkblue">Long</SPAN>
<SPAN style="color:green"><SPAN style="color:green"><SPAN style="color:green">'*************</SPAN></SPAN></SPAN>
<SPAN style="color:darkblue">Set</SPAN> myRng = Sheets(2).[a:d] <SPAN style="color:green">'define your sheet/range</SPAN>
<SPAN style="color:green"><SPAN style="color:green"><SPAN style="color:green">'*************</SPAN></SPAN></SPAN>
<SPAN style="color:darkblue">On</SPAN> <SPAN style="color:darkblue">Error</SPAN> <SPAN style="color:darkblue">Resume</SPAN> <SPAN style="color:darkblue">Next</SPAN>
<SPAN style="color:darkblue">Set</SPAN> clswfrm = myRng.SpecialCells(xlFormulas)
<SPAN style="color:darkblue">Set</SPAN> clswcst = myRng.SpecialCells(xlConstants)
<SPAN style="color:darkblue">Set</SPAN> myRng = <SPAN style="color:darkblue">Nothing</SPAN> <SPAN style="color:green"><SPAN style="color:green">'free up memory</SPAN></SPAN>
<SPAN style="color:darkblue">On</SPAN> <SPAN style="color:darkblue">Error</SPAN> <SPAN style="color:darkblue">GoTo</SPAN> 0
<SPAN style="color:darkblue">If</SPAN> clswfrm <SPAN style="color:darkblue">Is</SPAN> <SPAN style="color:darkblue">Nothing</SPAN> And clswcst <SPAN style="color:darkblue">Is</SPAN> <SPAN style="color:darkblue">Nothing</SPAN> <SPAN style="color:darkblue">Then</SPAN>
    MsgBox "No Unique Cells"
    <SPAN style="color:darkblue">Exit</SPAN> <SPAN style="color:darkblue">Sub</SPAN>
    <SPAN style="color:darkblue">ElseIf</SPAN> <SPAN style="color:darkblue">Not</SPAN> clswfrm <SPAN style="color:darkblue">Is</SPAN> <SPAN style="color:darkblue">Nothing</SPAN> And <SPAN style="color:darkblue">Not</SPAN> clswcst <SPAN style="color:darkblue">Is</SPAN> <SPAN style="color:darkblue">Nothing</SPAN> <SPAN style="color:darkblue">Then</SPAN>
        <SPAN style="color:darkblue">Set</SPAN> LpRange = Union(clswcst, clswfrm)
    <SPAN style="color:darkblue">ElseIf</SPAN> clswfrm <SPAN style="color:darkblue">Is</SPAN> <SPAN style="color:darkblue">Nothing</SPAN> <SPAN style="color:darkblue">Then</SPAN> <SPAN style="color:darkblue">Set</SPAN> LpRange = clswcst
    Else: <SPAN style="color:darkblue">Set</SPAN> LpRange = clswfrm
<SPAN style="color:darkblue">End</SPAN> <SPAN style="color:darkblue">If</SPAN>
<SPAN style="color:darkblue">Set</SPAN> clswfrm = Nothing: <SPAN style="color:darkblue">Set</SPAN> clswcst = <SPAN style="color:darkblue">Nothing</SPAN> <SPAN style="color:green">'Free up memory</SPAN>
<SPAN style="color:darkblue">Set</SPAN> Uni = <SPAN style="color:darkblue">New</SPAN> Collection
<SPAN style="color:darkblue">On</SPAN> <SPAN style="color:darkblue">Error</SPAN> <SPAN style="color:darkblue">Resume</SPAN> <SPAN style="color:darkblue">Next</SPAN>
<SPAN style="color:darkblue">For</SPAN> <SPAN style="color:darkblue">Each</SPAN> cl <SPAN style="color:darkblue">In</SPAN> LpRange
    Uni.Add cl.Value, <SPAN style="color:darkblue">CStr</SPAN>(cl.Value) <SPAN style="color:green">'assign unique key string</SPAN>
<SPAN style="color:darkblue">Next</SPAN> cl
<SPAN style="color:darkblue">On</SPAN> <SPAN style="color:darkblue">Error</SPAN> <SPAN style="color:darkblue">GoTo</SPAN> 0
<SPAN style="color:darkblue">Set</SPAN> LpRange = <SPAN style="color:darkblue">Nothing</SPAN> <SPAN style="color:green"><SPAN style="color:green">'free up memory</SPAN></SPAN>
TotUni = Uni.Count
<SPAN style="color:darkblue">Set</SPAN> Uni = <SPAN style="color:darkblue">Nothing</SPAN> <SPAN style="color:green">'<SPAN style="color:green"><SPAN style="color:green">'free up memory</SPAN></SPAN></SPAN>
MsgBox TotUni <SPAN style="color:green">'Work with the Unique value total here (replace msgbox)</SPAN>
<SPAN style="color:darkblue">End</SPAN> <SPAN style="color:darkblue">Sub</SPAN>
</FONT>
 
Upvote 0

Forum statistics

Threads
1,215,330
Messages
6,124,305
Members
449,150
Latest member
NyDarR

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