0

In sheet1 I have two columns:

enter image description here

In Sheet2 I have one column:

enter image description here

In Sheet3 I want to get the following result:

enter image description here

Arguments to get the data in Sheet3 are: Value of column A of Sheet2 equals a value in column A of Sheet1 (can be random row #) AND if it equals then value in column B of Sheet1 should be "a".

I wrote the following:

Sub MatchColumnsCondition()

    Dim sht1, sht2, sht3 As Worksheet
    Dim lr1, lr2, lr3 As Long
    Dim chk1, chk2 As Variant
    Dim out3 As Range
    Dim dup As Boolean
    Dim i, j

    Set sht1 = ThisWorkbook.Worksheets("Sheet1") 'data to search in including condition
    Set sht2 = ThisWorkbook.Worksheets("Sheet2") 'data to search from
    Set sht3 = ThisWorkbook.Worksheets("Sheet3") 'output data

    lr1 = sht1.Cells(sht1.Rows.Count, "A").End(xlUp).Row
    lr2 = sht2.Cells(sht2.Rows.Count, "A").End(xlUp).Row
    lr3 = sht3.Cells(sht3.Rows.Count, "A").End(xlUp).Row

    Set chk1 = sht1.Range("A1:A" & lr1)
    Set chk2 = sht2.Range("A1:A" & lr2)
    Set out3 = sht3.Range("A1:A" & lr3)

    For i = LBound(chk1) To UBound(chk1)
           For j = LBound(chk2) To UBound(chk2)
            If chk1(i, 1) = chk2(j, 1) And chk1.Offset(, 1) = "a" Then
                sht3.Range("A" & lr3) = chk1(i, 1)
            End If
        Next j
    Next i

End Sub

but I keep running into errors with it, but I don't know how to make it work properly.

1 Answer 1

1

to stay with your code

Sub MatchColumnsCondition()

    Dim sht1 As Worksheet, sht2 As Worksheet, sht3 As Worksheet
    Dim lr1 As Long, lr2 As Long
    Dim chk1 As Variant, chk2 As Variant
    Dim i As Long, j As Long

    Set sht1 = ThisWorkbook.Worksheets("Sheet1") 'data to search in including condition
    Set sht2 = ThisWorkbook.Worksheets("Sheet2") 'data to search from
    Set sht3 = ThisWorkbook.Worksheets("Sheet3") 'output data

    lr1 = sht1.Cells(sht1.Rows.Count, "A").End(xlUp).Row
    lr2 = sht2.Cells(sht2.Rows.Count, "A").End(xlUp).Row

     chk1 = sht1.Range("A1:B" & lr1).Value
     chk2 = sht2.Range("A1:A" & lr2).Value

    For i = LBound(chk1) To UBound(chk1)
           For j = LBound(chk2) To UBound(chk2)
            If chk1(i, 1) = chk2(j, 1) And chk1(i, 2) = "a" Then
                sht3.Cells(sht3.Rows.Count, "A").End(xlUp).Offset(1).Value = chk1(i, 1)
            End If
        Next
    Next

End Sub

where in your original code:

1) Dim sht1, sht2, sht3 As Worksheet

would actually result in:

Dim sht3 As Worksheet, sht1 As Variant, sht2 As Variant

since unexplicitly declared variables (Dim sht1, sht2, ...) would be implicitly assumed as of Variant type

hence explicity declare all Worksheet type variables, like Dim sht1 As Worksheet, sht2 As Worksheet, sht3 As Worksheet

2) LBound(chk1) To UBound(chk1) and LBound(chk2) To UBound(chk2)

LBound() and UBound() functions accept an array as parameter.

In order to have an array out of a Range you have to take its Value property

then

  • ok with Dim chk1, chk2 As Variant

that would result as Dim chk1 As Variant, chk2 As Variant and which is fine since a Variant is the right type we need to store a range values into

  • Set chk1 = sht1.Range("A1:A" & lr1) turns into chk1 = sht1.Range("A1:B" & lr1).Value, since you don't Set an array and you need it to store column B values, too

  • Set chk2 = sht2.Range("A1:A" & lr1) turns into chk2 = sht2.Range("A1:A" & lr1).Value

  • you don't need out3 , hence don't declare neither Set it

3) Offset() is a Range class property, while arrays have no methods nor properties

to get some value in 2nd column of a 2D array you use the column index like chk1(i, 2)

finally) sht3.Range("A" & lr3) would keep writing in the same cell over and over again

hence either you update lr3 (with some lr3 = lr3 + 1 before End If) or you need a dynamic range reference always pointing to sht3 column A first empty cell after last not empty one, like sht3.Cells(sht3.Rows.Count, "A").End(xlUp).Offset(1)

EDIT: added a different approach

provided (as per shown data) column B of Sheet1 have either "a"s or blank cells, then you could avoid loops and use AutoFilter() and Specialcells() methods of Range object, as follows (explanations in comments):

Sub MatchColumnsCondition2()

    Dim sht1 As Worksheet, sht2 As Worksheet, sht3 As Worksheet
    Dim chk2 As Variant

    Set sht1 = ThisWorkbook.Worksheets("Sheet1") 'data to search in including condition
    Set sht2 = ThisWorkbook.Worksheets("Sheet2") 'data to search from
    Set sht3 = ThisWorkbook.Worksheets("Sheet3") 'output data

    chk2 = sht2.Range("A1", sht2.Cells(sht2.Rows.Count, "A").End(xlUp)).Value

    With sht1 ' reference "sheet1"
        With .Range("B1:A" & .Cells(sht1.Rows.Count, "A").End(xlUp).Row) 'reference referenced sheet columns A:B range from row 1 down to column A last not empty cell row
            .Rows(1).EntireRow.Insert ' insert a "helper" row for headers
            With .Offset(-1).Resize(.Rows.Count + 1) ' reference referenced range plus added header row
                .Rows(1).Value = Array("h1", "h2") ' write dummy headers
                .AutoFilter field:=1, Criteria1:=Application.Transpose(chk2), Operator:=xlFilterValues ' filter referened range on its first column with sheet2 column A values
                .Resize(.Rows.Count - 1, 1).Offset(1, 1).SpecialCells(xlCellTypeVisible).SpecialCells(XlCellType.xlCellTypeConstants).Offset(, -1).Copy Destination:=sht3.Range("A1") ' copy referenced range second column filtered cells (skipping headers) with some constant value and paste to sheet 3 from cell A1
                .Rows(1).Delete xlUp ' delete "helper" row
            End With
       End With
    End With

End Sub
Sign up to request clarification or add additional context in comments.

3 Comments

helpful, thorough explanation :+)
Thanks a million, not only for fixing my code, but also for your explanation. It turns out I was closer than I thought, but the main problem was in my dim - leaving out the variables. I was under the false assumption that if you put dim and comma separate words and than end with a variable - all these would be that same variable. The adjusted code did exactly what I had in mind. Your second code does not work as intended if I have different data then "a" in column B of Sheet1. It would then also show that as a hit if the value in column A matches.Also
You are welcome. Yeah you were quite close, but for those three issues I pointed out. The second code would work if all unwanted cells in column B are blanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.