So currently I have two DATA inputs in excel Data 1 and Data 2 I need a formula or some sort to display results *currently this is a manual process.
-
I know that we have to use a function under Split, and compare them both, then make it back to a 123, 124, 125 sequence form – Bamuel Nov 03 '19 at 02:59
-
Does that mean this is a homework problem, with constraints? – Ron Rosenfeld Nov 04 '19 at 11:27
-
@RonRosenfeld nah it's just me being extra at work – Bamuel Nov 05 '19 at 10:29
3 Answers
Approach using Filter()
function
Function test(ByVal a, ByVal b, Optional Delim$ = ",") As String
'Purpose: return non unique values by comparing two comma separated string lists a vs. b
a = Split(a, Delim): b = Split(b, Delim)
Dim elem
For Each elem In b
a = Filter(a, elem, False) ' Include:=False, i.e. exclude non uniques
Next elem
test = Join(a, Delim & " ")
End Function
Argument a: 668,669,777,778,779,780,781,782,891,893,894,895
Argument b: 668,777,779,778,780,892,891,782
Result string 669, 781, 893, 894, 895
BTW the result shouldn't include 782 (c.f. OP) as this isn't a unique item.
Caveat/Edit
The above approach assumes three figure numbers only. As basically the Filter
function executes a partial string search this would lead to unwanted results if you would be searching for e.g. 7
thus excluding any number containing 7
, as well. ~~> See revised code
Revised code
Allows only full string matches:
Variant a) 2nd list contains doublettes, but is only a sub set of 1st list
Function test(ByVal a, ByVal b, Optional Delim$ = ",") As String
'Purpose: return non unique values by comparing two comma separated string lists a vs. b
a = "$" & Replace(a, Delim, "$" & Delim & "$") & "$"
a = Split(a, Delim): b = Split(b, Delim)
Dim elem
For Each elem In b
a = Filter(a, "$" & elem & "$", False) ' Include:=False, i.e. exclude non uniques
Next elem
test = Replace(Join(a, Delim & " "), "$", vbNullString)
End Function
Variant b) 2nd list contains also new numbers diferring from 1st list
This might be the waterproof solution to your question (results corresponding to @RonRosenfeld 's fine solution).
Function test(ByVal a, ByVal b, Optional Delim$ = ",", Optional ByVal cnt% = 1) As String
'Purpose: return non unique values by comparing two comma separated string lists a vs. b
If cnt = 1 Then ' recursive call to check 2nd string against 1st one
test = test(b, a, Delim, 2)
If Len(test) > 1 Then test = Mid(test, 1, Len(test) - 1)
End If
a = "$" & Replace(a, Delim, "$" & Delim & "$") & "$"
a = Split(a, Delim): b = Split(b, Delim)
Dim elem
For Each elem In b
a = Filter(a, "$" & elem & "$", False) ' Include:=False, i.e. exclude non uniques
Next elem
test = Replace(Join(a, Delim), "$", vbNullString) & Delim & test
If cnt = 0 Then test = Replace(test, Delim, Delim & " ") ' add blank after delimiters
End Function

- 9,436
- 3
- 33
- 57
If you are using Excel 2016 or Office 365 with the TEXTJOIN
function, you can do this with an array formula
=TEXTJOIN(", ",,FILTERXML("<t><s>" & SUBSTITUTE(SUBSTITUTE(TEXTJOIN(",",TRUE,Data_1,Data_2)," ",""),",","</s><s>") & "</s></t>","//s[not( .=preceding::*) and not(.=following::*)]"))
Since this is an array formula, you need to "confirm" it by holding down ctrl + shift while hitting enter. If you do this correctly, Excel will place braces {...}
around the formula as observed in the formula bar
TEXTJOIN
the strings using the comma delimiter- If there are only two or three strings, you could use a simple concatenation and avoid the
TEXTJOIN
function, but you'd still need Excel 2013+ to have theFILTERXML
function
- If there are only two or three strings, you could use a simple concatenation and avoid the
- Remove the spaces. If all delimiters are
<comma><space>
we could simplify the formula a bit. - Create an XML using the
<comma>
to define the nodes. - the
xPath
says to return all nodes that are not followed by or preceded by it's duplicate. TEXTJOIN
the resultant array

- 53,870
- 7
- 28
- 60
-
-
@Bamuel If you have the `TEXTJOIN` function, then the formula should work. – Ron Rosenfeld Nov 04 '19 at 10:45
-
Your `XPath` expression in the `FilterXML` function is not only tricky, but proves to be very effective in this one line formula +1). - BTW Is there a common help source to the function's node naming using the same tags, i.e. `
` and ` – T.M. Nov 04 '19 at 19:44`? .. c.f. a [recent post using FILTERXML](https://stackoverflow.com/questions/58673369/is-there-a-way-to-count-the-number-of-characters-per-word-for-a-string-returnin/58674097#58674097) ? - @RonRosenfeld -
@T.M. It doesn't make any difference how the nodes are named, so long as you use the same name for all the siblings, and a different name for the *wrapper*. One can, of course, create more complex xml's, but since what we're really doing is splitting a delimited string, and then applying an xPath to that, there's no need. – Ron Rosenfeld Nov 04 '19 at 19:49
-
Thx for the quick & correct response, but I only wanted to know if there is a **common source** to refer as your post and the cited one above use the *same* naming convention (i.e. a `DocumentElement` wrapper named `
` and and a sub level node name ` – T.M. Nov 04 '19 at 19:56`) - *BTW Always enjoy your helpful Postings.* - @RonRosenfeld -
1@T.M. I dunno. I noticed that naming convention being used by another, and I think the poster in your cited reference noticed my use of it. – Ron Rosenfeld Nov 04 '19 at 20:15
Function TEST(aString As String, aString2 As String, Optional Delimiter As String = ",") As String
array1 = Split(aString, Delimiter)
array2 = Split(aString2, Delimiter)
Dim i 'As Integer
Dim j 'As Integer
Dim isFound 'As Boolean
Dim output
For i = 0 To UBound(array1)
isFound = False
For j = 0 To UBound(array2) - 1
If array1(i) = array2(j) Then
isFound = True
End If
Next 'j
If Not isFound Then
output = output + array1(i) & ", "
End If
Next 'i
TEST = output
End Function
-
Friendly hint: Your `782` item isn't unique and shouldn't be occur in your list. Cause: in order to avoid a final delimiter in the result string your `j` loop *forgets* the last array2 item to be compared when counting only to `UBound(array2) - 1 instead to `UBound(array2)` only. Just replace the last delimiter character(s) by "" if the output len(gth) is greater than 0. (and don't forget to declare `array1` and `array2` as Variant; ~> Option Explicit!) - // FYI There are many ways leading to Rome, maybe you find my approach using the `Filter()` function helpful. – T.M. Nov 03 '19 at 16:19