例如,我有一个 xls,其中:
我需要以下内容:
使用 SQL 或 Python 对元素列表进行设置操作似乎很容易。但是如何在xls中做到这一点呢?
注意:它应该是一种自动化,只需最少的复制粘贴和点击。例如,我不想将 A 复制粘贴到 B 下面,然后“消除重复项”以获得 A 并集 B。
仅靠 Excel 似乎无法完成这项工作。但是,有可用的加载项。您可能想测试免费开源的 Power Analytics for Excel。它带有一些完全符合您要求的功能:
Excel 365 中的用法
在 Excel 365 Power Analytics for 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 酷,但比 VLOOKUP 好一点:-)
Microsoft Excel 不处理内置的集合运算。但是您可以使用 MATCH 函数和 错误处理通过 VBA 进行模拟。
这是对我有用的代码(我假设您的标题位于第一行):
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
您可以简单地使用下面的公式来获得结果
=IF(下(A4)=下(B4),"",A4)
我在几个层面上感到惊讶:
(1) 现在已经2020年了....Excel中仍然没有设置函数
(2) 得票最高的答案(从 2018 年开始)非常不切实际:在现实生活中,与另一个数据集相比,在缺少值的情况下插入空行的数据集并不整齐;这是该解决方案的前提。
最实用的解决方案(虽然仍然很尴尬;你听到我们了吗,微软???)是在数据透视表的帮助下解决:
结果是一种“单热编码”数据透视表,其中:
可以通过第 2 列(也称为“集合 A”)、第 3 列(又称为“集合 B”)和第 4 列(又称为“集合 A 和集合 B”)中的值,轻松地在不同集合和交集上过滤生成的数据透视表。
此解决方案适用于 Microsoft 365,并基于我在 另一篇文章中解释的方法。
对上述帖子代码的唯一修改是将LET的计算包装在UNIQUE公式中,以便我们得到一个实际的Set,如下所示:
=LAMBDA(array_a, array_b,
LET(
scanResult, IF(
COUNTA(array_a) > COUNTA(array_b),
SCAN(
"",
array_a,
LAMBDA(accumulator, current, XLOOKUP(current, array_b, array_b))
),
SCAN(
"",
array_b,
LAMBDA(accumulator, current, XLOOKUP(current, array_a, array_a))
)
),
UNIQUE(FILTER(scanResult, NOT(ISNA(scanResult))))
)
)