2009-07-13 17 views
17

Nie ma specjalnego typu dla funkcji w języku VBA. Trudno mi zobaczyć, jak dodać funkcje jako argumenty do funkcji w Excel VBA.excel vba: Typy specjalne - funkcje jako argumenty funkcji

Próbuję wykonać jest coś takiego:

function f(g as function, x as string) as string 
     f = g(x) 
end function 

Obecnie mam grupę małych funkcji powtarzania wszystko sami, ale z jednego połączenia do określonej funkcji.

Odpowiedz

13

Z Twojego kodu funkcja g przyjmuje parametr łańcuchowy i zwraca ciąg znaków. Proponuję utworzyć moduł klasy o nazwie IStringFunction do działania jako definicji interfejsu, że wszystkie funkcje będą wspierać, a więc:

moduł klasy: IStringFunction

Public Function Evaluate(ByVal s As String) As String 
End Function 

Następnie należy utworzyć kilka przykładowych funkcji wdrożenie tego interfejsu:

Class Moduł: HelloStringFunction

Implements IStringFunction 

Public Function IStringFunction_Evaluate(ByVal s As String) As String 
    IStringFunction_Evaluate = "hello " & s 
End Function 

moduł klasy: GoodbyeStringFunction

Implements IStringFunction 

Public Function IStringFunction_Evaluate(ByVal s As String) As String 
    IStringFunction_Evaluate = "goodbye " & s 
End Function 

... i wreszcie, niektóre kodu testu, aby wykonywać funkcje:

(Standard) Moduł: test

Sub Test() 

    Dim oHello As New HelloStringFunction 
    Dim oGoodbye As New GoodbyeStringFunction 

    MsgBox Evaluate(oHello, "gary") 
    MsgBox Evaluate(oGoodbye, "gary") 

End Sub 

Private Function Evaluate(ByVal f As IStringFunction, ByVal arg As String) As String 
    Evaluate = f.Evaluate(arg) 
End Function 

Uwaga że klasa implementująca interfejs musi mieć metody o nazwie <Interface>_<Method>, jak w powyższym przykładzie, a nie tylko <Method>, jak można się spodziewać.

Pobierz simple demo lub intermediate demo tutaj

+1

To mu nie pomoże, ponieważ wciąż musi napisać oddzielną funkcję oceny dla każdej klasy. – Treb

+0

@Treb: może nie rozumiem pytania, ale nie rozumiem, co masz na myśli. Każda klasa reprezentuje inną funkcję, więc oczywiście musi mieć oddzielną funkcję oceny! Może gdyby problem mógł zostać powtórzony, byłby jaśniejszy. –

+0

Cześć, myślę, że to jest właściwa odpowiedź. W ten sposób robię to w językach oo, po prostu nie wiedziałem, że interfejsy istnieją w VBA - moja wina. Pamiętam, jak widziałem tę technikę po raz pierwszy w * małym java *. Ale muszę przetestować proponowane rozwiązanie. W tej chwili dostałem komunikat o błędzie dotyczący nie implementowania interfejsu. Public Function Zastosuj (ByVal tmp As Variant) As Boolean Funkcja End --- Wbudowy IBooleanFunction Public Function zastosowania (ByVal tmp jako Variant) As Boolean zastosowanie funkcji = Application.IsText (TMP) End –

15

Od VBA ma swoje korzenie w interaktywnym językiem, to zawsze miał możliwość wykonywania tekst:

function f(g as string, x as string) as string 
     f = application.run(g,x) 
end function 

MyStringA = f("functionA",string1) 
MyStringB = f("functionB",string1) 
+0

to jest ładne, ale nie sądzę, że jest to właściwie to samo, co przekazywanie funkcji, o ile zakresy ... – epeleg

+0

to jest narkotyk! wezmę to, z lub bez idealnego scopingu. – grisaitis

+0

W programie Excel VBA 2010 ta składnia powoduje błąd kompilacji "Oczekiwano: Koniec instrukcji". Parametry wymagają nawiasów wokół nich: f = Application.Run (g, x) –

0

Możliwe jest przekazać funkcję jako Argument, a otrzymasz dokładnie to, czego szukasz, ale jest trochę odurzający. Osiąga się to poprzez wykorzystanie właściwości domyślnej klasy,

utworzyć klasę myFunction zawierające swoją funkcję

Public Function sayHi(ByVal s As String) As String 
    sayHi = "Hi " & s 
End Function 

wyeksportować go i otworzyć.Plik CLS w edytorze tekstowym

powinien pojawić się gdzieś w pliku linię, która definiuje swoją funkcję

Public Function sayHi(ByVal s As String) As String 

Pod nim, dodać linię Attribute Value.VB_UserMemId = 0, tak że teraz wygląda to tak:

Public Function sayHi(ByVal s As String) As String 
Attribute Value.VB_UserMemId = 0 
    sayHi = "Hi " & s 
End Function 

To, co tu zrobiliście, to oznaczenie sayHi jako klasy default property. Teraz można wywołać funkcję przez sam obiekt klasy class(args) zamiast class.function(args)

Zapisz zmieniony plik i zaimportować go do projektu VBA

moduł testowy

Sub test() 
    Dim parameterFunction As Object   'this is what we'll be passing to our routine 
    Set parameterFunction = New myFunction 'create instance of the function object 
    MsgBox f(parameterFunction, "Greedo") 
End Sub 

Function f(ByVal g As Object, ByVal x As String) As String 
     f = g(x) 
End Function 

* NB, to w jaki sposób możesz przekazać jakąkolwiek funkcję; ale możesz zamiast tego podać ByVal g As IStringFunction, aby uzyskać tylko podzbiór z poprawnym interfejsem, zgodnie z Gary McGill's answer

Powiązane problemy