2009-07-13 14 views
17

Non esiste un tipo speciale per le funzioni in VBA. È difficile per me vedere come aggiungere funzioni come argomenti alle funzioni in VBA di Excel.excel vba: Tipi speciali - Funzioni come argomenti delle funzioni

Quello che sto cercando di realizzare è qualcosa di simile:

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

Attualmente, ho un gruppo di piccoli tutte le funzioni di ripetere se stessi, ma con una sola chiamata a una funzione specifica.

risposta

13

Dal codice, la funzione g accetta un parametro stringa e restituisce una stringa. Vi suggerisco di creare un modulo di classe chiamato IStringFunction ad agire come la definizione di un'interfaccia che tutte le funzioni sosterrà, in tal modo:

modulo di classe: IStringFunction

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

Poi, crea un paio di esempi di funzioni implementa questa interfaccia: Modulo

Classe: HelloStringFunction

Implements IStringFunction 

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

modulo di classe: GoodbyeStringFunction

Implements IStringFunction 

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

... e, infine, un po 'di codice di prova per esercitare le funzioni di:

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

Nota che la classe che implementa l'interfaccia deve avere metodi denominati <Interface>_<Method> come nell'esempio sopra, non solo <Method> come ti aspetteresti.

Scaricare il simple demo o intermediate demo qui

+1

Questo non lo aiuta, perché deve ancora scrivere una funzione di valutazione separata per ogni classe. – Treb

+0

@Treb: forse non capisco la domanda, ma non vedo cosa intendi. Ogni classe rappresenta una funzione diversa, quindi ovviamente deve avere una funzione di valutazione separata! Forse se il problema potesse essere ribadito sarebbe più chiaro. –

+0

Ciao, penso che questa sia la risposta giusta. Questo è il modo di farlo in oo-lingue, semplicemente non lo sapevo, che le interfacce esistono in VBA - colpa mia. Ricordo di aver visto questa tecnica la prima volta in * un po 'di java *. Ma devo testare la soluzione proposta. Al momento ho ricevuto un messaggio di errore per non implementare l'interfaccia. Funzione Pubblica applicare (ByVal tmp come variante) come booleano End Function --- Utensili IBooleanFunction Funzione Pubblica applicare (ByVal tmp come variante) come booleano applicano = Application.IsText (tmp) End Function –

15

Dal VBA ha le sue radici in un linguaggio interattivo, ha sempre avuto la capacità di eseguire il testo:

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

questo è bello, ma non credo che sia in realtà lo stesso di passare una funzione fino agli ambiti ... – epeleg

+0

che è stupido! Lo prenderò, con o senza l'ambito ideale. – grisaitis

+0

In Excel VBA 2010, questa sintassi genera un errore di compilazione "Previsto: fine dell'istruzione". I parametri hanno bisogno di parentesi intorno a loro: f = Application.Run (g, x) –

0

E 'possibile passare una funzione come un argomento, e ottenere esattamente il comportamento che stai cercando, ma è un po 'hacky. Questo risultato è ottenuto sfruttando la proprietà predefinita di una classe,

creare una classe myFunction contenente la funzione

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

Export, e aprire il.file di cls in un editor di testo

Dovreste vedere da qualche parte nel file, una linea che definisce la funzione

Public Function sayHi(ByVal s As String) As String 

Sotto di esso, aggiungere la riga Attribute Value.VB_UserMemId = 0, in modo che ora assomiglia a questo:

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

Quello che hai fatto è quello di segnare sayHi come default property della classe. Ora è possibile chiamare la funzione di solo l'oggetto di classe class(args), piuttosto che class.function(args)

Salvare il file modificato e importarlo nel progetto VBA

modulo di test

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, questo modo in cui puoi passare qualsiasi funzione; ma puoi invece specificare ByVal g As IStringFunction per ottenere solo il sottoinsieme con l'interfaccia corretta come da Gary McGill's answer

Problemi correlati