寻找两组之间的唯一性

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