0

I need a public function to get array and counts values in specific column. I wrote the following and recives subscription out of range message.

Public Function CountUarrcol(inarr() As Variant, colidx As Integer) As Long
 Dim col As New Collection
 Dim i As Integer
 Dim element As Variant

 For i = 0 To UBound(inarr, colidx)
    For Each element In inarr(i + 1, colidx)
        col.Add Item:=CStr(element.value), Key:=CStr(element.value)
    Next
 Next i
 CountUarrcol = col.Count   End Function
marc_s
  • 675,133
  • 158
  • 1,253
  • 1,388
  • Is i + 1 putting you beyond the UBound of inarr during the loop? – QHarr Dec 12 '17 at 11:21
  • Why do you have two loops? How are you passing `inarr` to your function? What line does your code stop on when you get the error? – Ron Rosenfeld Dec 12 '17 at 11:37
  • i revised this piece to following: 'Public Function CountUarrcol(inarr As Variant, colidx As Integer) As Long Dim col As New Collection Dim i As Integer Dim element As Variant For Each element In inarr col.Add Item:=element, Key:=element Next CountUarrcol = col.Count End Function' – user7181718 Dec 12 '17 at 11:44
  • now error is 457 the key is already associated with an element of collection – user7181718 Dec 12 '17 at 11:54
  • See here [determining-whether-an-object-is-a-member-of-a-collection-in-vba](https://stackoverflow.com/questions/137845/determining-whether-an-object-is-a-member-of-a-collection-in-vba) – QHarr Dec 12 '17 at 12:29

2 Answers2

0

Assuming you want to do a count of distinct values within a specified column of an array, here is an example with a 5*3 array read in from a worksheet range, counting the distinct values in column 2. I am using a function by Mark Nold to check if the value to be added already exists in the collection.

Option Explicit

Public Sub test()

    Dim testArr()
    Dim myCount As Long

    testArr = ActiveSheet.Range("A1:C5").Value

    myCount = CountUarrcol(testArr, 2)

    MsgBox myCount

End Sub

Public Function CountUarrcol(inarr() As Variant, colidx As Long) As Long

    Dim col As New Collection
    Dim i As Long

    For i = 1 To UBound(inarr)

        If Not InCollection(col, CStr(inarr(i, colidx))) Then

            col.Add Item:=CStr(inarr(i, colidx)), key:=CStr(inarr(i, colidx))

        End If

    Next i

    CountUarrcol = col.Count

End Function

'Mark Nold  https://stackoverflow.com/questions/137845/determining-whether-an-object-is-a-member-of-a-collection-in-vba

Public Function InCollection(col As Collection, key As String) As Boolean
    Dim var As Variant
    Dim errNumber As Long

    InCollection = False
    Set var = Nothing

    Err.Clear
    On Error Resume Next
    var = col.Item(key)
    errNumber = CLng(Err.Number)
    On Error GoTo 0

    '5 is not in, 0 and 438 represent incollection
    If errNumber = 5 Then                        ' it is 5 if not in collection
        InCollection = False
    Else
        InCollection = True
    End If

End Function

Running macro

QHarr
  • 72,711
  • 10
  • 44
  • 81
0

I Used two sub routine as follow:

Public Function CountUvalinarrcol(ByRef inarr As Variant, ByVal colidx As Integer) As Long
     Dim col As New Collection
     Dim i As Integer
     Dim element As Variant
                         
     For i = 1 To UBound(inarr)
     element = inarr(i, colidx)

         If colContains(col, element) = False Then
            col.Add item:=CStr(element)
         End If
     Next i
     CountUvalinarrcol = col.Count
End Function

The other one is:

    Public Function colContains(colin As Collection, itemin As Variant) As Boolean
Dim item As Variant
  colContains = False
  For Each item In colin
    If item = itemin Then
      colContains = True
      Exit Function
    End If
  Next
End Function

Calling above functions:

sub test()
dim x as long
x= CountUvalinarrcol(lsarr, 0)
end sub