2016-06-29 3 views
1

Я хочу узнать, соответствует ли конкретная группа ячеек другой группе ячеек на другом листе, используя VBA. В моем случае мне нужно выяснить, соответствуют ли ячейки lastName, firstName. В моем решении, которое я придумал, я просматриваю первую таблицу, получая имя сотрудника. Затем прокрутите вторую таблицу, получив имя сотрудника. Затем посмотрим, совпадут ли эти два. Этот метод слишком дорогостоящий и занимает слишком много времени. Есть ли лучший способ сделать это?Поиск, если ячейка столбца равна другой в другом листе

Моя первая таблица содержит 6 строк, моя вторая таблица может содержать более 100 строк. Слишком много времени тратится впустую.

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

Вот что у меня есть до сих пор.

For i = 2 To managerRows 'Looping through the Managers Table 
     empFirst = managerSheet.Cells(i, 1) 
     empLast = managerSheet.Cells(i, 2) 
     empName = (empLast & ", " & empFirst) 

     For j = 3 To assignRows 'Looping through the Assignments table 
      empLastAssign = assignSheet.Cells(i, 4) 
      empFirstAssign = assignSheet.Cells(i, 5) 
      empNameAssign = (empLastAssign & ", " & empFirstAssign) 
      'MsgBox (empNameAssign) 
      ... 
      Conditional statement comparing names 
      ... 
     Next j 
    Next i 

Я знаю, что у меня нет условного оператора, я не стал писать, потому что я знал, что этот подход не является лучшим вариантом.

Я не могу добавить еще один столбец, чтобы объединить имена вторых листов, потому что они считываются из базы данных и хранятся в отдельных столбцах, фамилии и имени. В любом случае, есть ли способ, которым я могу объединить имена , не добавляя еще один столбец ко второму листу и попытаться найти их таким образом? Имеет ли это смысл?

Find будет выглядеть только в одной колонке, если я не ошибаюсь. Может ли это выглядеть пополам?

UPDATE

Я смог получить первое вхождение фамилии, но не другие. Я добавил еще одно поле для соответствия. Итак, теперь есть три поля. Last Name, First Name, и Project Name. Пока мой код найдет только первое событие и останется там. Я думаю, что мой порядок цикла неправильный.

Вот что у меня есть.

For i = 2 To managerRows 'Looping through the Managers Table 
     empLast = managerSheet.Cells(i, 1) 
     empFirst = managerSheet.Cells(i, 2) 
     empName = (empLast & ", " & empFirst) 
     projectName = managerSheet.Cells(i, 3) 
     managerLast = managerSheet.Cells(i, 4) 
     managerFirst = managerSheet.Cells(i, 5) 
     managerName = (managerLast & ", " & managerFirst) 

     Set findRow = assignSheet.Range(assignSheet.Cells(3, 4), assignSheet.Cells(assignRows, 4)) 'Set a range to look for Last Name 
     Set c = findRow.Find(empLast, LookIn:=xlValues) 'Find matching Last Name if it exists 
     If Not c Is Nothing Then 'Last Name found 
      Do Until c Is Nothing 'Is this in the wrong place? 
       If Cells(c.Row, 5) = empFirst Then 'If first name matches 
        If Cells(c.Row, 10) = projectName Then 'If project name matches. We found them 
         MsgBox ("Found: " & empLast & ", " & empFirst & ": Project: " & projectName & " : in: " & c.Row) 
        End If 
       End If 
       Set c = findRow.FindNext(c) 'Is this is the wrong place? 
      Loop 
     End If 
     Set c = Nothing 'Is this in the wrong place? 
    Next i 

Посмотрите на мой новый цикл 'Is this in the wrong place?.

UPDATE 2: решаемые

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

For i = 2 To managerRows 'Looping through the Managers Table 
     empLast = managerSheet.Cells(i, 1) 
     empFirst = managerSheet.Cells(i, 2) 
     empName = (empLast & ", " & empFirst) 
     projectName = managerSheet.Cells(i, 3) 
     managerLast = managerSheet.Cells(i, 4) 
     managerFirst = managerSheet.Cells(i, 5) 
     managerName = (managerLast & ", " & managerFirst) 
     'Focus Below this 
     Set findRow = assignSheet.Range(assignSheet.Cells(3, 4), assignSheet.Cells(assignRows, 4)) 'Set a range to look for Last Name 
     Set c = findRow.Find(empLast, LookIn:=xlValues) 'Find matching Last Name if it exists 
     If Not c Is Nothing Then 'Last Name found 
      Do Until c Is Nothing 
       If Cells(c.Row, 5) = empFirst Then 'If first name matches 
        If Cells(c.Row, 10) = projectName Then 'If project name matches. We found them 
         MsgBox ("Found: " & empLast & ", " & empFirst & ": Project: " & projectName & " : in: " & c.Row) 
         Set c = Nothing 
        Else 
         Set c = findRow.FindNext(c) 
        End If 
       Else 
        Set c = findRow.FindNext(c) 
       End If 
      Loop 
     End If 
    Next i 
+0

Вы можете попробовать 'WorksheetFunction.Vlookup' – JamesFaix

+0

Вы можете сортировать данные в "большом" листе? (BTW: 100+ строк не является большим числом строк!) – user3598756

ответ

1

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

For i = 2 To managerRows 'Looping through the Managers Table 
    empFirst = managerSheet.Cells(i, 1) 
    empLast = managerSheet.Cells(i, 2) 
    empName = (empLast & ", " & empFirst) 
    managerLast = managerSheet.Cells(i, 3) 
    managerFirst = managerSheet.Cells(i, 4) 
    managerName = (managerLast & ", " & managerFirst) 

    MsgBox (empName & ", " & managerName) 

    Set myRng = assignSheet.Range(assignSheet.Cells(3, 4), assignSheet.Cells(assignRows, 4) 
    Set c = myRng.Find(empName, lookin:=xlValues) 
    if Not c is Nothing Then 'you found last name, no look to see if first is a match 
     if assignSheet.cells(c.row, 5) = empFirst then 'if it is, do something 
      'do whatever you need to do here 
     else 
      firstAddress = c.Address 
      Do 
       Set c = myRng.FindNext(c) 

       if Not c is Nothing Then 'you found last name, no look to see if first is a match 
        if assignSheet.cells(c.row, 5) = empFirst then 'if it is, do something 
         'do whatever you need to do here 
        end if 
       end if 
      Loop While Not c Is Nothing And c.Address <> firstAddress 
     end if 
    end if 
Next i 

Для получения дополнительной информации о find, смотрите here.

+0

Просто изучил это, обновил мой вопрос. Я думаю, вы неправильно поняли это. Просто прояснилось это немного. –

+0

ОК. Да, я бы связал последние и первые имена, более или менее, как я сказал в своем ответе, и вы заявили в своем обновленном вопросе, а затем используйте функцию find, которую я упоминаю, тем самым только один цикл, а не два. –

+0

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

1

вам только нужно знать, если он есть ... а затем использовать COUNTIFS как:

=COUNTIFS(A:A,"Name",B:B,"Lastname"....) 

и если это не 0, то есть совпадение.

Для VBA это

Application.Countifs(Range("A:A"),"Name",Range("B:B"),"Lastname"....) 

Если вы оставили какие-либо вопросы, просто спросите;)

EDIT

... Мне нужен номер строки, что они существуют в ...

Вы, ver сказал, что! * Сердитое лицо * ... до сих пор, можно сделать более или менее быстрый способ:

Sub test() 
    Dim val As Variant, rowNum As Variant 
    With Sheets("Sheet1") 
    val = Evaluate(Intersect(.Columns(1), .UsedRange).Address & "&"" --- ""&" & Intersect(.Columns(2), .UsedRange).Address) 
    rowNum = Application.Match("name" & " --- " & "firstname", val, 0) 
    If IsNumeric(rowNum) Then Debug.Print "Found at Row: " & rowNum Else Debug.Print "Nothing was found" 
    End With 
End Sub 
+0

Да, это работает только для того, чтобы найти, существуют ли они, но мне нужен номер строки, в котором они существуют. Найти лучше для моей проблемы, потому что я могу найти номер строки. –

+0

, пожалуйста, проверьте мое редактирование ... он должен работать довольно быстро;) –

+0

Это сработало и после некоторой настройки. Хотел бы я выбрать два правильных ответа. Спасибо –

0

Я обычно использую словарь или сбор при поиске дубликатов. Таким образом, мне нужно только прокручивать каждый список один раз.

Sub FindDuplicates() 
    Dim empFirst As String, empLast As String, empName As String 
    Dim assignSheet As Worksheet, managerSheet As Worksheet 
    Dim i As Long, lastRow As Long 
    Dim d 
    Set assignSheet = Sheet2 
    Set managerSheet = Sheet1 

    Set d = CreateObject("Scripting.Dictionary") 
    With managerSheet 
     lastRow = .Range("A" & Rows.Count).End(xlUp).Row 

     For i = 2 To lastRow 'Looping through the Managers Table 
      empFirst = .Cells(i, 1) 
      empLast = .Cells(i, 2) 
      empName = (empLast & ", " & empFirst) 
      If Not d.exists(empName) Then d.Add empName, i 
     Next 
    End With 


    With assignSheet 
     lastRow = .Range("A" & Rows.Count).End(xlUp).Row 

     For i = 2 To lastRow 'Looping through the Managers Table 
      empFirst = .Cells(i, 4) 
      empLast = .Cells(i, 5) 
      empName = (empLast & ", " & empFirst) 
      If d.exists(empName) Then 

       Debug.Print "Match Found", empName, "assignSheet Row:" & i, "managerSheet Row:" & d(empName) 

      End If 

     Next 
    End With 

End Sub 

enter image description here

Смежные вопросы