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