下面的代码是我遇到的一些问题。对于在VB中使用用户窗体,我非常满意。
我的目标是从“供应商出价”工作表的“供应商”栏中创建3个ComboBoxes绘图数据,并创建3个ListBoxes以选择供应商的产品。
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()。如果我在UserForm GUI编辑器中创建了组合框,则ComboBox1_Change()将起作用。下面是我尝试实现的示例,但包含所有生成的组合框,例如ComboBox2、3,等等。
Private Sub ComboBox1_Change()
Me.ListBox1.ListIndex = Me.ComboBox1.ListIndex
End Sub
如果我的逻辑或解释不太清楚,我深表歉意,这是我作为新手正在努力改进的方面。
答案 0 :(得分:1)
参考:Chip Pearson - Events And Event Procedures In VBA
您需要结合使用WithEvents
和RaiseEvents
来处理新控件的事件。
存储对单个组合框的引用。使用WithEvents可以在ControlHandlerCollection
时通知ComboBox_Change()
。
Option Explicit
Public ControlHandlerCollection As VBAProject.ControlHandlerCollection
Public WithEvents ComboBox As MSForms.ComboBox
Private Sub ComboBox_Change()
ControlHandlerCollection.ComboBoxChanged ComboBox
End Sub
存储对单个ListBox的引用。使用WithEvents可以在ControlHandlerCollection
时通知ListBox_Change()
。
Option Explicit
Public ControlHandlerCollection As VBAProject.ControlHandlerCollection
Public WithEvents ListBox As MSForms.ListBox
Private Sub ListBox_Change()
ControlHandlerCollection.ListBoxChanged ListBox
End Sub
每当处理程序类之一将更改通知给它时,它同时持有ComboBoxHandlers
和ListBoxHandlers
的集合,它引发一个事件以将更改通知用户表单。
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
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