2017-06-07 2 views
-1

J'essaie de créer un User_form dynamique, où tous les Controls sont créés au moment de l'exécution.Formulaire utilisateur créé dynamique, avec 2 zones de liste déroulante dépendantes

J'ai 2 tableaux de Combo-Boxes, le premier tableau de Combo-Boxes est "Catgeory" (CatCBArr), et le deuxième tableau de Combo-Boxes est "Item" (ItemCBArr).

Je veux, qu'une fois que je sélectionne une valeur de la première zone de liste déroulante de "Catégorie", disons CatCBArr(0), que seuls les éléments liés dans ItemCBArr(0) seront affichés.

émission: je ne peux pas comprendre comment modifier la deuxième liste déroulante (ItemCBArr(0)) en fonction de la valeur sélectionnée dans la première liste déroulante (CatCBArr(0))

User_Form code (section pertinente)

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 

de CComboBox classe 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 

Capture d'écran-GUI User_Form

enter image description here

+0

'ComboBoxEvents.Value' renvoie la valeur. Vous pouvez faire un cas de sélection sur cette valeur et ensuite utiliser la deuxième méthode de liste déroulante '.addItem' pour ajouter les éléments dont vous avez besoin. Pour effacer les éléments dans le second coup droit, utilisez '.clear' –

+0

Ah, je vois que vous déclarez également les comboboxes dans le userform avec' Dim'. Utilisez 'Public' à la place pour le second tableau (Dim se comporte comme privé) Dans ce cas, vous pouvez accéder aux comboboxes de votre classe via' User_form.ItemCBArr (0) ' –

Répondre

1

D'accord, voici les bases. Votre classe CComboBox Je répliquée comme suit:

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 

Ensuite, j'ai créé un UserForm1 qui ajoute 2 comboboxes, l'un dont j'ajouter à une variable locale de type 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 

Même si cela fonctionne, l'approche ci-dessus n'est pas très propre, puisque votre classe n'est pas autonome - Il doit être au courant de l'UserForm. Une meilleure façon serait de lier les boîtes dans la classe déjà, puis de les passer du Userform lorsque vous initialisez vos tableaux de contrôles. Ensuite, il serait:

CComboBox Classe:

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 

Vous voyez ici vous liez déjà les boîtes dans une classe autonome. Dans le gestionnaire d'événements, vous pouvez créer une recherche pour les valeurs, etc. Puis dans le code UserForm1 vous les initialize comme suit:

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: Basé sur le fait qu'il doit être un tableau, vous pouvez modifier le userform comme suit:

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 

Dans le tableau, vous pouvez accéder à chaque boîte en tant que LinkedComboBox(i).DependBox et LinkedComboBox(i).TriggerBox. Vous n'aurez plus besoin des deux tableaux séparés, puisque tout est déjà contenu dans ce tableau LinkedComboBox

+0

Merci beaucoup pour la réponse, cela fonctionne bien. Comment le faites-vous fonctionner pour un tableau de combos de chaque type? J'ai 5 'TriggerBox' et 5' DependBox' (il sera dynamique à la fin) –

+0

Ajouter un tableau de cette classe personnalisée et passer l'index 0 pour chacune des deux boîtes à l'index 0 dans le tableau de classe personnalisée, etc. –

+0

J'ai essayé, mais je n'ai pas pu le faire fonctionner, pouvez-vous simplement ajouter cette section à votre deuxième approche de code? –