Как сравнить и показать различия по нескольким столбцам в Microsoft Excel - PullRequest
1 голос
/ 27 октября 2019

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

--A--     --B--
Apple     57
Orange    62
Lime      45
Orange    58
Apple     57

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

--A--     --B--   --C--
 Apple     57
 Orange    62       58
 Lime      45
 Orange    58       62
 Apple     57

Пожалуйста, помогите мне с этим, я знаю, как сравнивать значение в одном столбце, но потом не знаю, как искать дополнительное значение для них в другом столбце.

Ответы [ 3 ]

1 голос
/ 27 октября 2019

Поскольку я все еще нахожусь в процессе обучения, возможно, это не лучшее решение, но кажется, что оно работает `` `

' inoG

Sub Solution()

Dim rows As Integer
rows = Range("a1").End(xlDown).Row 'Getting total row number

Dim dt As Variant
dt = Range("a1:c" & rows) 'data into array '

'forward search
For i = 1 To rows
    For j = i + 1 To rows
        If dt(i, 1) = dt(j, 1) And dt(i, 2) <> dt(j, 2) Then
            dt(i, 3) = dt(j, 2)
            GoTo Continue1
        End If
    Next j
Continue1:
Next i


'backward search
For i = rows To 1 Step -1
   For j = i - 1 To 1 Step -1
        If dt(i, 1) = dt(j, 1) And dt(i, 2) <> dt(j, 2) Then
            dt(i, 3) = dt(j, 2)
            GoTo Continue2
        End If
    Next j
Continue2:
Next i

'filling row C and Highlighting
For i = 1 To rows
    If Not IsEmpty(dt(i, 3)) Then
        Cells(i, 3) = dt(i, 3)
        Range("A" & i).Interior.ColorIndex = 3
        End If
Next i

'Final Message
Dim totdif As Integer
totdif = WorksheetFunction.CountA(Range("C1:C1" & rows))
MsgBox totdif

End Sub

0 голосов
/ 28 октября 2019

Я думаю, что вы можете сделать это с помощью формул.

Если вы обеспокоены тем, что пользователи изменяют формулу, используйте Table (и, возможно, даже защитите столбец формулы, хотя для этого потребуетсяКод VBA, позволяющий расширить таблицу). Таким образом, диапазоны будут динамически настраиваться на добавление и удаление данных, и пользователям не нужно будет редактировать формулу:

С таблицей, переименованной Fruits, и столбцами, названными как на скриншоте:

=IFERROR(AGGREGATE(14,6,1/(([@Fruit]=[Fruit])*([@Value]<>[Value]))*[Value],1),"")

Использование условного форматирования для форматирования ячеек

enter image description here

РЕДАКТИРОВАНИЕ: Я думаю, что табличный подход даствам лучшее решение, но для подхода VBA я бы использовал словарь и набор различных значений, связанных с фруктами.

Предполагая, что ваш первый столбец называется "Фрукт" (или что-то, что вы можете использовать в Find, или даже известный адрес), вы можете использовать следующее для создания столбца альтернативных значений для каждого элемента.

'Add reference to Microsoft Scripting Runtime
'   or use late binding
Option Explicit
Sub diffs()
    Dim myD As Dictionary
    Dim vData As Variant
    Dim rData As Range, C As Range
    Dim wsSrc As Worksheet
    Dim I As Long, V As Variant
    Dim colVals As Collection


'Find the table
Set wsSrc = Worksheets("sheet2") 'or wherever
With wsSrc.Cells
    Set C = .Find(what:="Fruit", after:=.Item(1, 1), LookIn:=xlValues, lookat:=xlWhole, MatchCase:=True)
    If Not C Is Nothing Then
        With wsSrc
            Set rData = .Range(C, .Cells(.Rows.Count, C.Column).End(xlUp)).Resize(columnsize:=3)
            vData = rData
        End With
    Else
        MsgBox "No data table"
        Exit Sub
    End If
End With

'Collect the data into a dictionary
'Max 2 different values per fruit

Set myD = New Dictionary
    myD.CompareMode = TextCompare
    For I = 2 To UBound(vData)
        If Not myD.Exists(vData(I, 1)) Then
            Set colVals = New Collection
            colVals.Add Item:=vData(I, 2), Key:=CStr(vData(I, 2))

            myD.Add Key:=vData(I, 1), Item:=colVals
        Else
            On Error Resume Next 'omit duplicate values
            myD(vData(I, 1)).Add Item:=vData(I, 2), Key:=CStr(vData(I, 2))
            On Error GoTo 0
        End If
    Next I

'Populate column 3

For I = 2 To UBound(vData, 1)
    Set colVals = myD(vData(I, 1))
        vData(I, 3) = ""
        If colVals.Count > 1 Then
            For Each V In colVals
                If V <> vData(I, 2) Then vData(I, 3) = V
            Next V
        End If
Next I

Application.ScreenUpdating = False
With rData
    .Clear
    .Value = vData
    For I = 2 To UBound(vData)
        If vData(I, 3) <> "" Then
            With rData.Cells(I, 1)
                .Font.Color = vbWhite
                .Font.Bold = True
                .Interior.Color = vbRed
            End With
        End If
    Next I
End With

End Sub
0 голосов
/ 28 октября 2019

В моем следующем решении использовался вспомогательный столбец до rank значения в Column B для элемента в Column A с использованием функции COUNTIFS . Затем я использовал сводную таблицу, чтобы показать среднее значение каждого ранга для каждого элемента.

Demo

Предположим, у вас есть следующие именованные диапазоны :

  • ListItem ваши данные в Column A;
  • ListValue будучи вашими данными в Column B.

Формула в ячейке C2:

=IF(COUNTIFS(ListItem,A2,ListValue,">"&B2)+1>1,"2nd Value","1st Value")

Измените ссылки на ячейки, используемые в вашем случае.

В этом решении будет создана выходная таблица с разметкой всех уникальных элементов, а затем заполнение двух разных значений (если их два) в двух последовательных столбцах рядом с каждым элементом. Для сравнения я думаю, что сводная таблица является достаточной и достаточно эффективной.

Ps, чтобы создать сводную таблицу, вам просто нужно выделить исходную таблицу, перейти на вкладку Insert и нажать кнопку Сводная таблица кнопка для создания сводной таблицы. Настройте поля следующим образом, и у вас будет что-то похожее на мой пример:

Pivot Fields


EDIT #2

Если вы хотите отобразить второе значение в Column C для каждого элемента, здесь используется подход на основе формул.

В ячейке C2 введите следующую формулу и перетащитеэто вниз:

=IFERROR(AGGREGATE(14,6,AGGREGATE(14,6,ListValue/(ListItem=A2),ROW($Z$1:INDEX($Z:$Z,COUNTIF(ListItem,A2))))/((AGGREGATE(14,6,ListValue/(ListItem=A2),ROW($Z$1:INDEX($Z:$Z,COUNTIF(ListItem,A2))))<>B2)),1),"")

Demo2.0

Логика состоит в том, чтобы использовать ListValue/(ListItem=A2), чтобы вернуть диапазон значений для каждого элемента, а затем использовать AGGREGATE функция для фильтра для всех ошибок, затем используйте

AGGREGATE(14,6,ListValue/(ListItem=A2),ROW($Z$1:INDEX($Z:$Z,COUNTIF(ListItem,A2))))<>B2

для дальнейшего фильтра диапазон допокажите второе значение (которое отличается от первого значения), затем снова используйте функцию AGGREGATE , чтобы вернуть это значение.

Дайте мне знать, если у вас есть какие-либо вопросы. Приветствия:)

...