2017-06-07 4 views
-1

Ich versuche ein dynamisches Benutzerformular zu erstellen, in dem alle Controls zur Laufzeit erstellt werden.Dynamisch erstelltes Benutzerformular mit 2 abhängigen Kombinationsfeldern

Ich habe 2 Array von Combo-Boxen, erste Reihe von Combo-Boxen ist "Catgeory" (CatCBArr), und die zweite Reihe von Combo-Boxen ist "Artikel" (ItemCBArr).

Ich mag, dass ich einmal einen Wert aus der ersten Combo-Box von „Kategorie“ wählen, lassen Sie sich CatCBArr(0) sagt, dass nur der entsprechende Artikel in ItemCBArr(0) angezeigt.

Ausgabe: Ich kann nicht herausfinden, wie die zweite Combo-Box zu modifizieren (ItemCBArr(0)) entsprechend den ausgewählten Wert in der ersten Combo-Box (CatCBArr(0))

User_Form-Code (entsprechender Abschnitt)

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 Code

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-screen shot

enter image description here

+0

'ComboBoxEvents.Value' gibt den Wert zurück. Sie können einen Auswahlfall für diesen Wert eingeben und dann die zweite Combobox '.addItem'-Methode verwenden, um die benötigten Elemente hinzuzufügen. Um die Elemente in der zweiten Vorhand zu löschen, verwenden Sie '.clear' –

+0

Ah ich sehe, dass Sie auch die Comboboxen im Benutzerformular mit' Dim' deklarieren. Verwenden Sie 'Public' stattdessen für das zweite Array (Dim verhält sich genauso wie private) In diesem Fall können Sie auf die Comboboxen von Ihrer Klasse über' User_form.ItemCBArr (0) ' –

Antwort

1

Okay, hier die Grundlagen. Ihre Klasse CComboBox ich wie folgt repliziert:

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 

Als nächstes habe ich eine UserForm1, die 2 Comboboxen fügt hinzu, von denen ich auf eine lokale Variable vom Typ CComboBox hinzuzufügen.

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 

Obwohl dies funktioniert, ist der obige Ansatz nicht sehr sauber, da die Klasse nicht in sich geschlossen ist - es hat sich bewusst von der Userform sein. Ein besserer Weg wäre, die Boxen in der Klasse bereits zu verknüpfen und sie dann einfach aus der Benutzermaske zu übergeben, wenn Sie Ihre Steuerfelder initialisieren. Dann wäre es:

CComboBox Klasse:

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 

Hier sehen Sie bereits die Boxen in einer in sich geschlossenen Klasse verknüpfen. In der Ereignisbehandlungsroutine könnten Sie eine Suche nach den Werten usw. erstellen. Dann in der UserForm1 Code Sie sie wie folgt initialisieren:

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 

EDIT: Basierend auf der Tatsache, dass es ein Array sein muss, können Sie die Userform wie folgt ändern:

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 

Im Array können Sie auf jede Box wie LinkedComboBox(i).DependBox und LinkedComboBox(i).TriggerBox zugreifen. Sie werden die zwei separaten Arrays nicht mehr brauchen, da alles bereits in diesem LinkedComboBox Array enthalten ist

+0

zugreifen Vielen Dank für die Antwort, es funktioniert gut. Wie funktioniert es für ein Array von Combo-Boxen für jeden Typ? Ich habe 5 'TriggerBox' und 5' DependBox' (es wird am Ende dynamisch sein) –

+0

Fügen Sie ein Array dieser benutzerdefinierten Klasse hinzu und übergeben Sie den Index 0 für jedes der zwei Felder an Index 0 im benutzerdefinierten Klassenarray usw. –

+0

Ich habe es versucht, konnte es aber nicht zum Laufen bringen. Kannst du diesen Abschnitt einfach zu deinem zweiten Code-Ansatz hinzufügen? –

Verwandte Themen