Napisałem funkcję w VBA i poniżej przedstawiłem uproszczoną wersję. Zasadniczo wymaga argumentu, wykonuje preformat vlookup
na nazwanym zakresie w arkuszu przy użyciu wartości argumentu, przekazuje wartość vlookedup do innej funkcji, a na koniec zwraca wynik.
Korzystam z tej funkcji bardzo często ... jak 50 000 razy w moim skoroszycie. W rezultacie mój skoroszyt jest dość powolny do obliczenia.
Czy mogę wprowadzić kilka prostych zmian w tej funkcji, aby zoptymalizować ją pod kątem szybkości?
Czytelność nie jest problemem, chcę tylko, aby ta rzecz działała szybciej. Kod musi jednak pozostać w 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
microsoft-excel
worksheet-function
vba
optimize
rvictordelta
źródło
źródło
Odpowiedzi:
Pierwsza strategia: zoptymalizuj samą funkcję
Powinien podwoić prędkość
Wynika to z tego, że wyszukujesz zakres o nazwie „LookupRange” tylko raz zamiast dwa razy i tylko raz szukasz właściwej linii zamiast dwa razy.
Druga strategia: odzyskaj zasięg tylko raz z góry
Prawdopodobnie 4 razy szybciej
Jeśli pobieramy zakres w kodzie używającym
yield
funkcji, musimy to zrobić tylko razIstnieje wariant tej strategii, w którym zadeklarujesz wyszukiwanie poza wszystkimi procedurami, tak jak w przypadku poniższego słownika.
Trzecia strategia: umieść wszystkie istotne wartości w słowniku
O rząd wielkości szybciej, jeśli
Yield
często dzwonisz do BARDZO.Name
słownika odbywa się w słowniku, który jest o wiele bardziej wydajny niż wyszukiwanie zakresuTo jest kod:
źródło
Name
zwykle przeglądasz w jednym cyklu przetwarzania.Kilka rzeczy, które bym zrobił -
Gdy przekazujesz argumenty, domyślnie przekazujesz je ByRef, który jest wolniejszy niż ByVal i widząc, że nie potrzebujesz referencji, po prostu je przekaż
ByVal
.Nie jestem pewien, czy
match
jest to znacznie szybsze niż,vlookup
ale używającmatch
cięcia skrócisz procesy o połowę i po prostu odniesiesz się do potrzebnego wiersza.Przekształciłem również zmienne na standardowe nazwy konwencji VBA .
Nie potrzebujesz również
Application.run
wywoływania makra. Upewnij się, że przekazuje również argumenty ByValźródło
LookupRange
aby dopasowanie działało podczas definiowaniafoundRow