VBA: результаты сопоставления независимо от сортировки индексов?

У меня есть 3 листа (user1, user2, результат). Каждый лист имеет три столбца (A: System_ID, B: Комментарий, C: Время последнего изменения).

Код делает это:

  1. Получает максимальное время последнего изменения между user1 и user2 в столбце c.
  2. Результатом является получение этого комментария в столбце b (рядом с максимальным временем, найденным в столбце c)
  3. поместите результат (комментарий) в столбец b в таблице результатов

Просто комментарий с последним измененным временем выигрывает и вставляется в результат WS.

В любом случае, моя проблема в том, что я могу сопоставлять индексы только в том случае, если оба индекса в столбце A имеют одинаковую сортировку/порядок.

Мне нужно сопоставить все записи в столбце A, даже если они имеют разные row.number или индекс строки.

Как индексировать соответствие независимо от порядка в столбце A

        Sub Get_LastModified_Here()
        
        Application.EnableEvents = False
        
        Dim Location1 As Workbook
        Set Location1 = GetWorkbook("C:\Users\HP\Desktop\User_1.xlsb")
        Dim Location2 As Workbook
        Set Location2 = GetWorkbook("C:\Users\HP\Desktop\User_2.xlsb")
        
        Dim SourceCell As Range, SourceRange As Range, CurrentRange As Range
        Dim rngTarget As Range
        Dim strAdr As String
        Dim vSource As Variant, vTarget As Variant, vCurrent As Variant
        Dim i As Long
        
        Set SourceRange = Workbooks("User_2.xlsb").Sheets("Data").Range("A2:" & "A1607")
        
        With SourceRange
            Set SourceRange = .Resize(.Rows.Count, .Columns.Count + 3)
        End With
        
        strAdr = SourceRange.Address
        
        Set rngTarget = Workbooks("User_1.xlsb").Worksheets("Data").Range(strAdr)
        
        Set CurrentRange = ThisWorkbook.Worksheets("Data").Range(strAdr).Offset(0, 1)
        
        vSource = SourceRange
        vTarget = rngTarget
        vCurrent = CurrentRange
        
        
        For i = 1 To UBound(vSource, 1)
             'Match Column A
             If vSource(i, 1) = vTarget(i, 1) Then
                'Check max time in Column C (user1 vs user2)
                 If vSource(i, 3) > vTarget(i, 3) Then
                    'Get max comment from ((user max)) in column B  (result ws)
                    vCurrent(i, 1) = vSource(i, 2)
                    
                ElseIf vSource(i, 3) < vTarget(i, 3) Then
                    vCurrent(i, 1) = vTarget(i, 2)
                ElseIf vSource(i, 3) = vTarget(i, 3) Then
                    vCurrent(i, 1) = vSource(i, 2)
                End If
            End If
        Next i
        
        SourceRange = vSource
        rngTarget = vTarget
        CurrentRange = vCurrent
        
        Application.EnableEvents = True
        
    End Sub             

Вот подробное объяснение проблемы (прошу прощения за буквы CAPS):

Пользователь1 Лист

У меня есть SYSTEM_ID в ## Строке 1 ##

System_ID Комментарий LastModTime ID_1 Заметки пользователя 1 12.09.2020 22:00:01

Лист User2

У меня ТАКОЙ же SYSTEM_ID в ## Row 2 ##

System_ID Комментарий LastModTime ID_1 Заметки пользователя 2 12.09.2020 22:00:02

Это то, что я ПОЛУЧАЮ в листе результатов

У меня ТАКОЙ же SYSTEM_ID, но в ## Строке 3 ##

System_ID Комментарий LastModTime ID_1

Это то, что я хочу в таблице результатов

У меня ТАКОЙ же SYSTEM_ID, но в ## Строке 3 ##

System_ID Комментарий LastModTime ID_1 Заметки пользователя 2 12.09.2020 22:00:02

Что МОГУТ делать наши коды

Получить комментарий на основе времени последнего изменения, ТОЛЬКО ЕСЛИ "ID_1" находится в ТОЙ ЖЕ СТРОКЕ #. я пробовал (не помогло)

Что наши коды НЕ МОГУТ сделать

Получите комментарий на основе времени последнего изменения, ДАЖЕ ЕСЛИ "ID_1" находится в ДРУГОЙ СТРОКЕ #. это где мне нужна помощь?

Преобразование HTML-таблицы в профессиональный документ Excel
Преобразование HTML-таблицы в профессиональный документ Excel
Это самый простой способ создания Excel из HTML-таблицы.
Импорт excel в laravel в базу данных
Импорт excel в laravel в базу данных
Здравствуйте, дорогой читатель, в этой статье я расскажу практическим и быстрым способом, как импортировать файл Excel в вашу базу данных с помощью...
0
0
71
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

РЕДАКТИРОВАТЬ, чтобы подтвердить соответствие предположений:

Лист Пользователь1: | Идентификатор | Комментарий | Последний мод | | --- | ------- | --------| | 3 | S1 Связь3| 2 | | 2 | S1 Связь2| 8 | | 1 | S1 Связь1| 6 |

Лист Пользователь2: | Идентификатор | Комментарий | Последний мод | | --- | ------- | --------| | 1 | S2 Связь1| 3 | | 2 | S2 Связь2| 4 | | 3 | S2 Связь3| 8 |

Ожидаемый результат:

Идентификатор Комментарий ПРИМЕЧАНИЯ 1 S1 Связь 1 Id 1 самый высокий мод находится на листе 1 2 S1 Связь2 Id 2 самый высокий мод находится на листе 2 3 S2 Связь3 Идентификатор 3 самого высокого мода находится на листе 3

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

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

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

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

Попробуйте разобраться с этим и дайте нам знать, если вам нужна дополнительная помощь.

Sub Tester()
    Dim oDict As Object
    Dim a(0 To 1)
    Dim sUser1 As Worksheet
    Dim sUser2 As Worksheet
    
    Set oDict = CreateObject("Scripting.Dictionary")
    Set sUser1 = Sheets("User1")
    Set sUser2 = Sheets("User2")
    
    'Here I will assume that both ranges will always
    'be the same length. I'm also hardcoding in the
    'needed rows. You can use whichever logic
    'works best for you to determine how to capture
    'all rows in both sheets
    For i = 2 To 8
        'Two possibilities here:
        '   1. The SystemId in both sheets match and
        '      can be directly compared
        '   2. They differ and will each be checked
        '      to see if they already exist in the dict.
        'You can bypass this and just treat each of the
        'ranges individually, but I think it would be
        'slightly more performant the way I'm doing it.
        '
        'Also, this assumes that each SystemId will only
        'appear once in each sheet, and is a true Primary Key
        If sUser1.Cells(i, 1).Value = sUser2.Cells(i, 1) Then
            If sUser1.Cells(i, 3).Value > sUser2.Cells(i, 3).Value Then
                MergeEntryToDictionary oDict, sUser1.Cells(i, 1).Value, _
                    sUser1.Cells(i, 2).Value, sUser1.Cells(i, 3).Value
            Else
                MergeEntryToDictionary oDict, sUser2.Cells(i, 1).Value, _
                    sUser2.Cells(i, 2).Value, sUser2.Cells(i, 3).Value
            End If
        Else
            'In case they don't match, check each entry against the
            'dictionary to see if the systemId has already been added.
            'If not, then add it. Otherwise, compare the last mod date
            'of the entry to the current, and update if needed.
            MergeEntryToDictionary oDict, sUser1.Cells(i, 1).Value, _
                    sUser1.Cells(i, 2).Value, sUser1.Cells(i, 3).Value
            
            MergeEntryToDictionary oDict, sUser2.Cells(i, 1).Value, _
                    sUser2.Cells(i, 2).Value, sUser2.Cells(i, 3).Value
        End If
    Next i
    
    'Below prints back to sheet
    Dim k As Variant
    Dim n As Long
    n = 2
    For Each k In oDict.keys
        Sheets("result").Cells(n, 1).Value = k
        Sheets("result").Cells(n, 2).Value = oDict(k)(0)
        Sheets("result").Cells(n, 3).Value = oDict(k)(1)
        
        n = n + 1
    Next k
End Sub

Function MergeEntryToDictionary(ByRef oDict As Object, _
                                SystemId As String, _
                                sComment As String, _
                                LastModTime As Double) As Boolean
    Dim a(0 To 2)
    
    If oDict.exists(SystemId) Then
        If LastModTime > oDict(SystemId)(1) Then
            a(0) = sComment
            a(1) = LastModTime
            oDict(SystemId) = a
        End If
    Else
        a(0) = sComment
        a(1) = LastModTime
        
        oDict.Add SystemId, a
    End If
    
    MergeEntryToDictionary = True
End Function

От всего сердца искренне благодарю Вас за помощь! Мне просто нужно немного изменить здесь, пожалуйста, я попытался сделать различную сортировку на всех листах, в диапазоне листов user1 ("a2") = ID_1, в диапазоне листов user2 ("a3") = ID_1, в результате ("диапазон ("a4") = ID_1. Мне нужно сопоставить идентификаторы на основе их общего (значение = ID_1), а не на основе их адреса ("a2"). Смещение (0,2). Спасибо: D

Zatary 09.12.2020 18:03

он отлично работает, если все первичные ключи имеют одинаковый (порядок/сортировка). Мне просто нужно сопоставить их, даже если они упорядочены по-разному «результаты сопоставления независимо от сортировки индексов?»

Zatary 09.12.2020 18:12

@zatary код, который я написал, не различает местоположение. Функция смещения используется для извлечения значений из столбцов B и C (комментарий и отметка времени). Код работает независимо от того, совпадают ли идентификаторы с одинаковым номером строки. Это не работает для вас?

basodre 09.12.2020 18:15

Извините, к сожалению, этого не произошло, он работает точно так же, как мой код в вопросе. Если вы попробуете его на своем компьютере, он не будет работать так, как нужно. попробуйте поместить три столбца на три листа, но в столбце A поместите ("ID_1") в разные места, например, в sht user1 в строке 2, в sh user2 в строке 3 и т. д., вы обнаружите, что комментарии не будут отражаться, если все три иметь один и тот же номер строки, только тогда это работает, но если один и тот же system_id находится в разных номерах строк, это не сработает

Zatary 09.12.2020 18:28

@Zatary Я внес изменения в свой ответ. В верхней части поста я ввожу три таблицы, показывающие значения на листах user1 и user2. Затем я показываю ожидаемый результат, который соответствует результату, генерируемому моим кодом. Соответствует ли это вашим ожидаемым входным и выходным данным? Если нет, то чем он отличается?

basodre 09.12.2020 18:44

Привет, я отредактировал вопрос в таблицах, чтобы проиллюстрировать мою проблему чуть ниже кода, спасибо за ваше терпение :) Я не мог отредактировать ответ, пожалуйста, проверьте мой отредактированный вопрос. Проще говоря, разница в том, что я спрашиваю о сопоставлении ( один и тот же уникальный system_id) на всех листах в разных строках # в столбце A [system_id не обязательно должен иметь один и тот же номер строки на всех листах, чтобы отражать последние комментарии пользователей]

Zatary 09.12.2020 19:24

Привет, есть идеи по этому вопросу? Спасибо

Zatary 10.12.2020 15:56

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

basodre 10.12.2020 16:22

Другие вопросы по теме