After deleting entire rows, newly copied data is shifted down x rows - excel

Before I copy a new set of data into a set of columns I want to delete everything but the headers, which I do using the following code:
wsS.Rows("4:1048560").EntireRow.Delete
I do it like this because the data spreads over column A to AZ and it's not the same rows lenght.
But somehow, the comand leaves cells that contained data previously and are now empty selected, but only for columns A to F (I have 9 blocks of data that are copied and for each block I used a different sub() that are later called within a button). I also apply a filter before on the sheet where I copy the data from.
My problem is that the new copy somehow starts where the other data should have ended. The more ofther I run the code, the more rows down the copy will start. The code for copying was suggested by someone here and I only adapted it slightly to my needs.
The weird thing is that if I run the delete command above in the Immediate Window (or I do a manual delete) and then I run the full code again, the copied data will start as it should in cell A4.
I have also tried to do a select on cell A4 after I delete and then copy the new data. Still no success. And this happens only on the first set of data I copy (columns A to F) -> I used the same code to copy more ranges (A to F, H to M, O to T and so on)
This is the code for one block, namely A to F:
Private Sub CopyDataAtoF()
Dim wsR As Worksheet: Set wsR = ThisWorkbook.Worksheets("Data Raw")
Dim wsS As Worksheet: Set wsS = ThisWorkbook.Worksheets("Scatter Raw")
Dim lrR As Long: lrR = wsR.Cells(wsR.Rows.count, "A").End(xlUp).Row
Dim lrS1 As Long: lrS1 = wsS.Cells(wsS.Rows.count, "A").End(xlUp).Row + 1
Dim lrS2 As Long: lrS2 = wsS.Cells(wsS.Rows.count, "C").End(xlUp).Row + 1
Dim lrS3 As Long: lrS3 = wsS.Cells(wsS.Rows.count, "E").End(xlUp).Row + 1
With wsR
Dim fRng As Range: Set fRng = .Range(.Cells(1, "A"), .Cells(lrR, "AN"))
Dim rngN As Range: Set rngN = .Range(.Cells(2, "N"), .Cells(lrR, "N"))
Dim rngY As Range: Set rngY = .Range(.Cells(2, "Y"), .Cells(lrR, "Y"))
Dim cRng As Range: Set cRng = Union(rngN, rngY)
End With
Application.ScreenUpdating = False
wsS.Rows("4:1048560").EntireRow.Delete Shift:=xlUp
fRng.AutoFilter field:=25, Criteria1:="<>", Operator:=xlFilterValues
fRng.AutoFilter field:=1, Criteria1:="criteria1", Operator:=xlFilterValues
If fRng.SpecialCells(xlCellTypeVisible).CountLarge > 2 Then
cRng.Copy
wsS.Cells(lrS1, "A").PasteSpecial xlPasteValues
With wsS
Dim vis1 As Long: vis1 = .Cells(.Rows.count, "A").End(xlUp).Row
Dim lcS1 As Long: lcS1 = .Cells(lrS1, "A").End(xlToRight).Column + 1
Dim divA As Range: Set divA = .Range(.Cells(lrS1, "A"), .Cells(vis1, "A"))
Dim divY1 As Range: Set divY1 = .Range(.Cells(lrS1, lcS1), .Cells(vis1, lcS1))
divY1.Formula = "=" & .Cells(lrS1, 1).Address(RowAbsolute:=False) & " / 1000"
divA.Value2 = divY1.Value2
divY1.ClearContents
End With
End If
fRng.AutoFilter field:=1, Criteria1:="criteria2", Operator:=xlFilterValues
If fRng.SpecialCells(xlCellTypeVisible).CountLarge > 2 Then
cRng.Copy
wsS.Cells(lrS2, "C").PasteSpecial xlPasteValues
With wsS
Dim vis2 As Long: vis2 = .Cells(.Rows.count, "C").End(xlUp).Row
Dim lcS2 As Long: lcS2 = .Cells(lrS2, "C").End(xlToRight).Column + 1
Dim divC As Range: Set divC = .Range(.Cells(lrS2, "C"), .Cells(vis2, "C"))
Dim divY2 As Range: Set divY2 = .Range(.Cells(lrS2, lcS2), .Cells(vis2, lcS2))
divY2.Formula = "=" & .Cells(lrS2, 3).Address(RowAbsolute:=False) & " / 1000"
divC.Value2 = divY2.Value2
divY2.ClearContents
End With
End If
fRng.AutoFilter field:=1, Criteria1:="criteria3", Operator:=xlFilterValues
If fRng.SpecialCells(xlCellTypeVisible).CountLarge > 2 Then
cRng.Copy
wsS.Cells(lrS3, "E").PasteSpecial xlPasteValues
With wsS
Dim vis3 As Long: vis3 = .Cells(.Rows.count, "E").End(xlUp).Row
Dim lcS3 As Long: lcS3 = .Cells(lrS3, "E").End(xlToRight).Column + 1
Dim divE As Range: Set divE = .Range(.Cells(lrS3, "E"), .Cells(vis3, "E"))
Dim divY3 As Range: Set divY3 = .Range(.Cells(lrS3, lcS3), .Cells(vis3, lcS3))
divY3.Formula = "=" & .Cells(lrS3, 5).Address(RowAbsolute:=False) & " / 1000"
divE.Value2 = divY3.Value2
divY3.ClearContents
End With
End If
wsS.Range("A1").Select
wsR.AutoFilter.ShowAllData
Application.ScreenUpdating = True
End Sub

The issue you are experiencing, is due to the fact that all variable prefixed with lr are storing the index number (invariably) of last row that contained data, before you all delete them.
Based on how the code is written, when you paste new data, it starts from the index number stored in the lr-s.
The solution is to recalculate the value of the lr-s after deleting the data.
Replace the top of your code with the modified codes below, and the codes should work as your expect.
Private Sub CopyDataAtoF()
Dim wsR As Worksheet: Set wsR = ThisWorkbook.Worksheets("Data Raw")
Dim wsS As Worksheet: Set wsS = ThisWorkbook.Worksheets("Scatter Raw")
Application.ScreenUpdating = False
wsS.Rows("4:1048560").EntireRow.Delete Shift:=xlUp
Dim lrR As Long: lrR = wsR.Cells(wsR.Rows.count, "A").End(xlUp).Row
Dim lrS1 As Long: lrS1 = wsS.Cells(wsS.Rows.count, "A").End(xlUp).Row + 1
Dim lrS2 As Long: lrS2 = wsS.Cells(wsS.Rows.count, "C").End(xlUp).Row + 1
Dim lrS3 As Long: lrS3 = wsS.Cells(wsS.Rows.count, "E").End(xlUp).Row + 1
With wsR
Dim fRng As Range: Set fRng = .Range(.Cells(1, "A"), .Cells(lrR, "AN"))
Dim rngN As Range: Set rngN = .Range(.Cells(2, "N"), .Cells(lrR, "N"))
Dim rngY As Range: Set rngY = .Range(.Cells(2, "Y"), .Cells(lrR, "Y"))
Dim cRng As Range: Set cRng = Union(rngN, rngY)
End With
fRng.AutoFilter field:=25, Criteria1:="<>", Operator:=xlFilterValues
fRng.AutoFilter field:=1, Criteria1:="criteria1", Operator:=xlFilterValues
If fRng.SpecialCells(xlCellTypeVisible).CountLarge > 2 Then
The change I made in the code was to move;
Application.ScreenUpdating = False
wsS.Rows("4:1048560").EntireRow.Delete Shift:=xlUp
above;
Dim lrR As Long: lrR = wsR.Cells(wsR.Rows.count, "A").End(xlUp).Row
Dim lrS1 As Long: lrS1 = wsS.Cells(wsS.Rows.count, "A").End(xlUp).Row + 1
... ...
i.e. After deleting the necessary rows, the lr-s are then defined and calculated.
Thank you.

Related

Looping functions in VBA

My goal is to build a looping function that can take the *data and convert it into the *Goal Output
This is as far as I can make it with the code, my fundamental question is how to I nest my code inside of VBA to run 3 lines of code and then skip to line 6
*Data - sheet1
Layout
Machine 1
Work Center 1
Date
Machine 2
Work Center 2
Date
*Output - sheet2
Machine
Work Center
Date
Machine 1
Work Center 1
Date
Machine 1
Work Center 1
Date
*Goal Output - sheet 3
Machine
Work Center
Date
Machine 1
Work Center 1
Date
Machine 2
Work Center 2
Date
Code
Sub Fill_Data()
Sheet2.Activate
Set ws = Sheets("Sheet1")
Set ws2 = Sheets("Sheet2")
emptyrow = Cells(Rows.Count, 1).End(xlUp).Row + 1
Dim i As Integer
For i = 1 To 3
ws.Cells(i, 1).Copy
ws2.Cells(emptyrow, i).PasteSpecial
Next i
emptyrow = emptyrow + 1
End Sub
The below creates the loop you are asking for, you would just need to modify to your specific need.
Sub Fill_Data()
Set ws = Sheets("Sheet1")
Set ws2 = Sheets("Sheet2")
ws.Range("A1").Activate
emptyrow = Cells(Rows.Count, 1).End(xlUp).Row + 1
Dim i As Integer
Dim x As Integer
x = 1
For i = 1 To emptyrow
ws.Range(Cells(i, 1), Cells(i + 2, 1)).copy
ws2.Cells(x, 1).PasteSpecial Paste:=xlPasteAll, Operation:=xlNone, SkipBlanks:= _
False, Transpose:=True
i = i + 4
x = x + 1
Next i
End Sub
No need to nest any loops, you just need a couple extra incrementers to track everything.
Sub Fill_Data()
Dim ws As Worksheet
Dim ws2 As Worksheet
Set ws = Worksheets("Sheet1")
Set ws2 = Worksheets("Sheet2")
Dim emptyrow As Long
Dim lr As Long
Dim col As Long
Dim i As Long
With ws2
emptyrow = .Cells(Rows.Count, 1).End(xlUp).Row + 1
If emptyrow = 2 Then 'Populate Headers
.Cells(1, 1).Value = "Machine"
.Cells(1, 2).Value = "Work Center"
.Cells(1, 3).Value = "Date"
End If
End With
col = 1
With ws
lr = .Cells(Rows.Count, 1).End(xlUp).Row
For i = 1 To lr
If Not .Cells(i, 1).Value = "" And Not IsEmpty(.Cells(i, 1).Value) Then 'Skip blanks
ws2.Cells(emptyrow, col).Value = .Cells(i, 1).Value
If col = 3 Then 'Reset column and increment row
col = 1
emptyrow = emptyrow + 1
Else
col = col + 1
End If
End If
Next i
End With
End Sub
Transpose Groups of Data
Option Explicit
Sub TransposeGroupsOfData()
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim sws As Worksheet: Set sws = wb.Worksheets("Sheet1")
Dim slRow As Long: slRow = sws.Cells(sws.Rows.Count, "A").End(xlUp).Row
Dim dws As Worksheet: Set dws = wb.Worksheets("Sheet2")
Dim dlRow As Long: dlRow = dws.Cells(dws.Rows.Count, "A").End(xlUp).Row
Dim dCell As Range: Set dCell = dws.Cells(dlRow + 1, "A")
Dim sfgr As Long ' Source First Group Row
Dim sr As Long ' Source Row
Dim dco As Long ' Destination Column Offset
For sfgr = 1 To slRow Step 5
sr = sfgr
For dco = 0 To 2
dCell.Offset(, dco).Value = sws.Cells(sr, "A").Value
sr = sr + 1 ' next source row
Next dco
Set dCell = dCell.Offset(1) ' next cell below
Next sfgr
MsgBox "Data exported.", vbInformation
End Sub

Copy specific cells based on value in the same row in sheet1(table1) and paste into sheet2(table2) next available row

This code works, but it puts the values at the bottom of Sheet2(Table2), instead of next available row in table2. Any suggestions would be appreciated. Thanks
https://drive.google.com/file/d/19fZ6GLGtVNd13I-GTgLVjnfKlzrwx05U/view?usp=sharing
Sub Macro()
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets("Sheet2")
Dim LastRow As Long
Dim s As Long
Dim myRow As Long
s = ws.Range("A" & Application.Rows.Count).End(xlUp).Row
LastRow = Sheets("Sheet1").Cells(Rows.Count, "I").End(xlUp).Row
For myRow = 2 To LastRow
If Sheets("Sheet1").Cells(myRow, "I") = "INACTIVE" Then
ws.Range("A" & s + 1) = Sheets("Sheet1").Cells(myRow, "A")
ws.Range("B" & s + 1) = Sheets("Sheet1").Cells(myRow, "B")
ws.Range("C" & s + 1) = Sheets("Sheet1").Cells(myRow, "C")
ws.Range("D" & s + 1) = Sheets("Sheet1").Cells(myRow, "I")
End If
Next myRow
End Sub
Copying Data From One Excel Table to Another
Dealing with Excel tables in VBA can be quite tricky. This is a simple user-friendly version. You could dive much deeper into it by using (an array of) the table headers in the loop and whatnot.
Option Explicit
Sub Macro()
Dim sws As Worksheet: Set sws = ThisWorkbook.Worksheets("Sheet1")
Dim stbl As ListObject: Set stbl = sws.ListObjects("Table1")
Dim dws As Worksheet: Set dws = ThisWorkbook.Worksheets("Sheet2")
Dim dtbl As ListObject: Set dtbl = dws.ListObjects("Table2")
Dim sCell As Range
Dim srrg As Range
Dim drrg As Range
Dim r As Long
For Each sCell In stbl.ListColumns("Status").DataBodyRange
r = r + 1
If StrComp(CStr(sCell.Value), "INACTIVE", vbTextCompare) = 0 Then
Set srrg = stbl.ListRows(r).Range
Set drrg = dtbl.ListRows.Add.Range
drrg.Cells(1).Value = srrg.Cells(1).Value
drrg.Cells(2).Value = srrg.Cells(2).Value
drrg.Cells(3).Value = srrg.Cells(3).Value
drrg.Cells(4).Value = srrg.Cells(9).Value
End If
Next sCell
End Sub
the below code should work as s variable is inside the loop.
P.S.
Updated the code to match your example.
Also, the sheet2 has table, so the last row was not detected correctly by End(xlUp).Row
The problem was also with myRow =2
Sub Macro()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("Sheet2")
Dim ws1 As Worksheet: Set ws1 = ThisWorkbook.Sheets("Sheet1")
Dim LastRow As Long
Dim s As Long
Dim myRow As Long
LastRow = ThisWorkbook.Sheets("Sheet1").Cells(Rows.Count, "I").End(xlUp).Row
For myRow = 1 To LastRow
s = ws.Cells.Find("*", searchorder:=xlByRows, searchdirection:=xlPrevious).Row + 1
If ws1.Cells(myRow, "I") = "INACTIVE" Then
ws.Range("A" & s & ":C" & s) = ws1.Range("A" & myRow & ":C" & myRow).Value
ws.Range("D" & s) = "INACTIVE"
End If
Next myRow
MsgBox "OK"
End Sub

Copy data from multiple sheet and paste into 1 sheet

I am trying to copy data from multiple sheets and paste it into Sheet1. The result paste it into Sheet1 but the same row each time and not the next row of previous copied data. Here is my code. Any help is really appreciate. Thank you!
Sub LoopCopySheetsData()
Dim i As Integer
Dim wb As Workbook
Dim totalWS As Long
Set wb = ActiveWorkbook
'totalWS = wb.Sheets.Count
totalWS = 4
For i = 2 To totalWS 'Start of the VBA loop
If i < totalWS + 1 Then
Sheets(i).Select
With wb.Sheets(i)
Set findHeadRow = .Range("A:A").Find(What:="Data", LookIn:=xlValues)
End With
headRow = findHeadRow.Row
lastRow = Cells(Rows.Count, "A").End(xlUp).Row
Sheets(i).Range("A" & headRow + 1 & ":A" & lastRow).Copy
Range("A1").Activate
With wb.Sheets("Sheet1")
lastRowMaster = Cells(Rows.Count, "D").End(xlUp).Row
Sheets("Sheet1").Range("D" & lastRowMaster + 1).PasteSpecial xlPasteValues
End With
End If
Next i
End Sub
Copy Columns From Multiple Worksheets
If the header cell (Data) contains a formula, you will have to use xlValues instead of xlFormulas (first occurrence).
Adjust the values in the constants section.
Option Explicit
Sub LoopCopySheetsData()
' Source
Const sCol As String = "A"
Const sHeader As String = "Data"
' Destination
Const dName As String = "Sheet1"
Const dCol As String = "D"
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
Dim dws As Worksheet: Set dws = wb.Worksheets(dName)
Dim dfCell As Range
Set dfCell = dws.Cells(dws.Rows.Count, dCol).End(xlUp).Offset(1)
Dim sws As Worksheet
Dim srg As Range ' Range
Dim shCell As Range ' Header Cell
Dim slCell As Range ' Last Cell
Dim rCount As Long ' Source/Destination Rows Count
For Each sws In wb.Worksheets
If StrComp(sws.Name, dName, vbTextCompare) <> 0 Then ' exclude 'dws'
' Find header cell and last cell.
With sws.Columns(sCol)
Set shCell = _
.Find(sHeader, .Cells(.Cells.Count), xlFormulas, xlWhole)
Set slCell = .Find("*", , xlFormulas, , , xlPrevious)
End With
If Not shCell Is Nothing Then
If Not slCell Is Nothing Then
rCount = slCell.Row - shCell.Row ' without header
If rCount > 0 Then
Set srg = shCell.Offset(1).Resize(rCount)
dfCell.Resize(rCount).Value = srg.Value ' copy
Set dfCell = dfCell.Offset(rCount) ' next
End If
End If
End If
End If
Next sws
MsgBox "Done.", vbInformation
End Sub
Please heed this post: How to avoid using Select in Excel VBA. As second answer mentions, avoid any use of ActiveWorkbook, Activate, and Select for efficiency, maintenance, and readability.
Instead, explicitly qualify all Workbook, Worksheet, Cells, Range, and other objects. In fact, consider range assignment and avoid the need of copy and paste:
Sub LoopCopySheetsData()
Dim i As Integer, totalWS As Integer
Dim headRow As Long, lastRow As Long, headRowMaster As Long, lastRowMaster As Long
'totalWS = ThisWorkbook.Sheets.Count
totalWS = 4
For i = 2 To totalWS
If i < (totalWS + 1) Then
With ThisWorkbook.Sheets(i)
headRow = .Range("A:A").Find(What:="Data", LookIn:=xlValues).Row
lastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
With ThisWorkbook.Sheets("Sheet1")
headRowMaster = .Cells(.Rows.Count, "D").End(xlUp).Row
lastRowMaster = headRowMaster + (lastRow - headRow)
' ASSIGN VALUES BY RANGE
.Range("D" & headRowMaster + 1 & ":D" & lastRowMaster).Value = _
ThisWorkbook.Sheets(i).Range("A" & headRow + 1 & ":A" & lastRow).Value
End With
End If
Next i
End Sub

VBA Loop : Copy / Paste destination offsetting

First of all thanks for your help. I need to copy / paste datas. The idea is the next : depending on the cells content from the sheet AAA I want to copy / paste the datas to the corresponding sheet (XXX if XXX or to ZZZ if ZZZ).My macro worked but the issue is that I have an offset bothering me. Imagine , the first lap will paste the data to XXX , but the second lap will copy to ZZZ , in this case I have an issue because it will copy paste to the 3rd cells (3,1) whereas the cell(2,1) is empty
Sub CopyPastingMyDate()
Dim i As Long
Dim lrow As Long
Dim lcol As Long
Dim RngOne As Range
Dim RngTwo As Range
Dim ws As Worksheet
Set ws = ThisWorkbook.Worksheets("AAA")
lrow = ws.Cells(Rows.Count, 1).End(xlUp).Row
lcol = ws.Cells(1, Columns.Count).End(xlToLeft).Column
Set RngOne = ws.Range(ws.Cells(lrow, 1), ws.Cells(1, lcol))
For i = 2 To lrow
Set RngOne = ws.Range(ws.Cells(lrow, 1), ws.Cells(1, lcol))
If ws.Cells(i, 1) = "XXX" Then
Set RngTwo = ThisWorkbook.Worksheets("SheetXXX").Range(ThisWorkbook.Worksheets("SheetXXX").Cells(i, 1), ThisWorkbook.Worksheets("SheetXXX").Cells(i, lcol))
RngOne.Copy
RngTwo.PasteSpecial xlAll
End If
If ws.Cells(i, 1) = "ZZZ" Then
Set RngTwo = ThisWorkbook.Worksheets("SheetZZZ").Range(ThisWorkbook.Worksheets("SheetZZZ").Cells(i, 1), ThisWorkbook.Worksheets("SheetZZZ").Cells(i, lcol))
RngOne.Copy
RngTwo.PasteSpecial xlAll
End If
Next i
End Sub
How to fix it please ? I want to copy paste to from the first available cell. Thanks to all of you.
JaNa
Try this. I might be misunderstanding what you're copying though: I'm assuming each row needs to be copied to the correct sheet?
Sub CopyPastingMyDate()
Dim i As Long
Dim lrow As Long
Dim lcol As Long
Dim RngOne As Range
Dim RngTwo As Range
Dim ws As Worksheet, dest, wsDest As Worksheet
Set ws = ThisWorkbook.Worksheets("AAA")
lrow = ws.Cells(Rows.Count, 1).End(xlUp).Row
lcol = ws.Cells(1, Columns.Count).End(xlToLeft).Column
Set RngOne = ws.Range(ws.Cells(lrow, 1), ws.Cells(1, lcol))
For i = 2 To lrow
Select Case ws.Cells(i, 1).Value 'which destination sheet?
Case "XXX": dest = "SheetXXX"
Case "ZZZ": dest = "SheetZZZ"
Case Else: dest = ""
End Select
If Len(dest) > 0 Then
ws.Cells(i, 1).Resize(1, lcol).Copy 'copy the row
Set wsDest = ThisWorkbook.Worksheets(dest)
wsDest.Cells(wsDest.Rows.Count, 1).End(xlUp).Offset(1, 0).PasteSpecial xlAll
End If
Next i
End Sub
I have found a way to solve my issue by introducing a new variable x = last_row + 1 . I replaced in i in RngTwo by x .

Can anyone suggest me how to make this code work faster? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I am dealing with around 9000 data in my excel dataset. My goal is to find the match value between A column (sheet1) and A column(sheet2) if there is a match then copy the whole row from sheet 2 and put beside match value in sheet1. This is the code I have if you guys have any suggestions to make it work faster then please do let me know.
Dim sht11 As Worksheet, sht22 As Worksheet
Set sht11 = Worksheets("sheet1")
Set sht22 = Worksheets("sheet2")
Sheet1LastRow = Worksheets("sheet1").Range("A" &
Rows.Count).End(xlUp).Row
Sheet2LastRow = Worksheets("sheet2").Range("A" & Rows.Count).End(xlUp).Row
For j = 1 To Sheet1LastRow
For i = 1 To Sheet2LastRow
If sht11.Cells(j, 1).Value = sht22.Cells(i, 1).Value Then
sht11.Cells(j, 9).Resize(1, 124).Value = _
sht22.Cells(i, 9).Resize(1, 124).Value
Else
End If
Next i
Next j
While there is already a valid answer, in terms of speed the less you interact with the sheets, the better. See below for an alternative, and comments in the code for more details:
Sub copyValues()
Dim wb As Workbook: Set wb = ActiveWorkbook
Dim wsSrc As Worksheet: Set wsSrc = wb.Worksheets("Sheet2")
With wsSrc
Dim lRowSrc As Long: lRowSrc = .Cells(.Rows.Count, 1).End(xlUp).Row 'get last row in source data
Dim lColSrc As Long: lColSrc = .Cells(1, .Columns.Count).End(xlToLeft).Column 'get last column in source data
Dim arrSrc As Variant: arrSrc = .Range(.Cells(1, 1), .Cells(lRowSrc, lColSrc)) 'allocate the data to an array
End With
Dim wsDst As Worksheet: Set wsDst = wb.Worksheets("Sheet1")
With wsDst
Dim lRowDst As Long: lRowDst = .Cells(.Rows.Count, 1).End(xlUp).Row 'get last row in destination data
Dim lColDst As Long: lColDst = 8 '.Cells(1, .Columns.Count).End(xlToLeft).Column 'get last column in destination data - if no other data, can use the dynamic version, otherwise use the set value i guess
Dim arrDst As Variant: arrDst = .Range(.Cells(1, 1), .Cells(lRowDst, lColSrc + lColDst)) '
End With
Dim Rd As Long, Rs As Long, C As Long
For Rd = LBound(arrDst) To UBound(arrDst) 'iterate through all rows in the destination data
For Rs = LBound(arrSrc) To UBound(arrSrc) 'iterate through all rows in the source data
If arrDst(Rd, 1) = arrSrc(Rs, 1) Then 'if there is a match
For C = LBound(arrDst, 2) + lColDst To UBound(arrDst, 2) 'iterate through all columns in the source
arrDst(Rd, C) = arrSrc(Rs, C - lColDst) 'allocate to the destination array
Next C
'alternatively, can write the values directly back to the sheet (comment the C loop above and values allocation below the loops)
' With wsDst
' .Range(.Cells(Rd, 9), .Cells(Rd, lColSrc + lColDst)).Value = _
' wsSrc.Range(wsSrc.Cells(Rs, 1), wsSrc.Cells(Rs, lColSrc)).Value
' End With
Exit For
End If
Next Rs
Next Rd
With wsDst
.Range(.Cells(1, 1), .Cells(lRowDst, lColSrc + lColDst)) = arrDst 'put the values back on the sheet
End With
End Sub
I think this may help you:
Option Explicit
Sub test()
Dim rngToSearchIn As Range, rngFound As Range
Dim LastRow1 As Long, LastRow2 As Long, i As Long, LastColumn1 As Long, LastColumn2 As Long
Dim arr As Variant
Dim strSearchValue As String
Dim ws1 As Worksheet, ws2 As Worksheet
With ThisWorkbook
Set ws1 = .Worksheets("Sheet1")
Set ws2 = .Worksheets("Sheet2")
End With
With ws1
LastRow1 = .Cells(.Rows.Count, "A").End(xlUp).Row
arr = .Range("A1:A" & LastRow1)
End With
With ws2
LastRow2 = .Cells(.Rows.Count, "A").End(xlUp).Row
Set rngToSearchIn = .Range("A1:A" & LastRow2)
End With
For i = LBound(arr) To UBound(arr)
strSearchValue = arr(i, 1)
Set rngFound = rngToSearchIn.Find(What:=strSearchValue, LookAt:=xlWhole, MatchCase:=True, SearchFormat:=False)
If Not rngFound Is Nothing Then
With ws2
LastColumn2 = .Cells(rngFound.Row, .Columns.Count).End(xlToLeft).Column
.Range(.Cells(rngFound.Row, 1), .Cells(rngFound.Row, LastColumn2)).Copy
End With
With ws1
LastColumn1 = .Cells(i, .Columns.Count).End(xlToLeft).Column
.Cells(i, LastColumn1 + 1).PasteSpecial Paste:=xlPasteValues
End With
End If
Next i
End Sub

Resources