2009-07-13 7 views
17

Es gibt keinen speziellen Typ für Funktionen in VBA. Es ist schwer für mich zu sehen, wie Funktionen Funktionen in Excel VBA als Argumente hinzugefügt werden.Excel VBA: Sondertypen - Funktionen als Argument für Funktionen

Was ich versuche zu erreichen ist etwas wie folgt aus:

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

Derzeit habe ich eine Gruppe von kleinen Funktionen alle sich zu wiederholen, aber mit einem Aufruf zu einer bestimmten Funktion.

Antwort

13

Aus Ihrem Code nimmt die Funktion g einen String-Parameter und gibt eine Zeichenfolge zurück. Ich schlage vor, Sie ein Klassenmodul erstellen IStringFunction genannt als die Definition einer Schnittstelle zu handeln, die alle Funktionen unterstützen, also:

Klassenmodul: IStringFunction

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

Dann ein paar Beispielfunktionen erstellen Umsetzung dieser Schnittstelle:

Klassenmodul: HelloStringFunction

Implements IStringFunction 

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

Klassenmodul: GoodbyeStringFunction

Implements IStringFunction 

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

... und schließlich einige Testcode die Funktionen ausüben:

(Standard) Module: 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 

Hinweis dass die Klasse, die die Schnittstelle implementiert, Methoden wie <Interface>_<Method> wie im obigen Beispiel haben muss, nicht nur <Method> wie Sie es erwarten würden.

Laden Sie die simple demo oder intermediate demo hier

+1

zu bekommen Das hilft ihm nicht wirklich, weil er noch eine separate Bewertungsfunktion für jede Klasse schreiben muss. – Treb

+0

@Treb: vielleicht verstehe ich die Frage nicht, aber ich verstehe nicht, was du meinst. Jede Klasse repräsentiert eine andere Funktion, also muss sie natürlich eine separate Bewertungsfunktion haben! Vielleicht wäre es klarer, wenn das Problem neu formuliert werden könnte. –

+0

Hallo, ich denke das ist die richtige Antwort. Dies ist der Weg, es in Oo-Sprachen zu tun, ich wusste nur nicht, dass Schnittstellen in VBA existieren - mein Fehler. Ich erinnere mich, diese Technik das erste Mal in * einem kleinen Java * gesehen zu haben. Aber ich muss die vorgeschlagene Lösung testen. Im Moment habe ich eine Fehlermeldung erhalten, dass die Schnittstelle nicht implementiert wurde. Public Function (ByVal tmp As Variant) As End Function --- Implementiert IBooleanFunction Public Function Boolean gelten gelten (ByVal tmp As Variant) As Boolean gelten = Application.IsText (tmp) End Function –

15

Da VBA seine Wurzeln in einer interaktiven Sprache hat, hat es schon immer die Möglichkeit, Text auszuführen:

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

das ist nett, aber ich denke nicht, dass es tatsächlich das gleiche ist wie eine Funktion zu übergeben, soweit Bereiche gehen ... – epeleg

+0

das ist Dope! Ich nehme es, mit oder ohne ideales Scoping. – grisaitis

+0

In Excel VBA 2010 gibt diese Syntax einen Kompilierungsfehler "Erwartet: Ende der Anweisung". Die Parameter benötigen Klammern um sie herum: f = Application.Run (g, x) –

0

Es ist möglich, eine Funktion zu übergeben ein Argument, und erhalten genau das Verhalten, das Sie suchen, aber es ist ein bisschen hacky. Dies wird durch Ausnutzen der Standardeigenschaft einer Klasse erreicht,

Erstellen Sie eine Klasse myFunction Ihre Funktion enthält

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

Export es, und öffnen Sie die.cls-Datei in einem Texteditor

Sie sollten irgendwo in der Datei, eine Linie, die Ihre Funktion

Public Function sayHi(ByVal s As String) As String 

Darunter definiert, fügen Sie die Zeile Attribute Value.VB_UserMemId = 0, so dass es jetzt so aussieht:

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

Was Sie hier getan haben, ist sayHi als default property der Klasse zu markieren. Jetzt können Sie die Funktion, die durch das Klassenobjekt aufrufen allein class(args), anstatt class.function(args)

Speichern Sie die geänderte Datei und importieren Sie es in Ihrem VBA-Projekt

Test-Modul

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, diese So kannst du jede Funktion bestehen; aber Sie können stattdessen ByVal g As IStringFunction angeben, um nur die Teilmenge mit der richtigen Schnittstelle nach Gary McGill's answer

Verwandte Themen