Echo_2
Echo_2

Reputation: 71

Excel Macro, vlookup function works slow, ways to speed up macro

Hello stackexchange community.

I've built a simple tables converter, the main function of which is to convert the table from

1a Value
1b Value
1c Value
1d Value 

to

    a     b     c     d
1 Value Value Value Value

Unfortunately, the macro runs pretty slow (~ 3 lines per second for one column).

I'd really appreciate if someone could take a look at my piece of code and suggest the way to speed it up.

Here's the piece of code:

Dim LastFinalList As Integer: LastFinalList = Sheet1.Range("O1000").End(xlUp).Row

For Col = 16 To 19

For c = 2 To LastFinalList

searchrange = Sheet1.Range("J:L")

lookfor = Sheet1.Cells(c, 15) & Sheet1.Cells(1, Col)
CountFor = Application.VLookup(lookfor, searchrange, 3, False)

If IsError(CountFor) Then
Sheet1.Cells(c, Col).Value = "0"
Else
Sheet1.Cells(c, Col).Value = CountFor

End If

Next c

Next Col

Thanks in advance and best regards!

UPD:

The Data in unconverted table looks like this (e.g):

                      Updated by Macro  
Value Number Type    Key  Count Average Value
  10    1     a      1a     2       20
  30    1     a      1a     2       20
  40    1     b      1b     1       40
  50    1     c      1c     1       50 

So it is also required to calculate averages of repeating types, create a unique list of Numbers (which is LastFinalList in my case) and finally convert it to this:

Number  a    b    c
   1    20   40   50

application.vlookupseraches by Number&Type Key, which is also assigned in the unconverted table by macro. The same time those Keys are counted, in order to calculate average for the repeating ones.

Everything works in a blink of an eye till it comes to 'to update final table part.

Full Code:

    Sub ConvertToTable()

Dim LastMeter As Integer: LastMeter = Sheet1.Range("I1000").End(xlUp).Row

Sheet1.Range(Cells(2, 9), Cells(LastMeter, 9)).AdvancedFilter Action:=xlFilterCopy, CopyToRange:=Sheet1.Range("O2"), Unique:=True
Sheet1.Range("O1").Value = "The List"
Sheet1.Range("O2").Delete Shift:=xlUp

' to assign keys
For i = 2 To LastMeter
Set CountOpt = Sheet1.Cells(i, 10)
Sheet1.Cells(i, 10).FormulaR1C1 = "=r[0]c[-1]&r[0]c[-2]"
Sheet1.Cells(i, 11).FormulaR1C1 = "=COUNTIF(c10:c10, r[0]c10)"

Next i

'to calculate averages
For x = 2 To LastMeter
If Sheet1.Cells(x, 11).Value = 1 Then
Sheet1.Cells(x, 12).FormulaR1C1 = "=rc7"
ElseIf Sheet1.Cells(x, 11).Value > 1 Then
If Sheet1.Cells(x, 10).Value <> Sheet1.Cells(x - 1, 10).Value Then
Sheet1.Cells(x, 12).FormulaR1C1 = "=ROUND((SUM(rc7:r[" & Sheet1.Cells(x, 11).Value - 1 & "]c7)/" & Sheet1.Cells(x, 11).Value & "),4)"
Else
Sheet1.Cells(x, 12).FormulaR1C1 = "=r[-1]c12"
End If
End If

Next x

'to update final table
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual

Dim LastFinalList As Integer: LastFinalList = Sheet1.Cells(Rows.Count, 15).End(xlUp).Row

For Col = 16 To 19

For c = 2 To LastFinalList

searchrange = Sheet1.Range("J:L")

lookfor = Sheet1.Cells(c, 15) & Sheet1.Cells(1, Col)
CountFor = Application.VLookup(lookfor, searchrange, 3, False)

If IsError(CountFor) Then
Sheet1.Cells(c, Col).Value = "0"
Else
Sheet1.Cells(c, Col).Value = CountFor

End If

Next c

Next Col

Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True

Sheet1.Range("O1").Select

End Sub

Also, initially i had a SUMIF formula instead of application.vlookup to be input in each cell in the converted table. But the code was working as slow as now an was bit bulky, that's why i've decide to switch to VLOOKUP.

The thing is, if it actually the way application.vlookup works (with 0.3sec delay for each row), then i guess there's nothing that can be done, and i'm ok to accept that. Although, if that's not the case, i'd really appreciate if someone could help me out and speed up the process.

Thanks!

Upvotes: 0

Views: 978

Answers (2)

Echo_2
Echo_2

Reputation: 71

It appears that application.vlookup in my particular case was indeed working very slow (no idea why, though). I've managed to improve macro by replacing vlookup with SUMIF formula in each cell, so now the converted table is updated instantly. Thanks everyone who participated and provided their suggestions!

Upvotes: 0

Tushar
Tushar

Reputation: 3623

You can redefine your LastFinalList variable something like

LastFinalList = Sheets("Sheet1").UsedRange.Rows.Count

OR

LastFinalList = Sheets("Sheet1").Cells(Rows.Count, 2).End(xlUp).Row

instead of explicitly defining used range.

Also use following line of code before your code

Application.ScreenUpdating = False 

(Turn screen updating off to speed up macro code. User won't be able to see what the macro is doing, but it will run faster.)

After the whole code runs you can(optional) turn screen updating on with

Application.ScreenUpdating = True

Upvotes: 1

Related Questions