Проверка наличия хотя бы одного идентичного значения в разных диапазонах столбцов на основе идентификатора

#excel #vba

#excel #vba

Вопрос:

Я пытаюсь решить проблему в VBA и после долгого просмотра веб-страниц в поисках решений я действительно надеюсь, что кто-нибудь сможет мне помочь.
На самом деле это не очень сложная задача, но с очень небольшим знанием программирования и VBA, как новичок, я надеюсь, что смогу найти полезный совет или решение с помощью сообщества.

Итак, моя проблема заключается в следующем:

У меня есть таблица с 3 столбцами, первый заполнен числом для использования в качестве идентификатора. Столбцы 2 и 3 имеют разные значения, которые необходимо сравнить:
рисунок

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

Таким образом, нет необходимости совпадать со всеми именами желаемых диапазонов столбцов. Достаточно одного совпадения имен. Если имя совпадает, оно должно автоматически заполнить новый столбец «результат» с 1 для совпадения (0 для отсутствия совпадения).

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

     Dim ID_counter As Long
    ID_counter = 1
    
    If Cell.Value = ID_counter IN Range("Column1")
        Then Range("Column2").Select
        AND Range("Column3").Select
        WHERE ID_counter is the same
        
    In Column4 (If one Cell.Value IN Range("Column2-X:Column2-Y")
                IS IDENTICAL TO Range("Column3-X:Column3-Y"), return 1, else return 0

End Sub
  

Заранее большое спасибо за вашу помощь!

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

1. Я не думаю, что для этого вам нужен VBA (конечно, не нужно ничего выбирать). Я думаю, это можно сделать с помощью формулы COUNTIFS.

2. @SJR Не уверен в этом, потому что диапазоны отличаются по размеру, поэтому я думаю, что необходимо выбрать диапазон. И набор данных, который у меня есть, слишком длинный, чтобы решить это вручную…

3. Вы имеете в виду, что столбцы B и C имеют разную длину? Я тоже не думаю, что это имеет значение. Просто включите проверку того, что B не является пустым.

4. @SJR, некоторые ячейки B на самом деле пустые, например B4, B6 и B9, как показано на рисунке. Длина B и C не отличается, но на основе идентификатора в столбце A диапазон B и C, который необходимо сравнить, каждый раз отличается… надеюсь, это понятно…

5. Возможно, опубликовать образец немного большего размера? Почему нет 1 в строке 3 или 10 — это важно?

Ответ №1:

Это работает для вашего примера, поэтому, возможно, вы можете обобщить его. Формула в D2

 =IF(A2=A1,"",MAX(IF($A$2:$A$10=A2,COUNTIF($B$2:$B$10,$C$2:$C$10))))
  

и является формулой массива, поэтому его необходимо подтвердить с помощью CTRL, SHIFT и ENTER.

введите описание изображения здесь

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

1. Спасибо @SJR! Ваше решение действительно работает, хотя в какой-то момент оно не только выдает 0 = not true, 1 = true, но по какой-то причине оно также выдает число 1087… Должно быть связано с базовыми данными. Большое спасибо за вашу помощь!!

Ответ №2:

Альтернатива массива с помощью Match() функции

Этот подход сравнивает строковые элементы столбцов B и C , передавая два массива (именованные b , c ) в качестве аргументов (см. раздел c.f. [1] ):

 chk = Application.Match(b, c, 0)
  

Результирующий chk массив отражает все результаты поиска элементов первого массива через (основанные на 1) индексы позиций соответствующих элементов во втором массиве.

Не-результаты возвращают Error 2042 значение (см. раздел ); предполагается, что данные сгруппированы по [2]b) идентификатору.

 Sub OneFindingPerId()
'[0]get data
    Dim data: data = Sheet1.Range("A1:D10")                 ' << project's sheet Code(Name)
    Dim b:    b = Application.Index(data, 0, 2)             ' 2nd column (B)
    Dim c:    c = Application.Index(data, 0, 3)             ' 3rd column (C)
'[1]get position indices of identic strings via Match() function
    Dim chk:  chk = Application.Match(b, c, 0)              ' found row nums of a items in b
'[2]loop found position indices (i.e. no error 2042)
    Dim i As Long
    For i = 2 To UBound(chk)                                ' omit header row
        'a) define start index of new id and initialize result with 0
        If data(i, 1) <> data(i - 1, 1) Then
            Dim newId As Long: newId = i
            data(newId, 4) = 0
        End If
        'b) check if found row index corresponds to same id
        If Not IsError(chk(i, 1)) Then                        ' omit error 2042 values
            If data(chk(i, 1), 1) = data(i, 1) Then           ' same ids?
                If data(newId, 4) = 0 Then data(newId, 4) = 1 ' ~> result One if first occurrence
            End If
        End If
    Next i
'[3]write results
    Sheet1.Range("A1").Resize(UBound(data), UBound(data, 2)) = data
End Sub

  

Ответ №3:

Сначала введите эту пользовательскую функцию в стандартный модуль:

 Public Function zool(r1, r2, r3) As Integer
    Dim i As Long, v1 As Long, v2 As String
    Dim top As Long, bottom As Long
    
    zool = 0
    v1 = r1.Value
    top = r1.Row
    
    '   determine limits to check
    
    For i = top To 9999
        If v1 <> r1.Offset(i - top, 0).Value Then
            Exit For
        End If
    Next i
    bottom = i - 1
    
    For i = top To bottom
        v2 = Cells(i, "B").Value
            If v2 <> "" Then
                For j = top To bottom
                    If v2 = Cells(j, "C").Value Then zool = 1
                Next j
            End If
        Next i
                    
End Function
  

Затем в D2 введите:

 =IF(OR(A2="",A2=A1),"",zool(A2,B2,C2))
  

и скопируйте вниз:

введите описание изображения здесь

(это предполагает, что данные сначала были отсортированы или упорядочены по идентификатору)

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

1. к вашему сведению, альтернатива массиву путем Match() сравнения обоих массивов столбцов 🙂

2. @Gary’Sstudent Спасибо за вашу помощь! Очень признателен!