【问题标题】:ComboBox(number)_Change from generated ComboBoxes in VBComboBox(number) 从 VB 中生成的 ComboBox 改变
【发布时间】:2018-12-11 01:45:18
【问题描述】:

下面的代码是我遇到的一些问题。我很喜欢在 VB 中使用用户窗体。

我的目标是从“供应商投标”表中的供应商列创建 3 个组合框绘图数据和 3 个列表框来选择供应商的产品。

For j = 1 To 3

    Set myCombo = Frame1.Controls.Add("Forms.ComboBox.1", "ComboBox" & j)
    Set myList = Frame1.Controls.Add("Forms.ListBox.1", "ListBox" & j)

    With myList
        .Top = 18 + (150 - 84) * (j - 1)
        .Height = 34.85
        .Left = 198
        .Width = 180
        MsgBox .Name
    End With

    With myCombo
        .Top = 18 + (150 - 84) * (j - 1)
        .Height = 22.8
        .Left = 42
        .Width = 132
    End With

    Set rData = ThisWorkbook.Worksheets("VendorBids").Range("A:A").CurrentRegion
    Me.Controls("ComboBox" & j).List = rData.Offset(1).Value
    Me.Controls("ListBox" & j).ColumnCount = 1
    Me.Controls("ListBox" & j).List = rData.Offset(1, 1).Value



Next

这部分工作得很好。我有这个编码而不是在用户窗体中进行编码的原因是因为我有一个功能可以在用户按下命令按钮时添加另一行组合框和列表框。它也可以完美运行。

我遇到的问题是 ComboBox_Change()。如果我在用户窗体 GUI 编辑器中创建组合框,则 ComboBox1_Change() 将起作用。下面是一个我想要实现的示例,但包含所有生成的组合框,如 ComboBox2、3 等...

Private Sub ComboBox1_Change()

Me.ListBox1.ListIndex = Me.ComboBox1.ListIndex

End Sub

如果我的逻辑或解释不是很清楚,我深表歉意 - 这是我作为新手正在努力改进的内容。

【问题讨论】:

标签: vba excel combobox listbox


【解决方案1】:

参考:Chip Pearson - Events And Event Procedures In VBA

您将需要WithEventsRaiseEvents 的组合来处理新控件的事件。

ComboBoxHandler:类

存储对单个 Combobox 的引用。使用 WithEvents 它会在 ComboBox_Change() 时通知 ControlHandlerCollection

Option Explicit
Public ControlHandlerCollection As VBAProject.ControlHandlerCollection
Public WithEvents ComboBox As MSForms.ComboBox

Private Sub ComboBox_Change()
    ControlHandlerCollection.ComboBoxChanged ComboBox
End Sub

ListBoxHandler:类

存储对单个 ListBox 的引用。使用 WithEvents 它会在 ListBox_Change() 时通知 ControlHandlerCollection

Option Explicit
Public ControlHandlerCollection As VBAProject.ControlHandlerCollection
Public WithEvents ListBox As MSForms.ListBox

Private Sub ListBox_Change()
    ControlHandlerCollection.ListBoxChanged ListBox
End Sub

ControlHandlerCollection:类

每当处理程序类中的一个通知它发生更改时,它就会引发一个事件以通知用户窗体更改。

Private EventHandlers As New Collection

Public Event ComboBoxChange(ComboBox As MSForms.ComboBox)
Public Event ListBoxChange(ListBox As MSForms.ListBox)

Public Sub AddComboBox(ComboBox As MSForms.ComboBox)
    Dim ComboBoxHandler As New ComboBoxHandler
    Set ComboBoxHandler.ControlHandlerCollection = Me
    Set ComboBoxHandler.ComboBox = ComboBox
    EventHandlers.Add ComboBoxHandler
End Sub

Public Sub AddListBox(ListBox As MSForms.ListBox)
    Dim ListBoxHandler As New ListBoxHandler
    Set ListBoxHandler.ControlHandlerCollection = Me
    Set ListBoxHandler.ListBox = ListBox
    EventHandlers.Add ListBoxHandler
End Sub

Public Sub ComboBoxChanged(ComboBox As MSForms.ComboBox)
    RaiseEvent ComboBoxChange(ComboBox)
End Sub

Public Sub ListBoxChanged(ListBox As MSForms.ListBox)
     RaiseEvent ListBoxChange(ListBox)
End Sub

用户表单1:用户表单

Option Explicit
Private WithEvents ControlHandlerCollection As ControlHandlerCollection

Private Sub ControlHandlerCollection_ComboBoxChange(ComboBox As MSForms.ComboBox)
    MsgBox "Value: " & ComboBox.Value & vbNewLine & _
           "Name: " & ComboBox.Name & vbNewLine & _
           "Tag: " & ComboBox.Tag
End Sub

Private Sub ControlHandlerCollection_ListBoxChange(ListBox As MSForms.ListBox)
    MsgBox "Value: " & ListBox.Value & vbNewLine & _
           "Name: " & ListBox.Name & vbNewLine & _
           "Tag: " & ListBox.Tag
End Sub

Private Sub UserForm_Initialize()
    Set ControlHandlerCollection = New ControlHandlerCollection
End Sub

Private Sub btnAddRow_Click()
    Dim j As Long
    Dim rData As Range
    Dim myCombo As MSForms.ComboBox, myList As MSForms.ListBox
    Set rData = ThisWorkbook.Worksheets("VendorBids").Range("A:A").CurrentRegion

    For j = 1 To 3

        Set myCombo = Frame1.Controls.Add("Forms.ComboBox.1", "ComboBox" & j)
        Set myList = Frame1.Controls.Add("Forms.ListBox.1", "ListBox" & j)

        With myList
            .Top = 18 + (150 - 84) * (j - 1)
            .Height = 34.85
            .Left = 198
            .Width = 180
            .ColumnCount = 1
            .List = rData.Offset(1, 1).Value
            .Tag = rData.Offset(1, 1).Address
        End With

        With myCombo
            .Top = 18 + (150 - 84) * (j - 1)
            .Height = 22.8
            .Left = 42
            .Width = 132
            .List = rData.Offset(1).Value
            .Tag = rData.Offset(1).Address
        End With

        ControlHandlerCollection.AddComboBox myCombo
        ControlHandlerCollection.AddListBox myList
    Next
End Sub

【讨论】:

  • 谢谢!到目前为止,它的工作率为 100%。您是否介意解释更多或指向一些资源以了解有关 WithEvents、RaiseEvents 以及集合如何工作的更多信息?非常感谢您的帮助。
  • 用于存储对控制处理程序的引用的集合。如果没有收集,VBA 垃圾收集器将在子例程结束时清理控制处理程序。
  • WithEvents 将类与通过 Com 公开的控件事件挂钩。您还可以创建自己的类事件,该事件将通知任何使用WithEvents 监视您的类事件的类或用户表单。
  • 好的,所以 ComboBox_Change() 非常适合我。现在得到它我想要它做的事情。它具有已更改的 ComboBox 的所有数据,特别是名称。名称是 myCombo(number)。它没有任何关于哪个列表框与之相关的信息。因此,为了使其动态化,我想我会 1. 解析 myCombo(number) 的名称以仅获取数字。 2. 构建一个名为 (myList + number) 的变量,其中的数字是从 myCombo 名称中解析出来的。 3.设置新变量myList(number).ListIndex = ComboBox.ListIndex 有没有更高效或者更简洁的方式来实现呢?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多