简体   繁体   中英

Excel VBA find row number based on criteria in two columns, no loop

A little background, my sheet "Data" consists of a table, which my macro is supposed to populate. The table has dates running down the first column (Column P), and a few names as headers. My current macro, as seen below, loops through all my sheets, except the ones specified not to loop through, then in each sheet it loops through each cell in the range W7:W200. It then looks to match the right 10 values in the cell with a date in the column P on sheet "Data" (and sets that row as HdrRow). At the same time, it looks for the value in A9 in whatever sheet it is looping through, in order to match that value to a column header in sheet "Data" (and sets that column as HdrCol). After finding the row and column (intersecting cell), the macro then pastes the values of the cell it is looping through into that intersecting cell.

I am having trouble with this next part, I am looking to add another criteria for finding a row. I would like the macro to not only find a matching date in column P, but also a value in column Q that matches with the value in A1 of whichever sheet it is looping through; and then set that row as HdrRow. If possible, id like to not use a loop for this.

Sub Values()
    Dim HdrCol As Range
    Dim Site As String
    Dim SearchRange As Range
    Dim HdrRow As Range
    Dim FinDate As Date
    Dim ws As Worksheet
    Dim rng As Range




    ' Fill in Actual Value
    Sheets("Data").Range("W2:W100000").ClearContents

    For Each ws In ActiveWorkbook.Worksheets
        'Dont Copy Data from these worksheets
        If ws.Name <> "Portfolio" And ws.Name <> "Master" And ws.Name <> "Template" _
            And ws.Name <> "Coal" And ws.Name <> "E&P" And ws.Name <> "Gen" _
            And ws.Name <> "Hydro" And ws.Name <> "LNG" And ws.Name <> "Midstream" _
            And ws.Name <> "Solar" And ws.Name <> "Transmission" _
            And ws.Name <> "Wind" And ws.Name <> "Data" Then

            For Each cell In ws.Range("W7:W200")

                If cell <> "          " Then

                    Site = ws.Range("A9").Value
                    FinDate = Right(cell, 10)

                    'Find column ref
                    Set HdrCol = Sheets("Data").Range("P1:W1").find(Site, lookat:=xlPart)
                    If Not HdrCol Is Nothing Then
                    End If

                    'Find row ref
                    Set SearchRange = Sheets("Data").Range("P1", Range("P100000").End(xlUp))
                    Set HdrRow = SearchRange.find(FinDate, LookIn:=xlValues, lookat:=xlWhole)


                    Application.Goto Reference:=Cells(HdrRow.Row, HdrCol.Column)

                    If IsEmpty(Sheets("Data").Cells(HdrRow.Row, HdrCol.Column)) Then
                        cell.Copy Sheets("Data").Cells(HdrRow.Row, HdrCol.Column)
                    Else
                        cell.Copy Sheets("Data").Cells(HdrRow.Row, HdrCol.Column).End(xlDown).Offset(1, 0)
                    End If
                End If
            Next
        End If
    Next
End Sub

My first thought for a non-loop version to do this (loop is much simpler), would be to use match(), though if you have multiple values where A=Q or the same date is used, you might run into an issue.

Dim i,j as Integer

i=Application.Match(RefCell1,LookUp1,0).Row
j=Application.Match(RefCell2,LookUp2,0).Row

If i=j Then
    HdrRow=i
    Else
End If

I am specifically not making that match scenario the If statement condition so it's easier to read and edit.

You would run into issues where you have multiple of the same values, using this approach.


Another approach is to use a nested if statement:

Dim i as integer

i=Application.Match(RefCell1,LookUp1,0).Row

If Application.IfError(i,0)>0 Then
    If Cells(i,"Q").Value=Cells(RefCell1Row,"A").Value
        HdrRow=i
        Else
    End If
    Else
End If

In the end, I would still recommend a loop so you can assess line per line, which would build on the second approach.


Edit: Per request, to include a loop.

Dim i, j as Integer 

For i = 7 to 200 'Used the range you mentioned in your post, which I think is wrong for this example... these are row numbers for Data sheet
    For j = 7 to 200 'Row numbers for reference sheets
        If Sheet(ARRAY).Cells(j,"Q").Value=Sheets("Data").Cells(i,"A").Value Then
            If Cells(j,"P").Value=Cells(i,"B").Value 'Not sure what column the date is in Data sheet
                HdrRow=j
                Else
            End If
            Else
        End If
   Next j
Next i

Ends up being two loops, to account for the cells on both your data sheet, and each sheet you're referencing in the array. Make sure to turn off screen updating, because epilepsy is real!

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