动态创建的用户表单,带有 2 个相关的组合框

Dynamic created User-Form, with 2 dependent Combo-Boxes

我正在尝试创建动态 User_form,其中所有 Controls 都是在 运行 时间创建的。

我有 2 个组合框数组,第一个组合框数组是 "Catgeory" (CatCBArr) ,第二个组合框数组是 "Item" (ItemCBArr).

我想,一旦我 select 来自 "Category" 的第一个组合框的值,假设 CatCBArr(0),只有 ItemCBArr(0) 中的相关项目将显示。

问题:我不知道如何根据 selected 中的值修改第二个组合框 (ItemCBArr(0))第一个组合框 (CatCBArr(0))

User_Form代码(相关部分)

Option Explicit

Dim ItemsNumofRows As Long    
Dim QtyTB As MSForms.TextBox
Dim CatCB As MSForms.ComboBox
Dim ItemCB As MSForms.ComboBox

Dim Key As Variant

' dynamic Form controls (related to new Classes)
Dim CatCBArr()                     As New cComboBox
Dim ItemCBArr()                    As New cComboBox    
Dim QtyTBArr()                     As New cTextBox         

Private Sub UserForm_Initialize()

' reset flags
ItemsNumofRows = 5
TasksNamesUpd = False
TasksColUpd = False

ItemsRows_ControlsInit '<-- upload all Controls at run-time
Check_FormHeight

End Sub

'======================================================

Private Sub ItemsRows_ControlsInit()

For ItemRow = 0 To ItemsNumofRows

    ' add Category Combo-boxes
    Set CatCB = Me.Controls.Add("Forms.ComboBox.1", "Cb" & ItemRow, True)
    With CatCB
        ' loop through Dictionay items (view category)
        For Each Key In Dict.Keys
            .AddItem Key
        Next Key

        .SpecialEffect = fmSpecialEffectSunken
        .Left = 40
        .Width = 100
        .Height = 18
        .Top = 54 + 20 * ItemRow

        ReDim Preserve CatCBArr(0 To ItemRow)
        Set CatCBArr(ItemRow).ComboBoxEvents = CatCB
    End With

    ' add Item Combo-boxes
    Set ItemCB = Me.Controls.Add("Forms.ComboBox.1", "Cb_" & ItemRow, True)
    With ItemCB

        .SpecialEffect = fmSpecialEffectSunken
        .Left = 160
        .Width = 100
        .Height = 18
        .Top = 54 + 20 * ItemRow

        ReDim Preserve ItemCBArr(0 To ItemRow)
        Set ItemCBArr(ItemRow).ComboBoxEvents = ItemCB
    End With    
Next ItemRow

End Sub

cComboBox Class代码

Public WithEvents ComboBoxEvents As MSForms.ComboBox

Private Sub ComboBoxEvents_Change()

Dim CBIndex                            As Long

' get for ID number (row number), from third character in String Name.
' e.g "Cb1" will result 1)
CBIndex = CInt(Mid(ComboBoxEvents.Name, 3))

' ??? How do I get the Value, and update the second combo-box Items

Select Case ComboBoxEvents.Value


End Select

End Sub

GUI User_Form 屏幕截图

好的,这是基础知识。 你的classcCombobox我复制如下:

Private WithEvents ComboBoxEvents As MsForms.ComboBox
Private Sub ComboBoxEvents_Change()
    Select Case ComboBoxEvents.value
        Case "1":
            UserForm1.DependentBox.Clear
            UserForm1.DependentBox.AddItem "3"
            UserForm1.DependentBox.AddItem "4"
        Case "2":
            UserForm1.DependentBox.Clear
            UserForm1.DependentBox.AddItem "5"
            UserForm1.DependentBox.AddItem "6"
        Case Default:
            'Do Nothing
    End Select
End Sub
Public Property Let box(value As MsForms.ComboBox)
    Set ComboBoxEvents = value
End Property
Public Property Get box() As MsForms.ComboBox
    Set box = ComboBoxEvents
End Property

接下来,我创建了一个 UserForm1,它添加了 2 个组合框,我将其中一个添加到 cComboBox 类型的局部变量中。

Public DependentBox As MsForms.ComboBox
Private InitialBox As cComboBox
Private Sub UserForm_Initialize()
    Dim cBox As MsForms.ComboBox
    Set InitialBox = New cComboBox

    Set cBox = Me.Controls.Add("Forms.ComboBox.1", "initial", True)
    With cBox
        .Left = 6
        .Width = 100
        .Height = 25
        .Top = 6
        .AddItem "1"
        .AddItem "2"
    End With
    InitialBox.box = cBox

    Set DependentBox = Me.Controls.Add("Forms.ComboBox.1", "dependent", True)
    With DependentBox
        .Top = 6
        .Left = 126
        .Height = 25
        .Width = 100
    End With
End Sub

尽管这可行,但上述方法不是很干净,因为您的 class 不是独立的 - 它必须了解用户窗体。更好的方法是 link class 中的框,然后在初始化控件数组时从用户窗体传递它们。 那么它将是:

cComboBox class:

Private WithEvents p_ComboBoxEvents As MSForms.ComboBox
Private p_DependBox As MSForms.ComboBox
Private Sub p_ComboBoxEvents_Change()
    Select Case p_ComboBoxEvents.value
        Case "1":
            p_DependBox.Clear
            p_DependBox.AddItem "3"
            p_DependBox.AddItem "4"
        Case "2":
            p_DependBox.Clear
            p_DependBox.AddItem "5"
            p_DependBox.AddItem "6"
        Case Default:
            'Do Nothing
    End Select
End Sub
Public Property Let TriggerBox(value As MSForms.ComboBox)
    Set p_ComboBoxEvents = value
End Property
Public Property Get TriggerBox() As MSForms.ComboBox
    Set TriggerBox = p_ComboBoxEvents
End Property
Public Property Let DependBox(value As MSForms.ComboBox)
    Set p_DependBox = value
End Property
Public Property Get DependBox() As MSForms.ComboBox
    Set DependBox = p_DependBox
End Property

在这里您已经看到 link 独立 class 中的盒子。 在事件处理程序中,您可以为值等创建查找。 然后在 UserForm1 代码中将它们初始化如下:

Option Explicit
Private LinkedComboBox As cComboBox
Private Sub UserForm_Initialize()
    Dim cBox As MSForms.ComboBox
    Set LinkedComboBox = New cComboBox

    Set cBox = Me.Controls.Add("Forms.ComboBox.1", "initial", True)
    With cBox
        .Left = 6
        .Width = 100
        .Height = 25
        .Top = 6
        .AddItem "1"
        .AddItem "2"
    End With
    LinkedComboBox.TriggerBox = cBox

    Set cBox = Me.Controls.Add("Forms.ComboBox.1", "dependent", True)
    With cBox
        .Top = 6
        .Left = 126
        .Height = 25
        .Width = 100
    End With
    LinkedComboBox.DependBox = cBox
End Sub

编辑: 基于需要是数组,可以修改userform如下:

Option Explicit
Private LinkedComboBox(0 To 4) As cComboBOx
Private Sub UserForm_Initialize()
    Dim cBox As MSForms.ComboBox
    Dim i As Integer

    For i = 0 To 4
        Set LinkedComboBox(i) = New cComboBOx
        Set cBox = Me.Controls.Add("Forms.ComboBox.1", "initial", True)
        With cBox
            .Left = 6
            .Width = 100
            .Height = 25
            .Top = 6 + (i * 25)
            .AddItem "1"
            .AddItem "2"
        End With
        LinkedComboBox(i).TriggerBox = cBox

        Set cBox = Me.Controls.Add("Forms.ComboBox.1", "dependent", True)
        With cBox
            .Top = 6 + (i * 25)
            .Left = 126
            .Height = 25
            .Width = 100
        End With
        LinkedComboBox(i).DependBox = cBox
    Next i

End Sub

在数组中,您可以通过 LinkedComboBox(i).DependBoxLinkedComboBox(i).TriggerBox 访问每个框。您将不再需要这两个单独的数组,因为所有内容都已包含在这个 LinkedComboBox 数组