How can we perform common set operations (union, intersection, minus) in MS Excel?

前端 未结 4 1867
梦毁少年i
梦毁少年i 2021-01-05 15:00

For example, I have an xls where :

  • column A has list of items with property A
  • column B has list of items with property B

I need the fol

相关标签:
4条回答
  • 2021-01-05 15:32

    Intersection (In A & B): =IFNA(VLOOKUP(B2,$A$2:$B$42,1,FALSE),"")

    Union (In A or B): =IFS(A2,A2,B2,B2) Note that IFS is only in recent (as of 2018) versions.

    A - B (Only in A): =IF(NOT(IFNA(MATCH(A2,$B$2:$B$42,0),FALSE)),IF(A2,A2,""),"")

    B - A (Only in B): =IF(NOT(IFNA(MATCH(B2,$A$2:$A$42,0),FALSE)),IF(B2,B2,""),"") (Swap the letters)

    0 讨论(0)
  • 2021-01-05 15:32

    I'm surprised at several levels:
    (1) 2020 now .... and still no set functions in Excel
    (2) The highest voted answer (from 2018) is very impractical: in real live, data sets don't come neatly with empty rows inserted where a value is missing vs. another data set; which is the precondition for this solution.

    The most practical solution (though still awkward; do you hear us, Microsoft ???) is a work around with the help of a pivot table:

    • Add column to set A, with column name "set_name" and all values in the column set to "A" -> pivot input A
    • Add column to set B, with column name "set_name" and all values in the column set to "B" -> pivot input B
    • copy pivot input B (without column names ;-)) under pivot input A to form a joint range -> joint range
    • create a pivot table from the joint range with
      --- "set names" being used to form the columns of the pivot table
      --- pivot function set to "count()"

    The result is a sort of "one-hot-encoded" pivot table with:

    • 1st column: union set of A and B (aka ALL occuring values)
    • 2nd column: 1-values only for elements occuring in set A
      (caveat: assumption is that A only contains UNIQUE elements. Otherwise,
      values > 1 are possible)
    • 3rd column: 1-values only for elements occuring in set B
      (same caveat applies as for set A)
    • Total column: values showing "2" value exist in both sets

    The resulting pivot table can easily be filtered on the different sets and intersections via the values in columns 2 (aka "set A"),3 (aka "set B") and 4 (aka "Set A AND Set B").

    0 讨论(0)
  • 2021-01-05 15:37

    you can simple use below formula to get result

    =IF(LOWER(A4)=LOWER(B4),"",A4)

    0 讨论(0)
  • 2021-01-05 15:50

    Well, Microsoft Excel does not handle built-in set operations. But you can emulate then by VBA using MATCH function and error handling.

    Here is the code that worked for me (I presume that you have heading on the first line):

    Sub set_operations()
        Dim i, j, rangeA, rangeB, rowC, rowD, rowE, rowF As Long
        Dim test1, test2 As Boolean
    
        rangeA = ActiveSheet.Range("A" & CStr(ActiveSheet.Rows.Count)).End(xlUp).Row()
        rangeB = ActiveSheet.Range("B" & CStr(ActiveSheet.Rows.Count)).End(xlUp).Row()
        rowC = 2
        rowD = 2
        rowE = 2
        rowF = 2
        test1 = False
        test2 = False
        test2 = False
    
        'A union B
        On Error GoTo errHandler1
        For i = 2 To rangeA
            If Application.Match(ActiveSheet.Cells(i, 1), ActiveSheet.Range("C:C"), 0) > 0 Then
                If test1 = True Then
                    ActiveSheet.Cells(rowC, 3) = ActiveSheet.Cells(i, 1)
                    rowC = rowC + 1
                End If
            End If
            test1 = False
        Next i
        For j = 2 To rangeB
            If Application.Match(ActiveSheet.Cells(j, 2), ActiveSheet.Range("C:C"), 0) > 0 Then
                If test1 = True Then
                    ActiveSheet.Cells(rowC, 3) = ActiveSheet.Cells(j, 2)
                    rowC = rowC + 1
                End If
            End If
            test1 = False
        Next j
    
        'A intersection B
        For i = 2 To rangeA
            On Error GoTo errHandler2
            If Application.Match(ActiveSheet.Cells(i, 1), ActiveSheet.Range("B:B"), 0) > 0 Then
                On Error GoTo errHandler1
                If Application.Match(ActiveSheet.Cells(i, 1), ActiveSheet.Range("D:D"), 0) > 0 Then
                    If test1 = True And test2 = False Then
                        ActiveSheet.Cells(rowD, 4) = ActiveSheet.Cells(i, 1)
                        rowD = rowD + 1
                    End If
                End If
            End If
            test1 = False
            test2 = False
        Next i
    
        'A minus B
        For i = 2 To rangeA
            On Error GoTo errHandler2
            If Application.Match(ActiveSheet.Cells(i, 1), ActiveSheet.Range("B:B"), 0) > 0 Then
                On Error GoTo errHandler1
                If Application.Match(ActiveSheet.Cells(i, 1), ActiveSheet.Range("E:E"), 0) > 0 Then
                    If test1 = True And test2 = True Then
                        ActiveSheet.Cells(rowE, 5) = ActiveSheet.Cells(i, 1)
                        rowE = rowE + 1
                    End If
                End If
            End If
            test1 = False
            test2 = False
        Next i
    
        'B minus A
        For i = 2 To rangeB
            On Error GoTo errHandler2
            If Application.Match(ActiveSheet.Cells(i, 2), ActiveSheet.Range("A:A"), 0) > 0 Then
                On Error GoTo errHandler1
                If Application.Match(ActiveSheet.Cells(i, 2), ActiveSheet.Range("F:F"), 0) > 0 Then
                    If test1 = True And test2 = True Then
                        ActiveSheet.Cells(rowF, 6) = ActiveSheet.Cells(i, 2)
                        rowF = rowF + 1
                    End If
                End If
            End If
            test1 = False
            test2 = False
        Next i
    
    
    errHandler1:
        test1 = True
        Resume Next
    
    errHandler2:
        test2 = True
        Resume Next
    End Sub
    
    0 讨论(0)
提交回复
热议问题