Найти совпадения строк, равных по нескольким столбцам - PullRequest
0 голосов
/ 06 июля 2018

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

Что мне нужно, так это способ проверить, играл ли игрок ранее того же игрока, и выделить имя этого игрока. Так что ищите игрока и его противника и посмотрите, соответствует ли он строке в других столбцах.

Ответы [ 3 ]

0 голосов
/ 06 июля 2018

Вы можете использовать условное форматирование, чтобы сделать это. Смотрите изображение ниже: enter image description here

Три таблицы называются Раунд1, Раунд2, Раунд3. Я добавил вспомогательный столбец, в котором содержится формула условного форматирования, и расположил их по вертикали, чтобы я мог сделать снимок экрана, который подходит здесь.

Вот формулы. Обратите внимание, что они должны быть введены в массив, используя Ctrl + Shift + Ввод сочетание клавиш:

H2:

=OR(
         [@[Player A]]&[@[Player B]]=Round2[Player A]&Round2[Player B],[@[Player B]]&[@[Player A]]=Round2[Player A]&Round2[Player B],
         [@[Player A]]&[@[Player B]]=Round3[Player A]&Round3[Player B],[@[Player B]]&[@[Player A]]=Round3[Player A]&Round3[Player B]
)

H8:

=OR(
         [@[Player A]]&[@[Player B]]=Round1[Player A]&Round1[Player B],[@[Player B]]&[@[Player A]]=Round1[Player A]&Round1[Player B],
         [@[Player A]]&[@[Player B]]=Round3[Player A]&Round3[Player B],[@[Player B]]&[@[Player A]]=Round3[Player A]&Round3[Player B]
)

H14:

=OR(
         [@[Player A]]&[@[Player B]]=Round1[Player A]&Round1[Player B],[@[Player B]]&[@[Player A]]=Round1[Player A]&Round1[Player B],
         [@[Player A]]&[@[Player B]]=Round2[Player A]&Round2[Player B],[@[Player B]]&[@[Player A]]=Round2[Player A]&Round2[Player B]
)

... и вот что вам нужно добавить в диалоговое окно условного форматирования для первой таблицы:

enter image description here

Это довольно легко изменить, чтобы обрабатывать дальнейшие раунды, но это сложный и несколько неэффективный подход по сравнению с использованием объекта Dictionary через VBA.

0 голосов
/ 06 июля 2018

Вот как бы я сделал это сам, используя словарь VBA. Он обрабатывает любые таблицы, содержащие строку «Round» в имени таблицы.

Option Explicit

Sub HighlightDuplicates()

Dim lo As ListObject
Dim lr As ListRow
Dim dic As Object
Dim ws As Worksheet
Dim sTemp As String
Dim sPlayerB As String
Dim sPlayerA As String

Set dic = CreateObject("Scripting.Dictionary")

For Each ws In ActiveWorkbook.Worksheets
    For Each lo In ws.ListObjects
        If InStr(lo.Name, "Round") Then
            lo.Range.Interior.Pattern = xlNone
            For Each lr In lo.ListRows
                sPlayerA = UCase(Intersect(lr.Range, lo.ListColumns("Player A").Range))
                sPlayerB = UCase(Intersect(lr.Range, lo.ListColumns("Player B").Range))
                If sPlayerA > sPlayerB Then
                    sTemp = sPlayerB
                    sPlayerB = sPlayerA
                    sPlayerA = sTemp
                End If
                sTemp = sPlayerA & "|" & sPlayerB
                If Not dic.exists(sTemp) Then
                    dic.Add sTemp, False
                Else
                    dic(sTemp) = True
                End If
            Next lr
        End If
    Next lo
Next ws


For Each ws In ActiveWorkbook.Worksheets
    For Each lo In ws.ListObjects
        If InStr(lo.Name, "Round") Then
            For Each lr In lo.ListRows
                sPlayerA = UCase(Intersect(lr.Range, lo.ListColumns("Player A").Range))
                sPlayerB = UCase(Intersect(lr.Range, lo.ListColumns("Player B").Range))
                If sPlayerA > sPlayerB Then
                    sTemp = sPlayerB
                    sPlayerB = sPlayerA
                    sPlayerA = sTemp
                End If
                sTemp = sPlayerA & "|" & sPlayerB
                If dic(sTemp) Then
                    Intersect(lr.Range, lo.ListColumns("Player A").Range).Interior.Color = vbYellow
                    Intersect(lr.Range, lo.ListColumns("Player B").Range).Interior.Color = vbYellow
                End If
            Next lr
        End If
    Next lo
Next ws

End Sub

И вот результат:

enter image description here

0 голосов
/ 06 июля 2018

Что ж, это может быть интересно, очевидно, есть разные способы сделать это, но без VBA способ получить выделенные ячейки - через условное форматирование.

Пример ниже, очевидно, упрощен, но дает вам представление о том, как вы можете подойти к этому.

  • 1) Я создал лист с тремя раундами, как показано ниже:

enter image description here

  • 2) Я добавил условное форматирование в столбцы B, D и F, чтобы увидеть, имеет ли в ячейке справа последнее введенное значение. Вот так:

    =$C4=INDIRECT(CELL("ADDRESS"))
    
  • 3) Очевидно, вам нужно обратное форматирование для столбцов C, E и G, например:

    =$B=INDIRECT(CELL("ADDRESS"))
    
  • 4) Теперь при добавлении 4-го раунда (очевидно, вы можете настроить форматирование, когда вы хотите создать новую строку), вы вводите значение и нажимаете ENTER.

  • 5) Вывод будет таким:

enter image description here

  • 6) Мэтт сыграл Сару, Эмму и Джона

:)

EDIT1: Повторное чтение вашего вопроса, это не совсем то, что вам нужно. Я попробую настроить это!

EDIT2: См. Ниже мою попытку использовать VBA и фактически ответить на ваш вопрос:)

  • 1) Использование события изменения рабочего листа VBA:

    Private Sub Worksheet_Change(ByVal Target As Range)
    
    Dim Player As String, Opponent As String
    Dim C As Range
    
    'Check if a player name has been entered
    On Error Resume Next
    If InStr(1, Sheets(1).Cells(2, Target.Column), "Player", vbTextCompare) <> 0 Then
        If Right(Sheets(1).Cells(2, Target.Column).Value, 1) = "A" Then
            Opponent = Target.Offset(0, 2).Value
        ElseIf Right(Sheets(1).Cells(2, Target.Column).Value, 1) = "B" Then
            Opponent = Target.Offset(0, -2).Value
        End If
        Player = Target.Value
        If Opponent <> "" And Player <> "" Then
            Sheets(1).UsedRange.Cells.Interior.Pattern = xlNone
            With Sheets(1).UsedRange
                Set C = .Find(Opponent, Lookat:=xlWhole)
                If Not C Is Nothing Then
                    firstaddress = C.Address
                    Do
                        If C.Offset(0, 2).Value = Player Or C.Offset(0, -2).Value = Player Then
                            C.Interior.ColorIndex = 37
                        End If
                        Set C = .FindNext(C)
                    If C Is Nothing Then
                        GoTo Donefinding
                    End If
                    Loop While C.Address <> firstaddress
                End If
    Donefinding:
            End With
        End If
    End If
    
    End Sub
    
  • 2) Вставьте это в код листа (1)

  • 3) Убедитесь, что в строке 2 указано «Player A» или «Player B» в качестве значения

Что делает этот код:

  • A - проверяет, добавляете ли вы имя игроку A или игроку B
  • B - Если это так, он сначала очистит все форматирование, выполненное в предыдущем запуске
  • C - Затем используйте .findnext, чтобы получить любой матч только что добавленного игрока
  • D - В зависимости от A или B, проверит, является ли противник рядом с любой найденной ячейкой одинаковым
  • E - Если это так, он выделит эти ячейки

Я уверен, что код можно сделать с некоторой очисткой, но он работает:)

...