Excel 填充多个组合框';s使VBA用户窗体变慢

Excel 填充多个组合框';s使VBA用户窗体变慢,excel,vba,combobox,multiple-columns,Excel,Vba,Combobox,Multiple Columns,目前,我正在用40个组合框制作一个用户表单,所有组合框都有相同的列表。我的问题是填充所有这些组合框会使userform.show变慢。在这些组合框中填充的列表是一个非常长的列表(46542行,列表长度可以不同),该列表有3列 我一直在胡闹着连接整个列表,但这并没有带来太大的变化。另外,因为我需要在combobox中选择值,以便与combobox中的所有3列连接,等等。当在combobox中选择第1行而不是只在comboxbox文本字段中写入第1列时,它将返回所有3列,这意味着我实际上有4列,其中

目前,我正在用40个组合框制作一个用户表单,所有组合框都有相同的列表。我的问题是填充所有这些组合框会使
userform.show
变慢。在这些组合框中填充的列表是一个非常长的列表(46542行,列表长度可以不同),该列表有3列

我一直在胡闹着连接整个列表,但这并没有带来太大的变化。另外,因为我需要在combobox中选择值,以便与combobox中的所有3列连接,等等。当在combobox中选择第1行而不是只在comboxbox文本字段中写入第1列时,它将返回所有3列,这意味着我实际上有4列,其中第一列连接并隐藏在下拉列表

所以我的问题是,有没有办法让这个过程更轻松

下面是代码:

Private Sub UserForm_Initialize()
Set tsheet = ThisWorkbook.Sheets("Players")
Dim v As Variant, i As Long
v = tsheet.Range("A2:l" & Worksheets("Players").Cells(Rows.Count, 
1).End(xlUp).Row).Value
With Me.ComboBox1
.RowSource = ""
.ColumnCount = 4
.BoundColumn = 2
.ColumnWidths = "1;50;50;50" 'Hide first column in dropdown
For i = LBound(v) To UBound(v)
.AddItem v(i, 1) & " " & v(i, 2) & " " & v(i, 3)
.List(.ListCount - 1, 1) = v(i, 1)
.List(.ListCount - 1, 2) = v(i, 2)
.List(.ListCount - 1, 3) = v(i, 3)
Next i
End With
With Me.ComboBox2
.RowSource = ""
.ColumnCount = 4
.BoundColumn = 2
.ColumnWidths = "1;50;50;50" 'Hide first column in dropdown
For i = LBound(v) To UBound(v)
.AddItem v(i, 1) & " " & v(i, 2) & " " & v(i, 3)
.List(.ListCount - 1, 1) = v(i, 1)
.List(.ListCount - 1, 2) = v(i, 2)
.List(.ListCount - 1, 3) = v(i, 3)
Next i
End With
此代码一直持续到它达到combox40

我的旧代码运行得非常快,但它没有连接的列

ComboBox3.ColumnWidths = "50;50;50"         'COLUMN WITH OF LISTBOX
ComboBox3.ColumnCount = 3                                                 
'COLUMN NUMBER OF LISTBOX
ComboBox3.List = tsheet.Range("A2:l" & 
Worksheets("Players").Cells(Rows.Count, 1).End(xlUp).Row).Value
而不是

ComboBox3.List = tsheet.Range("A2:l" & 
Worksheets("Players").Cells(Rows.Count, 1).End(xlUp).Row).Value
使用类似的方法(将Arr声明为变体):-

不要重复相同的代码40次,而是创建一个循环

For i = 1 to 40
    Cbx = Me.Controls("ComboBox" & Cstr(i))
    ' then manipulate Cbx as you have done.
Next I
最后,既然您的40个组合框都是一样的,为什么不只使用1个呢?您可以将其从一行移动到另一行,让用户进行选择,并将选择转移到一个文本框中,该文本框在退出时显示在Cbx的位置。当您再次单击Tbx时,它将被Cbx替换,以便您可以再次访问列表。

而不是

ComboBox3.List = tsheet.Range("A2:l" & 
Worksheets("Players").Cells(Rows.Count, 1).End(xlUp).Row).Value
使用类似的方法(将Arr声明为变体):-

不要重复相同的代码40次,而是创建一个循环

For i = 1 to 40
    Cbx = Me.Controls("ComboBox" & Cstr(i))
    ' then manipulate Cbx as you have done.
Next I

最后,既然您的40个组合框都是一样的,为什么不只使用1个呢?您可以将其从一行移动到另一行,让用户进行选择,并将选择转移到一个文本框中,该文本框在退出时显示在Cbx的位置。当您再次单击Tbx时,它将被Cbx替换,以便您可以再次访问列表。

使用combobox控件的
RowSource
属性

Option Explicit


Private Sub UserForm_Initialize()

    Dim tsheet As Worksheet
    Set tsheet = ThisWorkbook.Sheets("Players")

    Dim rs As String
    rs = "Players!a2:d" & tsheet.Cells(tsheet.Rows.Count, 1).End(xlUp).Row

    Dim aaa As Control
    For Each aaa In Me.Controls
        If Left(aaa.Name, 8) = "ComboBox" Then
            aaa.RowSource = rs                ' =mySheet!a2:d24 in properties
            aaa.ControlSource = "Players!z1"  ' put the chosen value into this cell (example)
            aaa.ColumnCount = 4
            aaa.BoundColumn = 2
            aaa.ColumnWidths = "1;50;50;50"   ' Hide first column in dropdown
        End If
    Next aaa

End Sub

使用combobox控件的
RowSource
属性

Option Explicit


Private Sub UserForm_Initialize()

    Dim tsheet As Worksheet
    Set tsheet = ThisWorkbook.Sheets("Players")

    Dim rs As String
    rs = "Players!a2:d" & tsheet.Cells(tsheet.Rows.Count, 1).End(xlUp).Row

    Dim aaa As Control
    For Each aaa In Me.Controls
        If Left(aaa.Name, 8) = "ComboBox" Then
            aaa.RowSource = rs                ' =mySheet!a2:d24 in properties
            aaa.ControlSource = "Players!z1"  ' put the chosen value into this cell (example)
            aaa.ColumnCount = 4
            aaa.BoundColumn = 2
            aaa.ColumnWidths = "1;50;50;50"   ' Hide first column in dropdown
        End If
    Next aaa

End Sub
在模块中:

Dim ArrPlayers() as integer
在userform初始化中:

'To Do: add code to populate listbox with players
ReDim ArrPlayers (0 To 39)
在列表框更改事件中:

txtPosition.text = ArrPlayers(lstPlayers.ListIndex)
ArrPlayers(lstPlayers.ListIndex) = cInt(txtPosition.text)
在文本框更改事件中:

txtPosition.text = ArrPlayers(lstPlayers.ListIndex)
ArrPlayers(lstPlayers.ListIndex) = cInt(txtPosition.text)
然后需要保存这些值。

在模块中:

Dim ArrPlayers() as integer
在userform初始化中:

'To Do: add code to populate listbox with players
ReDim ArrPlayers (0 To 39)
在列表框更改事件中:

txtPosition.text = ArrPlayers(lstPlayers.ListIndex)
ArrPlayers(lstPlayers.ListIndex) = cInt(txtPosition.text)
在文本框更改事件中:

txtPosition.text = ArrPlayers(lstPlayers.ListIndex)
ArrPlayers(lstPlayers.ListIndex) = cInt(txtPosition.text)

然后您需要保存这些值。

Hi Variatus感谢您的输入。如果我对你的理解是正确的,我对此不太确定:)那么移动是不可能的,因为没有文本框,只有下拉菜单,当我说textfield时,我指的是组合框的textfield,我有40个文本框的原因是,当用户在所有文本框中选择某个内容并按下保存按钮时,所有这些内容都会被删除combox的文本字段被传输到工作表中。用户表单是这样的:它是一个高尔夫的起始表,意味着所有组合框都有一个包含所有球员的列表,然后他为每个起始位置选择球员,因此40 cbx但是thx对于上面的代码,我将看看我是否能使其工作,我认为将其设置为thx是很有意义的,因为它花时间帮助队友;)我真的不知道如何为ComboBox创建循环如果您在完全相同的位置有一个Tbx和一个大小相同的Cbx,那么顶部的一个将是用户可以看到或使用的全部。您可以隐藏其中一个控件,以便更好地测量,或者因为在需要Cbx之前并不真正需要它。所以,你有40个Tbx。当用户单击其中任何一个按钮时,Cbx将显示在相应位置。当他点击其他地方时,Cbx的结果被传输到它下面的Tbx,Cbx要么消失,要么在用户点击的Tbx位置重新出现。现在我得到了它,userform的孔加载速度快得多非常好thx很多!嗨,Variatus,谢谢你的意见。如果我对你的理解是正确的,我对此不太确定:)那么移动是不可能的,因为没有文本框,只有下拉菜单,当我说textfield时,我指的是组合框的textfield,我有40个文本框的原因是,当用户在所有文本框中选择某个内容并按下保存按钮时,所有这些内容都会被删除combox的文本字段被传输到工作表中。用户表单是这样的:它是一个高尔夫的起始表,意味着所有组合框都有一个包含所有球员的列表,然后他为每个起始位置选择球员,因此40 cbx但是thx对于上面的代码,我将看看我是否能使其工作,我认为将其设置为thx是很有意义的,因为它花时间帮助队友;)我真的不知道如何为ComboBox创建循环如果您在完全相同的位置有一个Tbx和一个大小相同的Cbx,那么顶部的一个将是用户可以看到或使用的全部。您可以隐藏其中一个控件,以便更好地测量,或者因为在需要Cbx之前并不真正需要它。所以,你有40个Tbx。当用户单击其中任何一个按钮时,Cbx将显示在相应位置。当他点击其他地方时,Cbx的结果被传输到它下面的Tbx,Cbx要么消失,要么在用户点击的Tbx位置重新出现。现在我得到了它,userform的孔加载速度快得多非常好thx很多!不要定义
t工作表
,然后在代码中使用
工作表(“玩家”)
。。。。使用
tsheet
无需在运行时定义
.RowSource
.ColumnCount.BoundColumn.ColumnWidths属性。。。。这些值将与工作簿一起保存。。。。在单独的子例程中设置这些值,只运行一次,然后保存工作簿。如果要对这些值进行任何更改,请重新运行sub,不要定义
t工作表
,然后在代码中使用
工作表(“玩家”)
。。。。使用
tsheet
无需定义
.RowSource