'********************************************************************************************************** ' Name: uniqueValues ' Author: mielk | 2014-08-27 ' ' Description: Function to return unique value only from the given 1D array. ' ' Parameters: ' arr Array which unique values are to be returned. ' ' Returns: ' Variant() Array containing unique values from the given 1D array. ' Result array is of Variant type, since base array given as an input ' parameter can store all types of data. ' ' ' Exceptions: ' NotArrayException Thrown if the given parameter is not an array. ' TooManyDimensionsException Thrown if the given array has more than one dimension. ' ' ' --- Changes log ----------------------------------------------------------------------------------------- ' 2014-08-27 mielk Function created. '********************************************************************************************************** Public Function uniqueValues(arr As Variant) As Variant() Const METHOD_NAME As String = "uniqueValues" '------------------------------------------------------------------------------------------------------ Dim result() As Variant Dim i As Long Dim dict As Object 'Dictionary Dim value As Variant '------------------------------------------------------------------------------------------------------ 'Check if the given parameter [arr] is an array and if it has exactly one dimension. ----------------| If Not VBA.IsArray(arr) Then GoTo NotArrayException '| If countDimensions(arr) > 1 Then GoTo TooManyDimensionsException '| '----------------------------------------------------------------------------------------------------| 'Initialize variable [dict] with the empty Dictionary for storing unique values. --------------------| Set dict = VBA.CreateObject("Scripting.Dictionary") '| '----------------------------------------------------------------------------------------------------| 'Iterate through all the items of the original array and try to insert them into dictionary ---------| '[dict]. Before adding item to the dictionary it is checked if it not exists already. If it is '| 'already found in the dictionary, it is being skipped. '| For i = LBound(arr) To UBound(arr) '| '| 'Before assigning item from source array [arr] to the variable [value], the function --------| '| 'must check if it is object or not, because different assigning statement is used '| '| 'in both those cases. '| '| If VBA.IsObject(arr(i)) Then '| '| Set value = arr(i) '| '| Else '| '| value = arr(i) '| '| End If '| '| '--------------------------------------------------------------------------------------------| '| '| '| 'Check if this value already exists in the dictionary [dict]. If not, it is being -----------| '| 'added. If it already exists, it is being skipped. '| '| If Not dict.Exists(value) Then '| '| Call dict.add(value, value) '| '| End If '| '| '--------------------------------------------------------------------------------------------| '| '| '| Next i '| '----------------------------------------------------------------------------------------------------| 'Convert dictionary keys into array using function getDictionaryKeys. uniqueValues = getDictionaryKeys(dict) '========================================================================================================== ExitPoint: Exit Function '---------------------------------------------------------------------------------------------------------- NotArrayException: 'Error handler for a case if the given parameter is not an array. GoTo ExitPoint TooManyDimensionsException: 'Error handler forPut your own error handling here for a case if the given array has more than one dimension. GoTo ExitPoint End Function '********************************************************************************************************** ' Name: countDimensions ' Author: mielk | 2012-03-03 ' ' Comment: Returns the number of dimensions of the given VBA array. ' ' Parameters: ' arr Array for which number of dimensions is to be returned. ' ' Returns: ' Integer The number of dimensions of the given VBA array. ' If the given value is not an array function returns -1. ' If the given value is declared as a dynamic array but its dimensions have not been ' declared yet, 0 is returned. ' ' ' --- Changes log ----------------------------------------------------------------------------------------- ' 2012-03-03 mielk Function created. ' 2014-06-15 mielk Returned type changed to Integer to allow -1 to be returned. ' For non-arrays values -1 is returned. '********************************************************************************************************** Public Function countDimensions(arr As Variant) As Integer Const METHOD_NAME As String = "countDimensions" '------------------------------------------------------------------------------------------------------ Dim bound As Long '------------------------------------------------------------------------------------------------------ If VBA.IsArray(arr) Then On Error GoTo NoMoreDimensions Do bound = UBound(arr, countDimensions + 1) countDimensions = countDimensions + 1 Loop Else countDimensions = -1 End If '---------------------------------------------------------------------------------------------------------- NoMoreDimensions: End Function '********************************************************************************************************** ' Name: getDictionaryKeys ' Author: mielk | 2013-04-10 ' ' Comment: Returns set of keys of the specified dictionary as a one-dimensional array. ' ' Parameters: ' dict Dictionary which keys are to be returned. ' ' Returns: ' Variant() Array of the keys from the given dictionary. ' ' ' Exceptions: ' IllegalTypeException Thrown if the given parameter is not a dictionary. ' ' ' --- Changes log ----------------------------------------------------------------------------------------- ' 2013-04-10 mielk Function created. '********************************************************************************************************** Public Function getDictionaryKeys(dict As Variant) As Variant() Const METHOD_NAME As String = "getDictionaryKeys" '------------------------------------------------------------------------------------------------------ Const DICTIONARY_TYPENAME As String = "Dictionary" '------------------------------------------------------------------------------------------------------ Dim varKey As Variant Dim arr() As Variant Dim lngItem As Long '------------------------------------------------------------------------------------------------------ 'Check if the given parameter dict is a dictionary. -------------------------------------------------| If VBA.StrComp(VBA.TypeName(dict), DICTIONARY_TYPENAME, vbTextCompare) Then _ GoTo IllegalTypeException '| '----------------------------------------------------------------------------------------------------| 'If the given dictionary is empty, empty array will be returned. ------------------------------------| If dict.Count Then '| '| 'Resize final table [arr] to be big enough for all the items from the given dictionary. -----| '| ReDim arr(1 To dict.Count) '| '| For Each varKey In dict.keys '| '| lngItem = lngItem + 1 '| '| '| '| 'Before adding value to the result array check if it is an object or ----------------| '| '| 'a primitive value and apply proper action. '| '| '| If VBA.IsObject(varKey) Then '| '| '| Set arr(lngItem) = varKey '| '| '| Else '| '| '| arr(lngItem) = varKey '| '| '| End If '| '| '| '------------------------------------------------------------------------------------| '| '| '| '| Next varKey '| '| '--------------------------------------------------------------------------------------------| '| '| End If '| '----------------------------------------------------------------------------------------------------| 'Assign the final table to the result variable. getDictionaryKeys = arr '========================================================================================================== ExitPoint: Exit Function '---------------------------------------------------------------------------------------------------------- IllegalTypeException: '(...) 'Error handling for the case if the given parameter is not a dictionary. GoTo ExitPoint End Function