三个级联组合框

时间:2018-10-24 03:21:10

标签: vba combobox userform

我要在comboboxes中将相对大量的数据转换为三个excel userform。基本上,我正在尝试为建筑产品创建采购订单系统。这涉及三个组合框,基本上分为“类别”,“子类别”和“产品”。

我发现一些使用.offset函数的代码,但是我发现使用此函数的唯一方法非常耗时。我是VBA的新手。

有没有一种方法可以使用此代码或其他代码对我的数据进行有效排序,而不是每次手动更改偏移量?

Private Sub UserForm_Initialize()

Dim ws As Worksheet
Dim LR As Long
Dim Cell As Range
Dim List As New Collection
Dim Item As Variant
Set ws = ActiveSheet

With ws
LR = Sheet1.Cells(.Rows.Count, 1).End(xlUp).Row
For Each Cell In .Range("A2:A" & LR)
    With Cell
        On Error Resume Next
        List.Add .Text, CStr(.Value)
        On Error GoTo 0
    End With
Next Cell
For Each Item In List
    ComboBox1.AddItem Item
    Next Item
End With
End Sub

Private Sub ComboBox1_Change()

Dim ws As Worksheet
Dim LR As Long
Dim Cell As Range
Dim List As New Collection
Dim Item As Variant
Set ws = ActiveSheet


With ws
    LR = Sheet1.Cells(.Rows.Count, 1).End(xlUp).Row
    ComboBox2.Clear
    For Each Cell In .Range("A2:A" & LR)
        With Cell
            If .Text = ComboBox1.Value Then
                On Error Resume Next
                List.Add .Offset(0, 1).Text, CStr(.Offset(0, 1).Value)
                On Error GoTo 0
            End If
        End With
    Next Cell
    For Each Item In List
        ComboBox2.AddItem Item
    Next Item
End With


End Sub

Private Sub ComboBox2_Change()

Dim ws As Worksheet
Dim LR As Long
Dim Cell As Range
Dim List As New Collection
Dim Item As Variant
Set ws = ActiveSheet

With ws
    LR = Sheet1.Cells(.Rows.Count, 1).End(xlUp).Row
    ComboBox3.Clear
    For Each Cell In .Range("A2:A" & LR)
        With Cell
            If .Text = ComboBox1.Value Then
                If .Offset(0, 1).Text = ComboBox2.Value Then
                On Error Resume Next
                List.Add .Offset(0, 2).Text, CStr(.Offset(0, 2).Value)
                On Error GoTo 0
            End If
        End If
        End With
    Next Cell
    For Each Item In List
        ComboBox3.AddItem Item
    Next Item
End With

End Sub

任何帮助都会很棒!

1 个答案:

答案 0 :(得分:0)

使用数据字段数组加快速度

据我了解,您主要关心的是使用UserForm中的级联组合框和可读代码避免大量.Offset来提高速度。

[i。]遍历一个范围总是很费时间,将您的完整数据集分配给 variant 数据字段数组({{1 }})

[ii。]调用单个帮助程序 myData使fillComboNo事件过程更加易读。

[iii。]附加帮助程序_Change 进行分类以使选择用户友好

[iv。]此外,此示例代码还允许在其他SortColl事件过程中使用相同的帮助过程fillComboNo 添加 更多组合框 。 -当然,在这种情况下,也有必要扩展分配给数据字段数组Combobox{No}_Change的范围(即从3列myData扩展到A:C

示例代码

基本上,此解决方案与您的方法很接近,因为它也使用集合。它更快,因为它使用如上所述的数据字段数组; 它并不假装提供最有效的方式来显示级联组合框。

此示例假定列举了所有需要的组合框A:DComboBox1ComboBox2,...

ComboBox3

帮助程序Option Explicit ' declaration head of the UserForm code module Dim myData ' Variant 2-dim datafield array ( 1-based !) Private Sub UserForm_Initialize() Dim LR As Long, ws As Worksheet Set ws = Sheet1 ' if using CodeName in thisWorkbook ' ~~~~~~~~~~~~~~~~~~~~~~~~~ ' [0] get entire DATA FIELD ' e.g. columns A:C (omitting title row) ' ~~~~~~~~~~~~~~~~~~~~~~~~~ LR = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row ' get last row myData = ws.Range("A2:C" & LR).Value2 ' << assign range values to datafield array ' [1] fill first ComboBox FillComboNo 1 ' <~~ helper procedure FillComboNo End Sub Private Sub ComboBox1_Change() FillComboNo 2 ' <~~ helper procedure FillComboNo End Sub Private Sub ComboBox2_Change() FillComboNo 3 ' <~~ helper procedure FillComboNo End Sub

FillComboNo

排序例程Sub FillComboNo(ByVal no As Long) ' Purpose: fill cascading comboboxes ' Note: assumes controls named as "ComboBox" & No (ComboBox1, ComboBox2, ...) Dim myList As New Collection Dim item As Variant Dim i As Long, ii As Long Dim OK As Boolean, OKTemp As Boolean ' [0] clear ComboBox{No} Me.Controls("ComboBox" & no).Clear ' [1] assign values in column No based on prior hierarchy levels For i = LBound(myData) To UBound(myData) ' [1a] check upper hierarchy OK = True For ii = 1 To no - 1 OKTemp = myData(i, ii) = Me.Controls("ComboBox" & ii): OK = OK And OKTemp Next ii ' [1b] add to collection If OK Then On Error Resume Next myList.Add myData(i, no), myData(i, no) If Err.Number <> 0 Then Err.Clear End If Next i ' [1c] sort collection via helper procedure SortColl myList ' <~~ helper procedure SortColl ' [2] fill ComboBox{No} For Each item In myList Me.Controls("ComboBox" & no).AddItem item Next item End Sub

SortColl