Как мы можем выполнять обычные операции над множествами (объединение, пересечение, минус) в MS Excel?

Например, у меня есть xls где:

  • в столбце А есть список объектов со свойством А
  • столбец B содержит список объектов со свойством B

Мне нужно следующее:

  • столбец C, представляющий собой A union B (уникальные предметы как A, так и B)
  • столбец D, который является пересечением A B (общие элементы A & B)
  • столбец E, который является A минус B (элементы в A, но не в B)
  • столбец F, который является B минус A (элементы в B, но не в A)

Операции над множествами элементов списка кажутся простыми с SQL или Python. Но как это сделать в xls?

Примечание: это должна быть автоматизация с минимальным количеством копий-вставок и кликов. Например, я не хочу копировать-вставлять A ниже B, а затем "исключать дубликаты", чтобы получить A B.

5 ответов

Пересечение (в A & B): =IFNA(VLOOKUP(B2,$A$2:$B$42,1,FALSE),"")

Союз (в A или B): =IFS(A2,A2,B2,B2) Обратите внимание, что IFS только в последних (по состоянию на 2018) версиях.

A - B (только в A): =IF(NOT(IFNA(MATCH(A2,$B$2:$B$42,0),FALSE)),IF(A2,A2,""),"")

B - A (только в B): =IF(NOT(IFNA(MATCH(B2,$A$2:$A$42,0),FALSE)),IF(B2,B2,""),"") (Поменяйте местами буквы)

Один Excel, кажется, не в состоянии выполнить эту работу. Тем не менее, есть надстройки. Возможно, вы захотите протестировать бесплатную Power Analytics для Excel с открытым исходным кодом . Он поставляется с некоторыми функциями, точно выполняющими то, что вы просили:

Использование в Excel 365

В Excel 365 Power Analytics для Excel можно использовать динамические массивы. Эта функция включена исключительно в Excel 365 и недоступна в Excel 2019, 2016 и т. д.

В следующем примере мы просто пишем =PA_Sets_And(A2:A11;B2:B6) в одну ячейку D2, а затем, как по волшебству, формула расширяется до необходимой длины в три строки.

Использование в Excel 2019, 2016,...

Здесь мы используем метод PA_Sets_And, чтобы узнать, содержится ли ячейка (B2) в диапазоне всего набора (A2:A11). Не так круто, как для Excel 365, но немного лучше, чем ВПР :-)

Ну, Microsoft Excel не обрабатывает встроенные операции над множествами. Но вы можете эмулировать VBA, используя функцию MATCH и обработку ошибок.

Вот код, который работал для меня (я предполагаю, что у вас заголовок в первой строке):

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

Вы можете просто использовать формулу ниже, чтобы получить результат

= ЕСЛИ (НИЖНИЙ (A4)= НИЖНИЙ (B4); ""; A4)

Я удивлен на нескольких уровнях:
(1) 2020 год... и все еще нет установленных функций в Excel
(2) Ответ, получивший наибольшее количество голосов (с 2018 года), очень непрактичен: в реальном времени наборы данных не поступают аккуратно со вставленными пустыми строками, в которых отсутствует значение, по сравнению с другим набором данных; что является предварительным условием для этого решения.

Наиболее практичным решением (хотя до сих пор неловко, ты слышишь нас, Microsoft???) является работа вокруг с помощью сводной таблицы:

  • Добавьте столбец в набор A, с именем столбца "set_name" и всеми значениями в столбце, установленными на "A" -> поворотный ввод A
  • Добавьте столбец в набор B, с именем столбца "set_name" и всеми значениями в столбце, установленными на "B" -> поворотный ввод B
  • скопировать сводный вход B (без имен столбцов;-)) под сводный вход A, чтобы сформировать объединенный диапазон -> объединенный диапазон
  • создать сводную таблицу из объединенного диапазона с
    --- "имена наборов", используемые для формирования столбцов сводной таблицы
    --- функция сводной таблицы установлена ​​на "count()"

Результатом является своего рода сводная таблица с горячим кодированием:

  • 1-й столбец: объединенный набор A и B (также известный как ВСЕ возникающие значения)
  • 2-й столбец: 1-значения только для элементов, входящих в набор A
    (предостережение: предполагается, что A содержит только УНИКАЛЬНЫЕ элементы. В противном случае возможны
    значения> 1)
  • 3-й столбец: 1-значения только для элементов, входящих в набор B
    (применяется то же предостережение, что и для набора A)
  • Столбец "Итого": значения, показывающие "2", существуют в обоих наборах

Результирующую сводную таблицу можно легко отфильтровать по различным наборам и пересечениям с помощью значений в столбцах 2 (он же "набор A"),3 (он же "набор B") и 4 (он же "Набор A И набор B").

Другие вопросы по тегам