At risk of being of topic, I decided to share some code, Q&A-style. If the general opinion is such that this would be off-topic I\'ll be happy to delete if need be.
Approach via FilterXML()
Just to enrich the variety of fine solutions above, I demonstrate an approach via the new worksheet function FilterXML()
.
Sub testUniqueItems()
' Purp: list unique items
' Site: https://stackoverflow.com/questions/59683363/unique-values-from-1d-array-without-iteration
Dim arr As Variant: arr = Array("A", "A", "C", "D", "A", "E", "G")
'[1]get uniques
Dim uniques
uniques = UniqueXML(arr)
'[2]display in Immediate Window: A,A,C,D,A,E,G => A,C,D,E,G
Debug.Print Join(arr, ",") & " => " & _
Join(uniques, ",")
End Sub
Function UniqueXML(arr, Optional Delim As String = ",")
' Purp: return unique list of array items
' Note: optional argument Delim defaulting to colon (",")
' Help: https://docs.microsoft.com/de-de/office/vba/api/excel.worksheetfunction.filterxml
' [1] get array data to xml node structure (including root element)
Dim wellformed As String
wellformed = "" & Join(arr, "") & " "
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' [2] define XPath string searching unique item values
' Note: c.f. udf: https://stackoverflow.com/questions/58677041/vba-excel-how-to-display-non-equal-values-in-an-excel-array/58685756#58685756
' ------------------------------------------------
' //i ... all node values after the DocumentElement
' [not( .=preceding::i)] ... only if not preceded by siblings of the same node value
' ------------------------------------------------
Dim myXPath As String
myXPath = "//i[not( .=preceding::i)]"
' [3a] get (delimiter separated) unique list
UniqueXML = Evaluate("=TEXTJOIN(""" & Delim & """,,FILTERXML(""" & wellformed & """, """ & myXPath & """))")
' [3b] return array
UniqueXML = Split(UniqueXML, Delim)
End Function
Related links
MS Help
Display non equal values in an Excel array
Caveat
Note that the Worksheet function FilterXML()
can be used from vers. 2016+, but TextJoin
only in vers. 2019+ (thx @FaneDuru for comments:-)
Furthermore you would have to be aware of the limits of evaluate. 255 chars only (thx @JvDv).
To overcome both obstacles I reworked above function to work in versions 2016+, too.
Modified function /Edit as of 2020-08-20
Function UniqueXML(arr, Optional Delim As String = ",")
' Purp: return unique list of array items
' Note: optional argument Delim defaulting to colon (",")
' Help: https://docs.microsoft.com/de-de/office/vba/api/excel.worksheetfunction.filterxml
' [1] get array data to xml node structure (including root element)
Dim wellformed As String
wellformed = "" & Join(arr, "") & " "
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' [2] define XPath string searching unique item values
' Note: c.f. udf: https://stackoverflow.com/questions/58677041/vba-excel-how-to-display-non-equal-values-in-an-excel-array/58685756#58685756
' ------------------------------------------------
' //i ... all node values after the DocumentElement
' [not( .=preceding::i)] ... only if not preceded by siblings of the same node value
' ------------------------------------------------
Dim myXPath As String
myXPath = "//i[not( .=preceding::i)]"
' [3] get "flat" 1-dim array (~> one-based!)
Dim tmp As Variant
tmp = Application.Transpose(WorksheetFunction.FilterXML(wellformed, myXPath))
' ' [3a] optional redim as zero-based array
' ReDim Preserve tmp(LBound(tmp) - 1 To UBound(tmp) - 1)
' [4] return function result
UniqueXML = tmp
End Function