Excel 如何在VBA中处理生成的列表框并动态添加项?

Excel 如何在VBA中处理生成的列表框并动态添加项?,excel,vba,listbox,Excel,Vba,Listbox,我成功地动态生成了列表框。但我现在正在努力解决和填充这些生成的列表框。此外,我不知道如何激活这些列表框的MultiSelect属性。只有ActiveX才能做到这一点吗 我第一次在userForm上尝试ActiveX-Listboxs。现在我切换回工作表上的“正常”列表框。“FS”是我正在处理的工作表的名称。为了便于理解:我正在遍历工作表FS上的列,并为每列创建一个列表框。在每个列表框中,将添加相应列的条目 For i = 1 To 10 LastRow = FS.Cells(Rows.C

我成功地动态生成了列表框。但我现在正在努力解决和填充这些生成的列表框。此外,我不知道如何激活这些列表框的MultiSelect属性。只有ActiveX才能做到这一点吗

我第一次在userForm上尝试ActiveX-Listboxs。现在我切换回工作表上的“正常”列表框。“FS”是我正在处理的工作表的名称。为了便于理解:我正在遍历工作表FS上的列,并为每列创建一个列表框。在每个列表框中,将添加相应列的条目

For i = 1 To 10
    LastRow = FS.Cells(Rows.Count, i).End(xlUp).Row
        With FS
            Set lb = FS.Shapes.AddFormControl(xlListBox, 100, 10, 100, 100)
            lb.ControlFormat.MultiSelect = 2
            For Each cell In FS.Range(Cells(1, i), Cells(LastRow,i)).Cells
                    lb.ControlFormat.AddItem cell.Value 'This is the problematic line
            Next cell
        End With
Next i

改为使用.ControlFormat.ListFillRange,并将MultiSelect设置为3。像这样的东西应该适合你:

Sub tgr()

    Dim FS As Worksheet
    Dim lb As Shape
    Dim i As Long

    Set FS = ActiveWorkbook.Worksheets("FS")
    For i = FS.Columns("A").Column To FS.Cells(1, FS.Columns.Count).End(xlToLeft).Column
        Set lb = FS.Shapes.AddFormControl(xlListBox, (i - 1) * 100 + 10, 10, 100, 100)
        With lb
            .ControlFormat.MultiSelect = 3
            .ControlFormat.ListFillRange = FS.Range(FS.Cells(1, i), FS.Cells(FS.Rows.Count, i).End(xlUp)).Address(External:=True)
        End With
    Next i

End Sub

改为使用.ControlFormat.ListFillRange,并将MultiSelect设置为3。像这样的东西应该适合你:

Sub tgr()

    Dim FS As Worksheet
    Dim lb As Shape
    Dim i As Long

    Set FS = ActiveWorkbook.Worksheets("FS")
    For i = FS.Columns("A").Column To FS.Cells(1, FS.Columns.Count).End(xlToLeft).Column
        Set lb = FS.Shapes.AddFormControl(xlListBox, (i - 1) * 100 + 10, 10, 100, 100)
        With lb
            .ControlFormat.MultiSelect = 3
            .ControlFormat.ListFillRange = FS.Range(FS.Cells(1, i), FS.Cells(FS.Rows.Count, i).End(xlUp)).Address(External:=True)
        End With
    Next i

End Sub

我建议你这样做:

Sub test()
''''Declarations'''''''''''''''''''''''''''
Dim lb As ListBox                           '
Dim sht As Worksheet                        '
Dim rng As Range                            '
Dim cell As Range                           '
Dim i As Long                               '
'''''''''''''''''''''''''''''''''''''''''''''
Set sht = ThisWorkbook.Worksheets("Name of your worksheet")
For i = 1 To 10
    With sht
        Set rng = .Range(.Cells(1, i), .Cells(.Rows.Count, i).End(xlUp))
        Set lb = sht.ListBoxes.Add(100 * i, 10, 100, 100) 'just an indicative way to create the List boxes without them overlapping
    End With
    lb.Name = "ListBox" & i
    lb.MultiSelect = 2
    For Each cell In rng
        lb.AddItem cell.Value
    Next cell
Next i
End Sub
sht.ListBoxes("ListBox" & i)
更新(涵盖所作评论)

我更新了上面的代码,将列表框命名为“ListBox1”、“ListBox2”等,而不是“ListBox1”等

要引用其中一个列表框,您需要使用对
列表框集合的引用。此集合属于列表框所在的工作表。例如,要引用“ListBoxi”,其中i=1,2…n,您需要这样做:

Sub test()
''''Declarations'''''''''''''''''''''''''''
Dim lb As ListBox                           '
Dim sht As Worksheet                        '
Dim rng As Range                            '
Dim cell As Range                           '
Dim i As Long                               '
'''''''''''''''''''''''''''''''''''''''''''''
Set sht = ThisWorkbook.Worksheets("Name of your worksheet")
For i = 1 To 10
    With sht
        Set rng = .Range(.Cells(1, i), .Cells(.Rows.Count, i).End(xlUp))
        Set lb = sht.ListBoxes.Add(100 * i, 10, 100, 100) 'just an indicative way to create the List boxes without them overlapping
    End With
    lb.Name = "ListBox" & i
    lb.MultiSelect = 2
    For Each cell In rng
        lb.AddItem cell.Value
    Next cell
Next i
End Sub
sht.ListBoxes("ListBox" & i)
不幸的是,据我所知,没有
.SelectedItems.Count
或类似的方法可用于表单控件列表框

记住这一点,您可以找到“ListBox1”的选定项目数,例如:

Dim selectedItems As Long
selectedItems = 0
Set lb = sht.ListBoxes("ListBox" & 1)
For i = 1 To lb.ListCount Step 1
    If lb.Selected(i) Then
        selectedItems = selectedItems + 1
    End If
Next i
If selectedItems = 0 Then
    MsgBox "No user selected"
End If
需要记住的几件事:

  • 根据列表框是否在用户窗体上,第一项的索引从
    0
    1
    不等
  • 要使用其名称(如
    Listbox1.DoSomething
    )引用列表框,它需要是
    ActiveX
    控件,而不是表单控件

  • 我建议你这样做:

    Sub test()
    ''''Declarations'''''''''''''''''''''''''''
    Dim lb As ListBox                           '
    Dim sht As Worksheet                        '
    Dim rng As Range                            '
    Dim cell As Range                           '
    Dim i As Long                               '
    '''''''''''''''''''''''''''''''''''''''''''''
    Set sht = ThisWorkbook.Worksheets("Name of your worksheet")
    For i = 1 To 10
        With sht
            Set rng = .Range(.Cells(1, i), .Cells(.Rows.Count, i).End(xlUp))
            Set lb = sht.ListBoxes.Add(100 * i, 10, 100, 100) 'just an indicative way to create the List boxes without them overlapping
        End With
        lb.Name = "ListBox" & i
        lb.MultiSelect = 2
        For Each cell In rng
            lb.AddItem cell.Value
        Next cell
    Next i
    End Sub
    
    sht.ListBoxes("ListBox" & i)
    
    更新(涵盖所作评论)

    我更新了上面的代码,将列表框命名为“ListBox1”、“ListBox2”等,而不是“ListBox1”等

    要引用其中一个列表框,您需要使用对
    列表框集合的引用。此集合属于列表框所在的工作表。例如,要引用“ListBoxi”,其中i=1,2…n,您需要这样做:

    Sub test()
    ''''Declarations'''''''''''''''''''''''''''
    Dim lb As ListBox                           '
    Dim sht As Worksheet                        '
    Dim rng As Range                            '
    Dim cell As Range                           '
    Dim i As Long                               '
    '''''''''''''''''''''''''''''''''''''''''''''
    Set sht = ThisWorkbook.Worksheets("Name of your worksheet")
    For i = 1 To 10
        With sht
            Set rng = .Range(.Cells(1, i), .Cells(.Rows.Count, i).End(xlUp))
            Set lb = sht.ListBoxes.Add(100 * i, 10, 100, 100) 'just an indicative way to create the List boxes without them overlapping
        End With
        lb.Name = "ListBox" & i
        lb.MultiSelect = 2
        For Each cell In rng
            lb.AddItem cell.Value
        Next cell
    Next i
    End Sub
    
    sht.ListBoxes("ListBox" & i)
    
    不幸的是,据我所知,没有
    .SelectedItems.Count
    或类似的方法可用于表单控件列表框

    记住这一点,您可以找到“ListBox1”的选定项目数,例如:

    Dim selectedItems As Long
    selectedItems = 0
    Set lb = sht.ListBoxes("ListBox" & 1)
    For i = 1 To lb.ListCount Step 1
        If lb.Selected(i) Then
            selectedItems = selectedItems + 1
        End If
    Next i
    If selectedItems = 0 Then
        MsgBox "No user selected"
    End If
    
    需要记住的几件事:

  • 根据列表框是否在用户窗体上,第一项的索引从
    0
    1
    不等
  • 要使用其名称(如
    Listbox1.DoSomething
    )引用列表框,它需要是
    ActiveX
    控件,而不是表单控件

  • 请在有问题的行之前尝试
    Debug.Print cell.Value
    ,看看您在有问题的行之前得到了什么
    Debug.Print cell.Value
    ,看看您在@Stavros获得了什么!生成列表框现在可以正常工作,我现在在读取值时遇到问题。似乎我无法从我命名为lb.name=“ListBox”&I的生成的列表框中读取项目
    如果ListBox1.SelectedItems.Count=0,则MsgBox“未选择项目”结束,如果
    -抛出错误“未找到对象”@DXR我已更新我的帖子以回答您的评论。如果这已经解决了你的问题,请考虑接受它作为回答。非常感谢你的帮助@斯塔夫罗斯!我有两个顾虑:1)为什么需要将变量“I”定义为“long”。“整数”不够吗?2) 是否可以在表单列表框上编程“OnClick”事件?e、 g.:在列表框1中选择一个项目会自动生成包含更多项目的第二个列表框。@例如,您可以在
    Module1
    中构建
    Sub
    ,并使用列表框的
    .OnAction
    属性。创建列表框时,可以设置此属性,如
    lb.OnAction=“Module1.runThis”
    ,其中
    runThis
    是单击列表框时要运行的
    子项。要了解更多信息,我建议你发布一个新问题谢谢@Stavros!生成列表框现在可以正常工作,我现在在读取值时遇到问题。似乎我无法从我命名为lb.name=“ListBox”&I的生成的列表框中读取项目
    如果ListBox1.SelectedItems.Count=0,则MsgBox“未选择项目”结束,如果
    -抛出错误“未找到对象”@DXR我已更新我的帖子以回答您的评论。如果这已经解决了你的问题,请考虑接受它作为回答。非常感谢你的帮助@斯塔夫罗斯!我有两个顾虑:1)为什么需要将变量“I”定义为“long”。“整数”不够吗?2) 是否可以在表单列表框上编程“OnClick”事件?e、 g.:在列表框1中选择一个项目会自动生成包含更多项目的第二个列表框。@例如,您可以在
    Module1
    中构建
    Sub
    ,并使用列表框的
    .OnAction
    属性。创建列表框时,可以设置此属性,如
    lb.OnAction=“Module1.runThis”
    ,其中
    runThis
    是单击列表框时要运行的
    子项。要了解更多信息,我建议你发布一个新问题谢谢@tigeravatar!生成列表框现在可以正常工作,我现在在读取值时遇到问题。似乎我无法从我命名为lb.name=“ListBox”&I的生成的列表框中读取项目<代码>如果ListBox1.SelectedItems.Count=0,则MsgBox“未选择项目”结束,如果
    -抛出错误“未找到对象”谢谢@tigeravatar!生成t