0

two

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.

Storax
  • 11,158
  • 3
  • 16
  • 33
Bamuel
  • 55
  • 8

3 Answers3

2

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

T.M.
  • 9,436
  • 3
  • 33
  • 57
2

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

enter image description here

  • 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 the FILTERXML function
  • 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
Ron Rosenfeld
  • 53,870
  • 7
  • 28
  • 60
  • I'm using Office 2016 – Bamuel Nov 04 '19 at 10:11
  • @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 ``? .. 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. Nov 04 '19 at 19:44
  • @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 ``) - *BTW Always enjoy your helpful Postings.* - @RonRosenfeld – T.M. Nov 04 '19 at 19:56
  • 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
0
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
Test12345
  • 1,625
  • 1
  • 12
  • 21
Bamuel
  • 55
  • 8
  • 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