2010-06-10 16 views
11

Me gustaría agregar un control y un evento asociado en tiempo de ejecución en Excel usando VBA, pero no sé cómo agregar los eventos.Cómo agregar eventos a los controles creados en tiempo de ejecución en Excel con VBA

Probé el código siguiente y el botón se creó correctamente en mi forma de usuario, pero el evento de clic asociado que debería mostrar el mensaje de saludo no funciona.

Cualquier consejo/corrección sería bienvenido.

Dim Butn As CommandButton 
Set Butn = UserForm1.Controls.Add("Forms.CommandButton.1") 
With Butn 
    .Name = "CommandButton1" 
    .Caption = "Click me to get the Hello Message" 
    .Width = 100 
    .Top = 10 
End With 

With ThisWorkbook.VBProject.VBComponents("UserForm1.CommandButton1").CodeModule 
    Line = .CountOfLines 
    .InsertLines Line + 1, "Sub CommandButton1_Click()" 
    .InsertLines Line + 2, "MsgBox ""Hello!""" 
    .InsertLines Line + 3, "End Sub" 
End With 
UserForm1.Show 
+0

Ver [esta respuesta] (http: // stackoverflow .com/a/1923457/98422) para una introducción rápida al uso de eventos en tiempo de ejecución en VBA. –

+0

pregunta bellamente redactada. Gracias, tenía exactamente la misma duda – BrainO2

Respuesta

1

Creo que el código se debe agregar a la forma de usuario, no al botón en sí.

así que algo como

With UserForm1.CodeModule 
    'Insert code here 
End With 

En lugar de su With ThisWorkbook

3

Prueba esto:

Sub AddButtonAndShow() 

    Dim Butn As CommandButton 
    Dim Line As Long 
    Dim objForm As Object 

    Set objForm = ThisWorkbook.VBProject.VBComponents("UserForm1") 

    Set Butn = objForm.Designer.Controls.Add("Forms.CommandButton.1") 
    With Butn 
     .Name = "CommandButton1" 
     .Caption = "Click me to get the Hello Message" 
     .Width = 100 
     .Top = 10 
    End With 

    With objForm.CodeModule 
     Line = .CountOfLines 
     .InsertLines Line + 1, "Sub CommandButton1_Click()" 
     .InsertLines Line + 2, "MsgBox ""Hello!""" 
     .InsertLines Line + 3, "End Sub" 
    End With 

    VBA.UserForms.Add(objForm.Name).Show 

End Sub 

Esto modifica permanentemente UserForm1 (suponiendo que guarda el libro). Si desea una forma de usuario temporal, agregue una nueva forma de usuario en lugar de configurarla en UserForm1. A continuación, puede eliminar el formulario una vez que haya terminado con él.

Chip Pearson tiene mucha información acerca de cómo codificar el VBE.

15

El código para agregar un botón en tiempo de ejecución y luego agregar eventos es realmente tan simple como difícil de descubrir ... Puedo decirlo porque he pasado más tiempo en esta perplejidad y me irrité más que en cualquier otra cosa que he programado ..

Crear un formulario de usuario y poner en el siguiente código:

Option Explicit 


Dim ButArray() As New Class2 

Private Sub UserForm_Initialize() 
    Dim ctlbut As MSForms.CommandButton 

    Dim butTop As Long, i As Long 

    '~~> Decide on the .Top for the 1st TextBox 
    butTop = 30 

    For i = 1 To 10 
     Set ctlbut = Me.Controls.Add("Forms.CommandButton.1", "butTest" & i) 

     '~~> Define the TextBox .Top and the .Left property here 
     ctlbut.Top = butTop: ctlbut.Left = 50 
     ctlbut.Caption = Cells(i, 7).Value 
     '~~> Increment the .Top for the next TextBox 
     butTop = butTop + 20 

     ReDim Preserve ButArray(1 To i) 
     Set ButArray(i).butEvents = ctlbut 
    Next 
End Sub 

Ahora U necesidad de añadir un módulo de clase a su código para la project..Please recordar su módulo de clase no Módulo. Y poner en siguiente código simple (en mi caso, el nombre de clase i s Clase 2) -


Public WithEvents butEvents As MSForms.CommandButton 

Private Sub butEvents_click() 

    MsgBox "Hi Shrey" 

End Sub 

Eso es todo. Ahora ejecútelo

+0

¡Gran respuesta! ¡Modificó fácilmente su ejemplo para otros tipos de formularios! – elektrykalAJ

+0

Parece que no puedo hacer que 'Me.Controls.Add (...)' funcione en Access 2010 Professional con un archivo .mdb. Puedo agregar la 'Biblioteca de objetos de Microsoft Forms 2.0', pero no hay un método 'Agregar' para un objeto de Controles (o Control o Formulario) del formulario 'Objeto de clase de Microsoft Access' en Acc2010, que está vinculado al 'Me 'objeto. Creo que tengo que hacer un 'CreateControl' en su lugar, pero todavía estoy luchando con los detalles. – mpag

4

DaveShaw, thx para este código hombre!

Lo he usado para una matriz de togglebutton (coloque una imagen en miniatura como trainer.jpg en la misma carpeta que el archivo de Excel para un togglebutton con una imagen).En el caso de 'clic' que ha invocado también está disponible (por el nombre del objeto como una cadena)

en la forma:

Dim CreateTrainerToggleButtonArray() As New ToggleButtonClass 

Private Sub CreateTrainerToggleButton(top As Integer, id As Integer) 

Dim pathToPicture As String 
pathToPicture = ThisWorkbook.Path & "\trainer.jpg" 
Dim idString As String 
idString = "TrainerToggleButton" & id 

Dim cCont As MSForms.ToggleButton 
Set cCont = Me.Controls.Add _ 
    ("Forms.ToggleButton.1") 

With cCont 
    .Name = idString 
    .Width = 20 
    .Height = 20 
    .Left = 6 
    .top = top 
    .picture = LoadPicture(pathToPicture) 
    End With 

    ReDim Preserve CreateTrainerToggleButtonArray(1 To id) 
    Set CreateTrainerToggleButtonArray(id).ToggleButtonEvents = cCont 
    CreateTrainerToggleButtonArray(id).ObjectName = idString 

    End Sub 

y una clase "ToggleButtonClass"

Public WithEvents ToggleButtonEvents As MSForms.ToggleButton 
    Public ObjectName As String 


    Private Sub ToggleButtonEvents_click() 
    MsgBox "DaveShaw is the man... <3 from your friend: " & ObjectName 
    End Sub 

Ahora solo simple llamada de UserForm_Initialize

Private Sub UserForm_Initialize() 
    Dim index As Integer 
    For index = 1 To 10 
    Call CreateTrainerToggleButton(100 + (25 * index), index) 
    Next index 
End Sub 
2

Esta fue mi solución para agregar un botón de comando y código wi sn uso de clases Se añade una referencia a permitir el acceso a VBIDE Agrega el botón

escribe entonces una función para controlar el evento clic en la hoja de

Sub AddButton() 
Call addref 
Set rng = DestSh.Range("B" & x + 3) 
'Set btn = DestSh.Buttons.Add(rng.Left, rng.Top, rng.Width, rng.Height) 
Set myButton = ActiveSheet.OLEObjects.Add(ClassType:="Forms.CommandButton.1", Left:=rng.Left, Top:=rng.Top, Height:=rng.Height * 3, Width:=rng.Width * 3) 
DoEvents 
With myButton 
    '.Placement = XlPlacement.xlFreeFloating 
    .Object.Caption = "Export" 
    .Name = "BtnExport" 

    .Object.PicturePosition = 1 
    .Object.Font.Size = 14 
    End With 
    Stop 
    myButton.Object.Picture = LoadPicture("F:\Finalised reports\Templates\Macros\evolution48.bmp") 

Call CreateButtonEvent 

End Sub 

Sub addref() 
On Error Resume Next 
Application.VBE.ActiveVBProject.References.AddFromFile "C:\Program Files (x86)\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.OLB" 
Application.VBE.ActiveVBProject.References.AddFromFile "C:\Program Files\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.OLB" 

End Sub 


    Private Sub CreateButtonEvent() 
On Error GoTo errtrap 

    Dim oXl As Application: Set oXl = Application 
    oXl.EnableEvents = False 
    oXl.DisplayAlerts = False 
    oXl.ScreenUpdating = False 
    oXl.VBE.MainWindow.Visible = False 

    Dim oWs As Worksheet 
    Dim oVBproj As VBIDE.VBProject 
    Dim oVBcomp As VBIDE.VBComponent 
    Dim oVBmod As VBIDE.CodeModule ' 
    Dim lLine As Single 
    Const QUOTE As String = """" 

    Set oWs = Sheets("Contingency") 
    Set oVBproj = ThisWorkbook.VBProject 
    Set oVBcomp = oVBproj.VBComponents(oWs.CodeName) 
    Set oVBmod = oVBcomp.CodeModule 

    With oVBmod 
     lLine = .CreateEventProc("Click", "BtnExport") + 1 
     .InsertLines lLine, "Call CSVFile" 
    End With 

    oXl.EnableEvents = True 
    oXl.DisplayAlerts = True 
Exit Sub 
errtrap: 


End Sub 
Cuestiones relacionadas