【问题标题】:Dynamic created User-Form, with 2 dependent Combo-Boxes动态创建的用户表单,带有 2 个相关的组合框
【发布时间】:2017-06-07 20:08:25
【问题描述】:

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

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

我希望,一旦我从“Category”的第一个 Combo-Box 中选择了一个值,比如CatCBArr(0),那么只会显示ItemCBArr(0) 中的相关项目。

问题:我不知道如何根据第一个 Combo-box (CatCBArr(0)) 中选择的值来修改第二个 Combo-box (ItemCBArr(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 类代码

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屏幕截图

【问题讨论】:

  • ComboBoxEvents.Value 返回值。您可以对该值进行选择案例,然后使用第二个组合框 .addItem 方法添加您需要的项目。要清除正手第二个中的项目,请使用.clear
  • 啊,我看到您还在用户表单中使用Dim 声明了组合框。使用 Public 代替第二个数组(Dim 的行为与私有相同)在这种情况下,您可以通过 User_form.ItemCBArr(0) 从您的班级访问组合框

标签: vba excel class userform


【解决方案1】:

好的,基本情况就讲到这里。 你的类 cCombobox 我复制如下:

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

即使这样可行,上述方法也不是很干净,因为你的类不是独立的——它必须知道用户窗体。更好的方法是已经链接类中的框,然后在初始化控件数组时从 Userform 传递它们。 那么它会是:

cComboBox 类:

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

在这里,您看到您已经在一个独立的类中链接了这些框。 在事件处理程序中,您可以创建值查找等。 然后在 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 数组中

【讨论】:

  • 非常感谢您的回答,效果很好。你如何使它适用于每种类型的组合框数组?我有 5 个TriggerBox 和 5 个DependBox(最后会是动态的)
  • 添加这个自定义类的数组,并将两个框的索引0分别传递给自定义类数组中的索引0等
  • 我试过了,但不能让它工作,你能把那个部分添加到你的第二种代码方法中吗?
  • 查看更新。当然,您仍然必须想办法为每个依赖框设置值。您可以给类一个 Lookup range 属性或其他东西,然后用于根据 TriggerBox 的值填充 DependBox。但是 - 这是另一个问题。
  • 这是另一个问题,我稍后再给它一个托盘。同时,非常感谢您的所有帮助:)
猜你喜欢
  • 2017-06-16
  • 1970-01-01
  • 1970-01-01
  • 2018-04-13
  • 1970-01-01
  • 1970-01-01
  • 2018-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多