Search code examples
excelvbafind

Use .Find to Find Two Strings that are placed in the same Row but different Columns


I am trying to use the .Find function to find two strings and determine which row they are in. For this example the two strings that I am looking for are "Wavelenght" and "Test-Config" as shown in the rowindex = getrowindex(sysnum, "Wavelength", "Test-Config") line. I have attached all my code. The current script produces an error at Set parameter_row = Worksheets(sysnum).Range("B:B").Find(What:=parametername, What:=routingname, Lookat:=xlWhole, LookIn:=xlFormulas, MatchCase:=True) saying "Named Argument Not Found." I also have already checked and I do not have Solver.xlam in my Available References

 Public Sub Main()
Dim wb As Workbook, ws As Worksheet, i As Range, dict As Object, sysnum As Integer, sysrow As Integer, syscol As Integer, wsName As String 
Dim wbSrc As Workbook

Dim value As Long, colindex As Long, rowindex As Long

Set wb = ThisWorkbook
Set ws = wb.Worksheets("Sheet1") 

Set wbSrc = Workbooks.Open("Q:\Specification and Configuration Document.xlsx")
Set dict = CreateObject("scripting.dictionary")
    For Each i In ws.Range("E2:E15").Cells ' i = every WD number
      sysnum = i.value
      sysrow = i.Row
      syscol = i.Column

      If sysnum = "" Then
        On Error Resume Next
      End If
If Not dict.Exists(sysnum) Then ' check if unique value already exists before adding it to dictionary
    dict.Add sysnum, True
    If Not SheetExists(sysnum, ThisWorkbook) Then
        wsName = i.EntireRow.Columns("D").value ' sheet to be copied
        If SheetExists(wsName, wbSrc) Then ' if there is a sheet for wsName to copy
            wbSrc.Worksheets(wsName).Copy After:=ws ' copy the sheet
            wb.Worksheets(wsName).name = sysnum ' rename the copy
        End If
    Else
        MsgBox "Sheet " & sysnum & " already exists"
    End If
End If

Sheets(1).Select
' Wavelength Turning Range Section
' in sheet 1
colindex = getcolumnindex(ws, "Tuning Range (nm)")
value = getjiradata(sysrow, colindex)

' in SD sheet
rowindex = getrowindex(sysnum, "Wavelength Tuning Range", "Test-Config-OCT")

Next i
End Sub

Function SheetExists(SheetName As String, wb As Workbook)
  On Error Resume Next
  SheetExists = Not wb.Sheets(SheetName) Is Nothing
End Function

Function getcolumnindex(sht As Worksheet, colname As String) As Long 
Dim paramname As Object
Set sht = Worksheets("Sheet1")
Set paramname = sht.Range("A1:Z2").Find(What:=colname, Lookat:=xlWhole, LookIn:=xlFormulas, MatchCase:=True)
    If Not paramname Is Nothing Then
        getcolumnindex = paramname.Column
    End If
End Function

Function getjiradata(WDrow As Integer, parametercol As Long) 
   Dim cell As Variant, ws As Worksheet
   cell = getcolumnindex(ws, "Tuning Range (nm)")
   getjiradata = Cells(WDrow, parametercol)

End Function

Function getrowindex(WDnum As Variant, parametername As String, routingname As String) As Long 
   Dim parameter_row As Object
   Set parameter_row = Worksheets(sysnum).Range("B:B").Find(What:=parametername, What:=routingname, Lookat:=xlWhole, LookIn:=xlFormulas, MatchCase:=True)
      If Not parameter_row Is Nothing Then
          getrowindex = parameter_row.Row
      End If
End Function

UPDATE:

Function getrowindex(WDnum As Variant, parametername As String, routingname As String) As Long ' finds the row index of parameters in SD tab
Dim parameter_row As Range, ws As Worksheet, rowname As Range, addr As String

Set ws = ThisWorkbook.Sheets(WDnum)

Set rowname = ws.Columns("B").Find(What:=parametername, Lookat:=xlWhole, LookIn:=xlFormulas, MatchCase:=True)
    If Not rowname Is Nothing Then addr = rowname.Address ' remember the first cell found with parametername
    Do While Not rowname Is Nothing
        If rowname.Offset(0, 1).Value = routingname Then ' check column C for cell with routingname
            getrowindex = rowname.Row
            Exit Function
        End If
    Set rowname = ws.Columns("B").FindNext(after:=rowname)
        If rowname.Address = addr Then Exit Do
    Loop
 End Function 

Solution

  • You only need to find Wavelength Tuning Range. Once found you just need to check if the second column contains Test-Config-OCT.

    I've given two functions - the first will return all instances of the found rows, the second will stop when it finds the first row.

    You need to pass the function the first column range reference, the number of columns across that the second item will appear in, the value to look for in the first column and the value to look for in the second column:
    ReturnRowReference(RangeToSearch, OffSetColumn, FirstItem, SecondItem)

    Public Sub Test()
    
        Dim MyResult As Range
        Set MyResult = ReturnRowReference(Sheet1.Range("C7:D14"), 2, "Wavelength Tuning Range", "Test-Config-OCT")
        
        Dim MyFirstResult As Range
        Set MyFirstResult = ReturnFirstRowReference(Sheet1.Range("C7:D14"), 2, "Wavelength Tuning Range", "Test-Config-OCT")
        
        If Not MyResult Is Nothing Then
            MsgBox MyResult.Address & vbCr & vbCr & _
                   MyFirstResult.Address, vbOKOnly + vbInformation
        End If
        
    End Sub
    
    
    
    Public Function ReturnRowReference(RangeToSearch As Range, OffsetColumns As Long, FirstItem As String, SecondItem As String) As Range
    
        With RangeToSearch
            'Start looking after the last cell in the column.... which equates to the first cell in the column.
            Dim FoundRange As Range
            Set FoundRange = .Find(What:=FirstItem, After:=.Cells(.Rows.Count, 1), _
                                   LookAt:=xlWhole, LookIn:=xlValues, _
                                   SearchOrder:=xlByRows, SearchDirection:=xlNext, _
                                   MatchCase:=True)
                                   
            If Not FoundRange Is Nothing Then
                Dim FirstAddress As String
                FirstAddress = FoundRange.Address
                Do
                    If FoundRange.Offset(, OffsetColumns) = SecondItem Then
                        Dim ReturnRange As Range
                        If ReturnRange Is Nothing Then
                            Set ReturnRange = FoundRange.EntireRow
                        Else
                            Set ReturnRange = Union(ReturnRange, FoundRange.EntireRow)
                        End If
                    End If
                    Set FoundRange = .FindNext(FoundRange)
                Loop While FoundRange.Address <> FirstAddress
            End If
        End With
        
        Set ReturnRowReference = ReturnRange
    
    End Function
    
    Public Function ReturnFirstRowReference(RangeToSearch As Range, OffsetColumns As Long, FirstItem As String, SecondItem As String) As Range
    
        With RangeToSearch
            'Start looking after the last cell in the column.... which equates to the first cell in the column.
            Dim FoundRange As Range
            Set FoundRange = .Find(What:=FirstItem, After:=.Cells(.Rows.Count, 1), _
                                   LookAt:=xlWhole, LookIn:=xlValues, _
                                   SearchOrder:=xlByRows, SearchDirection:=xlNext, _
                                   MatchCase:=True)
                                   
            If Not FoundRange Is Nothing Then
                If FoundRange.Offset(, OffsetColumns) = SecondItem Then
                    Set ReturnFirstRowReference = FoundRange.EntireRow
                End If
            End If
        End With
    
    End Function  
    

    This is the data I used:
    enter image description here

    and this is the message box it returned.
    So first procedure found rows 7 & 11, second procedure only found row 7.
    enter image description here

    Update to OP's edited code:

    Sub Test()
    
        MsgBox getrowindex("Sheet1", "Wavelength Tuning Range", "Test-Config-OCT")
    
    End Sub
    
    Public Function getrowindex(WDnum As Variant, parametername As String, routingname As String) As Long ' finds the row index of parameters in SD tab
    
        Dim parameter_row As Range, ws As Worksheet, rowname As Range, addr As String
    
        Set ws = ThisWorkbook.Worksheets(WDnum) 'Changed Sheets to Worksheets.  Sheets also includes Chart Sheets and Old style macro sheets.
    
        Set rowname = ws.Columns("B").Find(What:=parametername, Lookat:=xlWhole, LookIn:=xlFormulas, MatchCase:=True)
        
        If Not rowname Is Nothing Then 'Check that something is found.
            addr = rowname.Address ' remember the first cell found with parametername.
            Do
                If rowname.Offset(0, 1).Value = routingname Then ' check column C for cell with routingname
                    getrowindex = rowname.Row
                    Exit Do 'Found the correct row so exit the loop.
                End If
                Set rowname = ws.Columns("B").FindNext(after:=rowname)
            Loop While rowname.Address <> addr 'We know that rowname is not nothing at this point, so just check if it's back at the first address.
        End If
        
     End Function