简体   繁体   中英

Finding if a column cell equals another in a different sheet

I want to find out if a particular group of cells match another group of cells in a different sheet using VBA. In my case, I need to find out if the lastName, firstName cells match. In my solution that I came up with, I'm looping through the first table, getting the employee name. Then looping through the second table, getting the employee name. Then seeing if the two match up. This method is too costly and takes too long. Is there any better way to do this?

My first table contains 6 rows, my second table can contain 100+ rows. Too much time is wasted.

I was thinking about just searching down the entire column to see if the last name matches first, if it does, then go and see if the first name matches... but then again, there could be some people with the same last name..

Here is what I have so far.

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

I know I have no conditional statement, I didn't bother writing it because I knew this approach is not the best one.

I cannot add another column to concatenate the second sheets names because they are read from a database and kept in separate columns and last name and first name. Anyways, is there a way that I can concatenate the names without adding another column to the second sheet and try to find them that way? Does that make sense?

Find will only look in one column if I'm not mistaken. Can it look in two?

UPDATE

I'm able to get the first occurrence of the last name, but not the others. I've added another field to match. So there are three fields to match now. Last Name , First Name , and Project Name . So far, my code will only find the first occurrence and stay there. I think my order of the looping is wrong.

Here is what I have so far.

  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

Take a look at 'Is this in the wrong place? for my new loop.

UPDATE 2: Solved

I have successfully filtered on three columns using find and findNext . With the help of some good answers. I will post the completed version. I had to add extra else statement into my filters in order to go to the next ling found. Hopefully others can learn from this, as there is no clear answer for filtering on three columns using 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

Instead of using two loops, you can use just the first one and utilize the find function. I believe it'll be faster for you.

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

For more information on find , look here .

you only need to know if it is there... then use COUNTIFS like:

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

and if it is not 0 then there is a match.

For VBA it is

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

If you have any questions left, just ask ;)

EDIT

... I need the row number that they exist in ...

You never said that! *angry face*... still, it is possible to do in a more or less fast way:

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

I usually use a dictionary or collection when looking for duplicates. In this way I only have to loop through each list one time.

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

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM