寻找两组之间的唯一性
Finding unique between two groups
谁能告诉我如何根据以下 table 编写一个公式来识别所有拥有不同产品或产品基础发生变化的客户 ID?
结果:在 C 列上显示具有不同产品的客户 ID 1 和 3
我认为 COUNTIFS 可以有效地解决这个问题
=COUNTIFS($A:$A,"="&A2,$B:$B,"="&B2)
我在C列的公式是:
=COUNTIFS($A:$A;A2;$B:$B;B2)=COUNTIF$A:$A;A2)
无论客户是否一直购买相同的产品,此公式都将 return True/False。您对那些购买了 不同 产品的客户感兴趣,因此您希望在这种情况下按 FALSE 选项进行过滤:
如果你有 E365,你就有 UNIQUE 和 FILTER 等功能,所以你可以使用公式而不是手动过滤范围。
我认为 excel 函数不能为您提供 non-single 结果的串联答案。 VBA 可以解决这个问题。
假设您的数据将是:
- 数据范围 A2:B11(在 A1:B1 中排除了 headers),假定 non-blank 个单元格
- 按 CustomerID(按任何类型的订单)排序,VBA 脚本将 运行 沿着您排序的 CustomerID 列
- result(s)(CustomerIDs 有超过 1 个产品)将从 C2 沿着 C 列打印。因此,请确保清除 C 列中的现有数据。
VBA 脚本应该是:
Sub list()
Dim i As Integer
Dim cell As Range
Dim d_cust() As Variant
Set customerID = ActiveSheet.Range("$A:" & Range("A2").End(xlDown).Address)
Set Product = ActiveSheet.Range("$B:" & Range("B2").End(xlDown).Address)
i = 0
For Each cell In customerID
On Error Resume Next
If cell.Value <> d_cust(i - 1) And Evaluate("=SUMPRODUCT((" & customerID.Address & "=" & cell.Value & ")/(COUNTIFS(" & Product.Address & "," & Product.Address & "," & customerID.Address & "," & Chr(34) & cell.Value & Chr(34) & ")+(" & customerID.Address & "<>" & cell.Value & ")))") > 1 Then
ReDim Preserve d_cust(0 To i) As Variant
d_cust(i) = cell.Value
ActiveSheet.Cells((2 + i), 3) = cell.Value
i = i + 1
End If
Next cell
End Sub
这是C2中C列的结果,每个单元格1个结果。你可以改变
通过更改起始单元格和方向 此处 的结果 row/column:ActiveSheet.Cells((2 + i), 3) = cell.Value
如@Foxfire 和 Burns 和 Burns 所述,如果您有 O365,则可以使用 Filter 和 Unique。它看起来像这样:
=UNIQUE(FILTER(A2:A11,COUNTIFS(A2:A11,A2:A11,B2:B11,"<>"&B2:B11)<>0))
如果您没有 O365,您可以恢复为 pull-down 公式。如果你在 D2 中输入它,比如说,它将是:
=IFERROR(INDEX(A:A,MATCH(1,(COUNTIFS(A:A,A:A,B:B,"<>"&B:B)<>0)*(COUNTIF(D1:D,A:A)=0),0)),"")
作为数组公式输入。
检索具有多个项目的唯一值(字典)
- 调整常量部分中的值。
Option Explicit
Sub RetrieveMultiProductIds()
' Source
Const sName As String = "Sheet1"
Const sFirstCellAddress As String = "A1"
' Destination
Const dName As String = "Sheet1"
Const dFirstCellAddress As String = "C1"
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim ws As Worksheet: Set ws = wb.Worksheets(sName)
' Reference the source data range and write its values to an array.
Dim srg As Range
Dim srCount As Long
Dim fCell As Range: Set fCell = ws.Range(sFirstCellAddress)
With fCell.CurrentRegion
Set srg = fCell.Resize(.Row + .Rows.Count _
- fCell.Row, .Column + .Columns.Count - fCell.Column)
srCount = .Rows.Count - 1
End With
If srCount < 1 Then Exit Sub ' too few rows
Set srg = srg.Resize(srCount, 2).Offset(1)
Dim sData As Variant: sData = srg.Value
' Store the unique ids in the keys and their corresponding values
' in the items of a dictionary. If for the same key a different value
' is encountered, flag the item with "@".
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
dict.CompareMode = vbTextCompare
Dim sKey As Variant
Dim r As Long
Dim drCount As Long
For r = 1 To srCount
sKey = sData(r, 1)
If dict.Exists(sKey) Then
If dict(sKey) <> "@" Then
If dict(sKey) <> sData(r, 2) Then
dict(sKey) = "@"
drCount = drCount + 1
End If
End If
Else
dict(sKey) = sData(r, 2)
End If
Next r
If drCount = 0 Then Exit Sub
' Write the flagged keys to a 2D one-based one-column array.
Dim dData As Variant: ReDim dData(1 To drCount, 1 To 1)
r = 0
For Each sKey In dict.Keys
If dict(sKey) = "@" Then
r = r + 1
dData(r, 1) = sKey
End If
Next sKey
' Write the values from the array to the destination range and clear below.
With wb.Worksheets(dName).Range(dFirstCellAddress)
.Resize(r).Value = dData
.Resize(.Worksheet.Rows.Count - .Row - r + 1).Offset(r).Clear
End With
MsgBox "Number of found multi-product ids: " & r, vbInformation
End Sub
谁能告诉我如何根据以下 table 编写一个公式来识别所有拥有不同产品或产品基础发生变化的客户 ID?
结果:在 C 列上显示具有不同产品的客户 ID 1 和 3
我认为 COUNTIFS 可以有效地解决这个问题
=COUNTIFS($A:$A,"="&A2,$B:$B,"="&B2)
我在C列的公式是:
=COUNTIFS($A:$A;A2;$B:$B;B2)=COUNTIF$A:$A;A2)
无论客户是否一直购买相同的产品,此公式都将 return True/False。您对那些购买了 不同 产品的客户感兴趣,因此您希望在这种情况下按 FALSE 选项进行过滤:
如果你有 E365,你就有 UNIQUE 和 FILTER 等功能,所以你可以使用公式而不是手动过滤范围。
我认为 excel 函数不能为您提供 non-single 结果的串联答案。 VBA 可以解决这个问题。
假设您的数据将是:
- 数据范围 A2:B11(在 A1:B1 中排除了 headers),假定 non-blank 个单元格
- 按 CustomerID(按任何类型的订单)排序,VBA 脚本将 运行 沿着您排序的 CustomerID 列
- result(s)(CustomerIDs 有超过 1 个产品)将从 C2 沿着 C 列打印。因此,请确保清除 C 列中的现有数据。
VBA 脚本应该是:
Sub list()
Dim i As Integer
Dim cell As Range
Dim d_cust() As Variant
Set customerID = ActiveSheet.Range("$A:" & Range("A2").End(xlDown).Address)
Set Product = ActiveSheet.Range("$B:" & Range("B2").End(xlDown).Address)
i = 0
For Each cell In customerID
On Error Resume Next
If cell.Value <> d_cust(i - 1) And Evaluate("=SUMPRODUCT((" & customerID.Address & "=" & cell.Value & ")/(COUNTIFS(" & Product.Address & "," & Product.Address & "," & customerID.Address & "," & Chr(34) & cell.Value & Chr(34) & ")+(" & customerID.Address & "<>" & cell.Value & ")))") > 1 Then
ReDim Preserve d_cust(0 To i) As Variant
d_cust(i) = cell.Value
ActiveSheet.Cells((2 + i), 3) = cell.Value
i = i + 1
End If
Next cell
End Sub
这是C2中C列的结果,每个单元格1个结果。你可以改变
通过更改起始单元格和方向 此处 的结果 row/column:ActiveSheet.Cells((2 + i), 3) = cell.Value
如@Foxfire 和 Burns 和 Burns 所述,如果您有 O365,则可以使用 Filter 和 Unique。它看起来像这样:
=UNIQUE(FILTER(A2:A11,COUNTIFS(A2:A11,A2:A11,B2:B11,"<>"&B2:B11)<>0))
如果您没有 O365,您可以恢复为 pull-down 公式。如果你在 D2 中输入它,比如说,它将是:
=IFERROR(INDEX(A:A,MATCH(1,(COUNTIFS(A:A,A:A,B:B,"<>"&B:B)<>0)*(COUNTIF(D1:D,A:A)=0),0)),"")
作为数组公式输入。
检索具有多个项目的唯一值(字典)
- 调整常量部分中的值。
Option Explicit
Sub RetrieveMultiProductIds()
' Source
Const sName As String = "Sheet1"
Const sFirstCellAddress As String = "A1"
' Destination
Const dName As String = "Sheet1"
Const dFirstCellAddress As String = "C1"
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim ws As Worksheet: Set ws = wb.Worksheets(sName)
' Reference the source data range and write its values to an array.
Dim srg As Range
Dim srCount As Long
Dim fCell As Range: Set fCell = ws.Range(sFirstCellAddress)
With fCell.CurrentRegion
Set srg = fCell.Resize(.Row + .Rows.Count _
- fCell.Row, .Column + .Columns.Count - fCell.Column)
srCount = .Rows.Count - 1
End With
If srCount < 1 Then Exit Sub ' too few rows
Set srg = srg.Resize(srCount, 2).Offset(1)
Dim sData As Variant: sData = srg.Value
' Store the unique ids in the keys and their corresponding values
' in the items of a dictionary. If for the same key a different value
' is encountered, flag the item with "@".
Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
dict.CompareMode = vbTextCompare
Dim sKey As Variant
Dim r As Long
Dim drCount As Long
For r = 1 To srCount
sKey = sData(r, 1)
If dict.Exists(sKey) Then
If dict(sKey) <> "@" Then
If dict(sKey) <> sData(r, 2) Then
dict(sKey) = "@"
drCount = drCount + 1
End If
End If
Else
dict(sKey) = sData(r, 2)
End If
Next r
If drCount = 0 Then Exit Sub
' Write the flagged keys to a 2D one-based one-column array.
Dim dData As Variant: ReDim dData(1 To drCount, 1 To 1)
r = 0
For Each sKey In dict.Keys
If dict(sKey) = "@" Then
r = r + 1
dData(r, 1) = sKey
End If
Next sKey
' Write the values from the array to the destination range and clear below.
With wb.Worksheets(dName).Range(dFirstCellAddress)
.Resize(r).Value = dData
.Resize(.Worksheet.Rows.Count - .Row - r + 1).Offset(r).Clear
End With
MsgBox "Number of found multi-product ids: " & r, vbInformation
End Sub