【问题标题】:Assign code to a button created dynamically将代码分配给动态创建的按钮
【发布时间】:2012-04-30 18:10:14
【问题描述】:

我正在尝试获取我在 excel 用户窗体表单上动态创建的按钮,以运行名为 transfer 的宏,该宏是我在项目“模块”部分的 Module 1 中编写的。

下面我已经粘贴了我迄今为止在用户窗体中编写的代码,它实际上设法在框架中创建Transfer to Sheet 按钮(我也动态创建了)但是出于某种原因,当我运行 VBA 时,我收到一条 438 error 消息,上面写着 Object doesn't support this property or method

谁能告诉我如何解决这个问题?

代码如下:

Dim framecontrol1 As Control

Set workitemframe = Controls.Add("Forms.Frame.1")
With workitemframe
    .Width = 400
    .Height = 400
    .Top = 160
    .Left = 2
    .ZOrder (1)
    .Visible = True
End With

workitemframe.Caption = "Test"
Set framecontrol1 = workitemframe.Controls.Add("Forms.commandbutton.1")

With framecontrol1
    .Width = 100
    .Top = 70
    .Left = 10
    .ZOrder (1)
    .Visible = True
    .Caption = "Transfer to Sheet"
End With
framecontrol1.OnAction = "transfer"

【问题讨论】:

    标签: vba excel


    【解决方案1】:

    这是一个例子。请根据您的需要修改它:)

    此示例将创建一个命令按钮并为其分配代码,以便在按下它时显示“Hello World”。

    将此代码粘贴到命令按钮的单击事件中,这将动态创建一个新的命令按钮并为其分配代码。

    Option Explicit
    
    Dim cmdArray() As New Class1
    
    Private Sub CommandButton1_Click()
        Dim ctl_Command As Control
        Dim i As Long
    
        i = 1
    
        Set ctl_Command = Me.Controls.Add("Forms.CommandButton.1", "CmdXYZ" & i, False)
    
        With ctl_Command
            .Left = 100
            .Top = 100
            .Width = 255
            .Caption = "Click Me " & CStr(i)
            .Visible = True
        End With
    
        ReDim Preserve cmdArray(1 To i)
        Set cmdArray(i).CmdEvents = ctl_Command
    
        Set ctl_Command = Nothing
    
    End Sub
    

    并将此代码粘贴到类模块中

    Option Explicit
    
    Public WithEvents CmdEvents As MSForms.CommandButton
    
    Private Sub CmdEvents_Click()
    
        MsgBox "Hello Word"
    
    End Sub
    

    快照

    【讨论】:

    • +1 我不完全确定该按钮是要保留(我的代码)还是最终消失(此代码)。类模块是为新按钮提供代码的巧妙解决方法
    • 嗨 Siddharth,您的示例效果非常好,您解释它的方式也很棒,尤其是对于像我这样的 VBA 新手!如果不让你解释 cmdArray(i) 是什么,我不能让你走。部分在 ReDim Preserve cmdArray(1 To i) Set cmdArray(i).CmdEvents = ctl_Command
    • (哎呀...在我写完消息之前按回车键!)正如我所说,最好了解 cmdArray(i) 需要什么,因此您可以提供任何解释那会很棒。再次感谢您的帮助悉达多!
    • @TonyCatton: 不,不.. 让我走...... 只是开玩笑:) cmdArray(i) 创建一个命令按钮控件数组,然后为它们分配一个公共事件。 Redim 可用于重新调整数组的尺寸。当您不想破坏现有数组(包括元素中的所有现有数据)时,可以使用Preserve。如果您不使用“Preserve”,那么它会破坏现有数组和现有元素。 HTH
    • @SiddharthRout 您好,感谢您对这个问题的回答,我想问一下您将如何将参数传递给点击事件处理程序?
    【解决方案2】:

    您需要以编程方式将代码添加到用户窗体。我使用了来自 vbax article 的代码作为参考

    以下代码:

    1. 从普通模块运行
    2. 将按钮添加到名为 UserForm1 的用户窗体中
    3. 将此代码添加到单击事件的用户窗体中

      Private Sub CommandButton1_Click()
      Call Transfer
      End Sub
      

    来自普通模块的 VBA

        Sub AddToForm()
        Dim UF As Object
        Dim frameCOntrol1 As Object
        Set UF = ActiveWorkbook.VBProject.VBComponents("UserForm1")
        Set frameCOntrol1 = UF.designer.Controls.Add("Forms.CommandButton.1")
        With frameCOntrol1
            .Width = 100
            .Top = 70
            .Left = 10
            .ZOrder (1)
            .Visible = True
            .Caption = "Transfer to Sheet"
        End With
    
        With UF.CodeModule
            .InsertLines 2, _
                         "Private Sub " & frameCOntrol1.Name & "_Click()" & Chr(13) & _
                         "Call Transfer" & Chr(13) & _
                         "End Sub"
        End With
    
    End Sub
    

    【讨论】:

    • + 1 解决问题的另一种方法 :)
    • +1 我不同意这段代码的 VBAX 评级为“简单”。 (我还在第一句话中编辑了一个有点幽默的错字。)
    • + 1 @DougGlancy :) 我同意你的看法。对 VBE 进行编程或编写类模块绝不是“简单”编程 :) 但是我猜我可能是错的,它是在谈论“易用性”而不是代码的难度级别。对于新手来说,如果你把所有东西都放在盘子里,那么他/她的代码总是“容易”使用的,我想这就是那个页面所做的:)