Reputation: 35
I'm currently running a Macro that looks for a value from column A of 'sheet 1' in column C of sheet 2, if these match then the value from column B of sheet 1 should be copied to column M of the corresponding row in sheet 2.
The Macro I have works, but because this is a massive worksheet, the loop in it is taking far too much time. This is because sheet 1 has around 300,000 rows and the value in each instance is unique. in Sheet 2 there are around 50,000 rows. It's been running overnight and has only reached 60,000 rows in sheet 1 so far
I'm by no means a VBA expert, or even intermediate but from what I've read maybe using Find would be faster than looking for a match and looping?
this is the macro i'm currently using
Option Explicit
Sub lookupandcopy()
Application.Screenupdating = True
Dim j As Long, i As Long, lastRow1 As Long, lastRow2 As Long
Dim sh_1, sh_3 As Worksheet
Dim MyName As String
Set sh_1 = Sheets("sheet1")
Set sh_3 = Sheets("sheet2")
lastRow1 = sh_1.UsedRange.Rows.Count
For j = 2 To lastRow1
MyName = sh_1.Cells(j, 1).Value
lastRow2 = sh_3.UsedRange.Rows.Count
For i = 2 To lastRow2
If sh_3.Cells(i, 3).Value = MyName Then
sh_3.Cells(i, 13).Value = sh_1.Cells(j, 2).Value
End If
Next i
Next j
Application.Screenupdating = True
End Sub
If I've missed anything off or any other detail that's needed please let me know!
Upvotes: 3
Views: 6245
Reputation: 51988
You seem to be using columns A and B in sheet1 as a dictionary (and accessing the values by a linear search). Why not load the values into a dictionary objects which has O(1) search? Make sure that your project includes a reference to Microsoft Scripting Runtime (tools > references in the VBE if you haven't done such things) then try:
Sub lookupandcopy()
Application.ScreenUpdating = False
Dim AVals As New Dictionary
Dim i As Long, j As Long, lastRow1 As Long, lastRow2 As Long
Dim sh_1, sh_3 As Worksheet
Dim MyName As String
Set sh_1 = Sheets("sheet1")
Set sh_3 = Sheets("sheet2")
With sh_1
lastRow1 = .Range("A:A").Rows.Count 'last row in spreadsheet
lastRow1 = .Cells(lastRow1, 1).End(xlUp).Row 'last used row in column A
'load the AVal dict
For j = 2 To lastRow1
MyName = .Cells(j, 1).Value
If Len(MyName) > 0 Then AVals.Add MyName, .Cells(j, 2).Value
Next j
End With
With sh_3
lastRow2 = .Range("A:A").Rows.Count
lastRow2 = .Cells(lastRow2, 3).End(xlUp).Row 'last used row in column 3
For i = 2 To lastRow2
MyName = .Cells(i, 3).Value
If AVals.Exists(MyName) Then
.Cells(i, 13).Value = AVals.Item(MyName)
End If
Next i
End With
Application.ScreenUpdating = True
End Sub
If you have repeated values in column A then you would need to do something like store as values collections of row indices where the value occurs, but the effort of setting up such a dictionary would still be better than using nested loops.
Upvotes: 1