【问题标题】:Actions for multiple similar dynamically created command buttons多个类似的动态创建的命令按钮的操作
【发布时间】:2014-08-24 20:14:59
【问题描述】:

我正在用 Excel VBA 编写一个程序,它基本上从一个文本框和一个命令按钮开始,命令按钮将在其下方创建一个新的文本框和命令按钮,而该命令按钮将依次创建一个新的文本框和命令按钮等。希望你跟着那个烂摊子走。

我可以创建初始按钮没问题(它必须动态创建,以便以后有机会删除)。然后我的问题是创建click() 事件处理程序。我需要所有的click() 事件来做同样的事情,但是相对于它自己的名字来命名新的对象。这一切都让我大吃一惊,我真的很感谢你的帮助。

请随意询问具体信息,但我还没有真正能够很好地围绕这个主题编写一些测试代码。

【问题讨论】:

  • 这可能会有所帮助:Using WithEvents on UserForms
  • @z̫͋ 我对WithEvents很熟悉,但我不知道如何使用动态初始化(并以无法预料的方式命名)按钮的点击事件。例如,一个按钮的名称可能是"NewButton" & i,我不知道如何为此创建事件处理程序,即使使用WithEvents
  • 使用 WithEvents 按钮的名称无关紧要。您创建一个接收事件的变量并将按钮分配给该变量。按钮的名称与它没有任何关系。在我看来,最好创建您需要的所有控件并切换 .Visible 属性,而不是尝试在运行时创建控件。即使您这样做,您仍然可能需要一个通用程序。
  • @DickKusleika 你能告诉我一些在 标签中使用通用名称而不是细节的代码,以帮助我理解吗?我明白你对 WithEvents 的看法,只是不知道该怎么做。

标签: vba excel dynamic commandbutton


【解决方案1】:

创建一个名为 CEventClass 的自定义类模块(插入 - 类模块,F4 更改名称)。将此代码输入到类模块中

'These are declared WithEvents so the events are
'exposed to us
Public WithEvents cmdEvent As MSForms.CommandButton
Public WithEvents tbxEvent As MSForms.TextBox


'This will fire for any control
'assigned to cmdEvent
Private Sub cmdEvent_Click()

    MsgBox cmdEvent.Caption

End Sub

'This will fire for any control
'assigned to tbxEvent
Private Sub tbxEvent_Change()

    If Len(tbxEvent.Text) < 6 Then
        tbxEvent.BackColor = vbYellow
    Else
        tbxEvent.BackColor = vbWhite
    End If

End Sub

现在创建一个没有控件的用户窗体。将此代码放入表单的代码模块中

'These will keep the class instances in
'scope for as long as the form is loaded
Private mEventButtons As Collection
Private mEventTexts As Collection

Private Sub UserForm_Initialize()

    Dim cmd As MSForms.CommandButton
    Dim txt As MSForms.TextBox
    Dim clsEventClass As CEventClass

    Set mEventButtons = New Collection
    Set mEventTexts = New Collection

    'Create two commandbuttons
    Set cmd = Me.Controls.Add("Forms.CommandButton.1", "FirstName")
    cmd.Top = 10
    cmd.Left = 10
    cmd.Caption = "First"
    'Create a new instance of CEventClass and
    'assign the button to cmdEvent
    Set clsEventClass = New CEventClass
    Set clsEventClass.cmdEvent = cmd
    mEventButtons.Add clsEventClass

    Set cmd = Me.Controls.Add("Forms.CommandButton.1", "SecondName")
    cmd.Top = 50
    cmd.Left = 10
    cmd.Caption = "Second"
    Set clsEventClass = New CEventClass
    Set clsEventClass.cmdEvent = cmd
    mEventButtons.Add clsEventClass

    'Create two textboxes and assign them to new instances
    'of the class
    Set txt = Me.Controls.Add("Forms.TextBox.1", "ThirdName")
    txt.Top = 10
    txt.Left = 150
    Set clsEventClass = New CEventClass
    Set clsEventClass.tbxEvent = txt
    mEventTexts.Add clsEventClass

    Set txt = Me.Controls.Add("Forms.TextBox.1", "FourthName")
    txt.Top = 50
    txt.Left = 150
    Set clsEventClass = New CEventClass
    Set clsEventClass.tbxEvent = txt
    mEventTexts.Add clsEventClass

End Sub

现在,当您运行表单时,如果您单击/更改控件,这两个事件将触发。

您可能会注意到文本框没有更新后事件。该事件实际上不是文本框事件,而是文本框的控件容器的事件,因此您不能以这种方式公开它。这就是我更喜欢在设计时创建所有控件并根据需要隐藏或取消隐藏它们的原因之一。我仍然可以将 WithEvents 用于某些控件,这样我就不必过多地重复代码。但是对于像 TextBox_AfterUpdate 这样的东西,我只是在设计时创建了所有的事件过程。

更新:

如果您希望事件创建新按钮,您必须做更多的事情。首先,您必须在用户窗体之外公开集合。你把它添加到你的用户表单模块中

Public Property Get EventButtons() As Collection
    Set EventButtons = mEventButtons
End Property

然后你改变你的命令按钮事件代码来创建一个新按钮

Private Sub cmdEvent_Click()

    Dim cmd As MSForms.CommandButton
    Dim clsEventClass As CEventClass

    Set cmd = cmdEvent.Parent.Controls.Add("Forms.CommandButton.1", cmdEvent.Caption & "1")
    cmd.Top = cmdEvent.Top + 40
    cmd.Left = cmdEvent.Left
    cmd.Caption = cmdEvent.Caption & "1"
    Set clsEventClass = New CEventClass
    Set clsEventClass.cmdEvent = cmd
    cmdEvent.Parent.EventButtons.Add clsEventClass

End Sub

这将创建一个新按钮,该按钮位于被单击的位置下方 40 点处。你没有说你的命名或定位逻辑是什么,所以我假设你可以解决这个问题。使用 cmdEvent.Parent 获取对 Userform 的引用。

【讨论】:

  • 这有可能做我想做的事,但我需要点击按钮在用户窗体上创建一个新按钮,点击时将创建另一个按钮,用户想要多少次。
  • 非常好,正是我需要的。谢谢
  • 好的,当我尝试在您放入更新的创建过程中包含一个文本框时,我收到了一个运行时错误 91。这是罪魁祸首:Set tbx = tbxEvent.Parent.Controls.Add("Forms.TextBox.1") 为什么这不起作用?跨度>
  • 您是否将其放入 cmdEvent_Click() 中?那么它应该是Set tbx = cmdEvent.Parent.Controls...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-03
  • 2013-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-28
相关资源
最近更新 更多