私はVBAで関数を作成し、以下に簡略化されたバージョンを提供しました。基本的に、引数を取り、引数の値を使用してシート内の名前付き範囲でvlookup
を実行し、vlookedup値を別の関数に渡し、最後に結果を返します。
私はこの関数をよく使用します。ワークブックで50,000回のように。その結果、私のワークブックの計算はかなり遅くなります。
この関数に速度を最適化するために行うことができるいくつかの簡単な変更はありますか?
読みやすさは問題ではありません。私はこれをより速く実行したいだけです。ただし、コードはVBAにとどまる必要があります。
Public Function Yield(Name As String, Price As Double)
Dim DDate As Double
Dim ConversionFactor As Double
DDate = Application.WorksheetFunction.VLookup(Name, Range("LookupRange"), 3, 0)
ConversionFactor = Application.WorksheetFunction.VLookup(Name, Range("LookupRange"), 7, 0)
Yield = 100 * Application.Run("otherCustomFunction",DDate,ConversionFactor,Price)
End Function
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
これは、「LookupRange」という名前の範囲を2回ではなく1回だけ検索し、正しい行を2回ではなく1回だけ検索するためです。
yield
関数を使用するコードで範囲を取得する場合、それを1回だけ実行する必要があります。
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
以下の辞書で行うように、すべてのルーチンの外部でルックアップを宣言するこの戦略の変形があります。
Yield
を非常に頻繁に呼び出すと、桁違いに速くなります。Name
sを検索します。これは、範囲で検索するよりもはるかに効率的です。これはコードです:
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
私がするいくつかのこと-
Option Explicit
Public Function Yield(ByVal lookupName As String, ByVal price As Double)
Dim dDate As Double
Dim conversionFactor As Double
Dim foundRow As Long
foundRow = Application.WorksheetFunction.Match(lookupName, Range("LookupRange"))
dDate = Range("lookuprange").Cells(foundRow, 3)
converstionfactor = Range("LookupRange").Cells(foundRow, 7)
Yield = 100 * otherCustomFunction(dDate, conversionFactor, price)
End Function
引数を渡すときは、デフォルトで、ByValよりも遅いByRefを渡し、必要がないことを確認します。 referenceはそれらにByVal
を渡すだけです。
match
がvlookup
よりもはるかに速いかどうかはわかりませんが、match
を使用すると、プロセスが半分になり、必要な行を参照するだけです。
また、変数を 標準のVBA命名規則 名前に変換しました。
また、マクロを呼び出すためにApplication.run
は必要ありません。それが引数ByValも渡していることを確認してください