2011-09-13 48 views
8

Estoy tratando de llamar a una función con un nombre de variable que se genera en tiempo de ejecución en función de un valor de cuadro combinado. Esto es sencillo en la mayoría de los lenguajes, pero parece que no puedo resolverlo en Excel VBA, sospecho que es porque realmente no entiendo cómo funciona el compilador. He encontrado varias publicaciones cercanas, pero parece que no funcionan. El código siguiente es incorrecto, pero debería dar una idea de lo que quiero.Función de llamada a Excel VBA con nombre de variable

Gracias

Sub main() 
    'run formatting macros for each institution on format button click 

    Dim fn As String 
    Dim x As Boolean 

    'create format function name from CB value   
    fn = "format_" & CBinst.Value 

    'run function that returns bool 
    x = Eval(fn) 

    ... 

End Sub 

Respuesta

15

CallByName es lo que se necesita para realizar la tarea.

ejemplo: Código en la Hoja1

Option Explicit 
Public Function Sum(ByVal x As Integer, ByVal y As Integer) As Long 
    Sum = x + y 
End Function 

Código es el módulo 1 (módulo bas)

Option Explicit 

Sub testSum() 
Dim methodToCall As String 
methodToCall = "Sum" 

MsgBox CallByName(Sheet1, methodToCall, VbMethod, 1, 2) 
End Sub 

de ejecutar el método testSum llama al método Sum usando el nombre del método dado en una variable de cadena , pasando 2 parámetros (1 y 2). El valor de retorno de la llamada a la función se devuelve como salida de CallByName.

+0

Agradable. Hubiera intentado Evaluar, ya que no sabía eso. –

+0

Excelente, gracias! – BWG

+0

Hola ... ¿Qué pasa si no quiero la función 'suma' en Sheet1 ... pero lo digo en Module1. ¿Cómo puedo llamar a la función 'suma' del Módulo1 utilizando CallByName? Esto no parece funcionar. Por favor avise. – ihightower

0

Usted debe escribir una función que acepta el valor CB como un parámetro y luego utiliza un selecto caso de llamar a la función de formato apropiado.

Algo similar a este

Function SelectFormatting(Name as String) As Boolean 
Select Case CBinst.Value 
Case "Text1": 
    SelectFormatting = Text1FormattingFunction() 
Case "Text2": 
    . 
    . 
    . 
End Select 
End Function 
+0

Gracias por la respuesta. Esta es de hecho la manera directa de resolver este problema. Esperaba resumir la necesidad de agregar casos para cada valor de CB por dos razones: 1) el código será actualizado regularmente por personas de distintas capacidades de codificación y sería agradable permitirles agregar una nueva opción de CB y formatear función sin tocar las tripas del programa y 2) la lista CB puede ser bastante larga. Tal vez esto es simplemente ridículo sobre la ingeniería. – BWG

1

Lo anterior funciona, pero no con un gran número de nombres

Uso Application.Run (MacroName, parámetros)

Tienes que puedan asegurarse de que no es una macro pero es mejor que el anterior ya que no hay una declaración seleccionada.

0

Con respecto a mi respuesta anterior que puede que encuentre esto útil para comprobar si existe la macro

'================================================================================= 
'- CHECK IF A MODULE & SUBROUTINE EXISTS 
'- VBA constant : vbext_pk_Proc = All procedures other than property procedures. 
'- An error is generated if the Module or Sub() does not exist - so we trap them. 
'--------------------------------------------------------------------------------- 
'- VB Editor : Tools/References - add reference TO ...... 
'- .... "Microsoft Visual Basic For Applications Extensibility" 
'---------------------------------------------------------------------------------- 
'- Brian Baulsom October 2007 
'================================================================================== 
Sub MacroExists() 
    Dim MyModule As Object 
    Dim MyModuleName As String 
    Dim MySub As String 
    Dim MyLine As Long 
    '--------------------------------------------------------------------------- 
    '- test data 
    MyModuleName = "TestModule" 
    MySub = "Number2" 
    '---------------------------------------------------------------------------- 
    On Error Resume Next 
    '- MODULE 
    Set MyModule = ActiveWorkbook.VBProject.vbComponents(MyModuleName).CodeModule 
    If Err.Number <> 0 Then 
    MsgBox ("Module : " & MyModuleName & vbCr & "does not exist.") 
    Exit Sub 
    End If 
    '----------------------------------------------------------------------------- 
    '- SUBROUTINE 
    '- find first line of subroutine (or error) 
    MyLine = MyModule.ProcStartLine(MySub, vbext_pk_Proc) 
    If Err.Number <> 0 Then 
    MsgBox ("Module exists  : " & MyModuleName & vbCr _ 
      & "Sub " & MySub & "() : does not exist.") 
    Else 
    MsgBox ("Module : " & MyModuleName & vbCr _ 
     & "Subroutine : " & MySub & vbCr _ 
     & "Line Number : " & MyLine) 
    End If 
End Sub 
'----------------------------------------------------------------------------------- 
Cuestiones relacionadas