【问题标题】:How to address generated ListBoxes and add Items dynamically in VBA?如何处理生成的列表框并在 VBA 中动态添加项目?
【发布时间】:2019-07-03 13:31:28
【问题描述】:

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

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

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

【问题讨论】:

  • 在有问题的行之前尝试Debug.Print cell.Value,看看你会得到什么

标签: excel vba listbox


【解决方案1】:

我建议你这样做:

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

更新(覆盖评论)

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

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

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

需要注意的几点:

  1. 根据列表框是否在用户窗体上,第一项的索引从 01 不等
  2. 要使用名称如Listbox1.DoSomething 来引用列表框,它必须是ActiveX 控件而不是表单控件。

【讨论】:

  • 谢谢@Stavros!生成列表框现在可以正常工作,我现在在读取值时遇到问题。似乎我无法从我命名为 lb.name = "ListBox" & i 的那些生成的 ListBox 中读出项目。 If ListBox1.SelectedItems.Count = 0 Then MsgBox "No Item Selected" End If - 抛出错误“找不到对象”
  • @DXR 我已更新我的帖子以回复您的评论。如果这解决了您的问题,请考虑接受它作为答案。
  • 您好,非常感谢@stavros 的帮助!我有两个担忧:1)为什么需要将变量“i”定义为“long”。 “整数”还不够吗? 2) 是否可以在表单列表框上编写“OnClick”事件?例如:在 Listbox1 中选择一个项目会自动生成第二个 Listbox,其中包含更多项目。
  • @DXR 例如,您可以在Module1 中构建Sub 并使用列表框的.OnAction 属性。创建列表框后,您可以设置此属性,如lb.OnAction = "Module1.runThis",其中runThis 是您希望在单击列表框时运行的sub。有关更多信息,我建议您发布一个新问题
【解决方案2】:

使用 .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

【讨论】:

  • 谢谢@tigeravatar!生成列表框现在可以正常工作,我现在在读取值时遇到问题。似乎我无法从我命名为 lb.name = "ListBox" & i 的那些生成的 ListBox 中读出项目。 If ListBox1.SelectedItems.Count = 0 Then MsgBox "No Item Selected" End If - 抛出错误“找不到对象”
猜你喜欢
  • 2019-11-06
  • 1970-01-01
  • 2017-10-18
  • 2021-05-06
  • 1970-01-01
  • 2017-10-28
  • 2022-11-21
  • 1970-01-01
  • 2016-05-06
相关资源
最近更新 更多