Сравните и покажите различия в двух столбцах, затем покажите различия и в нескольких столбцах

#excel #vba

#excel #vba

Вопрос:

У меня есть лист с данными в 2 столбцах, A и B:

 --A--     --B--
Apple     57
Orange    62
Lime      45
Orange    58
Apple     57
Orange    78
Lime      23
Melon     15
  

Мне нужно выполнить поиск дубликатов в столбце A, затем, если они есть, найдите их значение в столбце B. Если они разные, я хочу покрасить ячейку в столбце A в красный цвет, показать другое значение этой записи в столбце C и показать сообщение о том, сколько существует безразличий. Если в столбце A более 2 записей, а в столбце B — несколько разных значений, тогда я хочу показать другие значения в столбцах C, D, E и т. Д. Что-то вроде этого:

 --A--     --B--   --C--   --D--
 Apple     57
 Orange    62       58     78
 Lime      45       23
 Orange    58       62     78
 Apple     57
 Orange    78       58     62
 Lime      23       45
 Melon     15
  

У меня есть код, который почти делает это, что означает, что он показывает различия в столбце C, если в столбце A. Есть только два одинаковых значения. Однако, если в столбце A более 2 одинаковых значений, то он дает неполные данные для столбцов C, D и т. Д. Вот так:

 --A--     --B--   --C--
 Apple     57
 Orange    62       58  
 Lime      45       23
 Orange    58       78 
 Apple     57
 Orange    78       62 
 Lime      23       45
 Melon     15
  

Вот код:

 Dim pos As Variant 'match index
Dim rows As Integer
Dim i As Variant
Sheets("Chain").Range("C1:C1000").ClearContents
rows = Range("A:A").End(xlDown).Row 'Getting total row number
For i = 1 To rows

    'Find position of next occurence
    If i = 1 Then
    pos = WorksheetFunction.Match(Range("A" amp; i).Value, Range("A" amp; i amp; ":A" amp; rows   1), 0)   i
    Else
    pos = WorksheetFunction.Match(Range("A" amp; i).Value, Range("A" amp; i   1 amp; ":A" amp; rows   1), 0)   i
    End If
    'If there is no next occurence find previous occurences
    If pos = 0 Then
    pos = WorksheetFunction.Match(Range("A" amp; i).Value, Range("A1:A" amp; i - 1), 0)

    End If

    On Error Resume Next

    Dim j As Integer
    Dim pos1 As Integer
    Dim pos2 As Integer
    j = i

    'While next occurence is same skip it
    While (Cells(i, 2) = Cells(pos, 2)) And (j < rows)
        j = 1   pos
        pos1 = pos
        pos = WorksheetFunction.Match(Range("A" amp; i).Value, Range("A" amp; j amp; ":A" amp; rows   1), 0)   j - 1
        pos2 = pos
        If pos1 = pos2 Then GoTo Endwhile

    Wend
Endwhile:

    'Writing into Column C
    Range("C" amp; i).Value = Cells(pos, 2).Value
    ' Highlighting duplicate cells
    If Cells(i, 2) <> Cells(i, 3) Then

    Range("A" amp; i).Interior.Color = TextBox5.BackColor
    End If

    If Cells(i, 2) = Cells(i, 3) Then Cells(i, 3) = ""
    pos = 0

Next i

'Final Message

Dim totdif As Integer
totdif = WorksheetFunction.CountA(Range("C1:C1" amp; rows))
If totdif = 0 Then
MsgBox "No indifferences found"
Else
MsgBox "Indifferences found: " amp; totdif
End If
  

Ответ №1:

У меня возникнет соблазн сделать это таким образом, используя словарь для сбора уникальных значений:

 Sub Tester()

    Dim dict As Object, rng As Range, rw As Range, tmp, u As Long, vA, vB, e, n
    
    Set dict = CreateObject("scripting.dictionary")
    Set rng = ActiveSheet.Range("A1", Cells(Rows.Count, 1).End(xlUp)).Resize(, 2)
    rng.Offset(0, 2).Resize(, 50).ClearContents 'clear any previous results
    
    'first collect all ColB values for each unique colA value
    For Each rw In rng.Rows
        vA = rw.Cells(1).Value
        vB = rw.Cells(2).Value
        If Not dict.exists(vA) Then
            dict.Add vA, Array(vB) 'new key
        Else
            tmp = dict(vA)
            'already have this value for this key?
            If IsError(Application.Match(vB, tmp, 0)) Then
                u = UBound(tmp)   1
                ReDim Preserve tmp(u)
                tmp(u) = vB 'add the new value
                dict(vA) = tmp
            End If
        End If
    Next rw
    
    'loop the rows again and add all the values
    For Each rw In rng.Rows
        vA = rw.Cells(1).Value
        vB = rw.Cells(2).Value
        
        tmp = dict(vA)
        'have >1 value ?
        If UBound(tmp) > 0 Then
            rw.Cells(1).Font.Color = vbRed
            n = n   1
            For Each e In tmp
                'add if doesn't match the existing value on this row
                If e <> vB Then Cells(rw.Row, Columns.Count).End(xlToLeft).Offset(0, 1).Value = e
            Next e
        End If
    Next rw
    MsgBox n amp; " duplicates" 
End Sub
  

Комментарии:

1. Похоже, это работает. Не могли бы вы также добавить выделение ячеек красным цветом, которые имеют разные значения в столбце A, и сообщение о том, сколько значений неверно в конце сценария?