First strategy: optimize the function itself
Should double the speed
Public Function Yield(Name As String, Price As Double)
Dim Lookup As Range, rw As Integer
Set Lookup = Range("LookupRange")
rw = Application.WorksheetFunction.Match(Name, Lookup.Resize(ColumnSize:=1), 0)
Yield = 100 * Application.Run("otherCustomFunction", Lookup.Cells(rw, 3), Lookup.Cells(rw, 7), Price)
End Function
This because you only lookup the range with name "LookupRange" once instead of twice and you only look for the right line once instead of twice.
Second strategy: retrieve the range only once upfront
Probably 4 times as fast
If we retrieve the range in the code that uses the yield
function, we only have to do that once
Public Function Yield(Lookup As Range, Name As String, Price As Double)
rw = Application.WorksheetFunction.Match(Name, Lookup.Resize(ColumnSize:=1), 0)
Yield = 100 * Application.Run("otherCustomFunction", Lookup.Cells(rw, 3), Lookup.Cells(rw, 7), Price)
End Function
Public Sub CallingRoutine()
Dim Lookup As Range, rw As Integer
Set Lookup = Range("LookupRange")
' Some code
For Each someItem In someSet
Dim amount As Double, Name As String, Price As Double
' Some code to deter;ine name and price
amount = Yield(Lookup, Name, Price)
' Some code that used the yield
Next someThing
End Sub
There is a variant of this strategy where you declare Lookup outside all routines, like I do with the dictionary below..
Third strategy: Put all relevant values in a dictionary
An order of magnitude faster if you call Yield
VERY often.
- You look up the named range
- You ask all values from excel at once
- You look up the
Name
s in a dictionary, which is way more efficient than a looking up in a range
This is the code:
Public Function Yield(Name As String, Price As Double)
If LookDict Is Nothing Then
Set LookDict = New Dictionary
Dim LookVal As Variant, rw As Integer, ToUse As ToUseType
LookVal = Range("LookupRange").Value
For rw = LBound(LookVal, 1) To UBound(LookVal, 1)
Set ToUse = New ToUseType
ToUse.Row3Val = LookVal(rw, 3)
ToUse.Row7Val = LookVal(rw, 7)
LookDict.Add LookVal(rw, 1), ToUse
Next rw
End If
Set ToUse = LookDict.Item(Name)
Yield = 100 * Application.Run("otherCustomFunction", _
ToUse.Row3Val, ToUse.Row7Val, Price)
End Function
Public Sub CallingRoutine()
' Some code
For Each someItem In someSet
Dim amount As Double, Name As String, Price As Double
' Some code to deter;ine name and price
amount = Yield(Name, Price)
' Some code that used the yield
Next someThing
End Sub
are you sure that indeed vlookup is the responsible for the long time, or can it be the "otherCustomFunction"? – Máté Juhász – 2016-03-22T08:24:52.037
otherCustomFunction almost certainly has something to do with it, but it's not something I can edit in this scenario. I would just like to optimize the lookup and variable assignment. – rvictordelta – 2016-03-22T12:51:30.063
This question should be on codereview, not on superuser – Dirk Horsten – 2016-03-22T21:20:05.437