【问题标题】:Pass Filtered Table data to ListBox将过滤后的表格数据传递给 ListBox
【发布时间】:2020-08-19 01:42:22
【问题描述】:

我有一张下表:

我正在尝试过滤数据,然后将过滤后的数据显示到用户窗体上的列表框。 到目前为止的代码:

Dim iList As Variant

Sheet1.ListObjects("PostOneTable").Range.AutoFilter Field:=1, Criteria1:=TextBox1.Value & "*"
Sheet1.ListObjects("PostOneTable").Range.AutoFilter Field:=2, Criteria1:=TextBox2.Value & "*"
Sheet1.ListObjects("PostOneTable").Range.AutoFilter Field:=3, Criteria1:=TextBox3.Value & "*"
Sheet1.ListObjects("PostOneTable").Range.AutoFilter Field:=5, Criteria1:=TextBox4.Value & "*"

Dim jList As Range

Set jList = 
Sheet1.ListObjects("PostOneTable").DataBodyRange.SpecialCells(xlCellTypeVisible)

ListBox1.List = jList

但是,在运行代码时,我遇到了一些问题。 首先,过滤器似乎没有正确应用。比如我用一个字符串,比如:

Sheet1.ListObjects("PostOneTable").Range.AutoFilter Field:=1, Criteria1:="ryd"

我希望只能在表格和列表框中看到第四项。但是,两者都是空白。

第二个问题是代码没有将过滤后的列表驱动到文本框。

请注意,我知道使用循环的其他搜索方式。然而,这种方法 很好,因为最终用户将能够直接在表格中看到他们在表单上的操作结果。

谢谢!

编辑: 在玩它时,我发现了一些有趣的东西。如果我注释掉驱动数据到列表框的部分并重写过滤行,过滤现在可以工作了。

【问题讨论】:

  • ListBox 的列必须与您分配给它的 List 一样多。您还应该指定所有列的宽度并分配一个 BoundColumn。
  • @Variatus 全部完成。列表框有六列,并且正确指定了宽度。这都是在属性框中完成的;不在代码中
  • 在这种情况下,请尝试将未过滤的 DataBodyRange 分配给列表框。如果可行,请将jList.Value 传输到由您的代码格式化的数组。如果它不起作用将jList.Value 转移到字符串数组。但无论哪种方式都需要与使用 Add 方法填充列表框一样多的代码和时间 :-)
  • @Variatus 错误代码是“无法设置列表属性。无效的属性数组索引。”错误出现在“ListBox1.List = jList”上。你能告诉我 Add 方法吗?自从发布以来,我可能更喜欢循环......
  • AddItem 方法对于多列数据来说有点麻烦,并且比将数组分配给 ListBox.List 慢很多。但是对于初学者或中级开发人员来说,我的答案可能比我的答案更容易写。

标签: excel vba


【解决方案1】:

Range.Value 仅返回范围内第一个区域的值。 Range.SpecialCells(xlCellTypeVisible) 将返回一个 Range,其中包含每个连续单元格块的区域。

ListBox1.List = jList

ListBox1.List 将只有第一组可见行的数据(第一组在jList 中)。

您仍然可以使用ListObject 过滤数据。您只需要编写一个函数来返回可见数据。这是一项琐碎的任务。

ListBox1.List = ListObjectVisibleData(Sheet1.ListObjects("PostOneTable"))

Public Function ListObjectVisibleData(ByVal ListObject As ListObject)
    Dim Map As New Collection
    Dim Row As Range
    For Each Row In ListObject.DataBodyRange.Rows
        If Not Row.EntireRow.Hidden Then
            Map.Add Row
        End If
    Next
    
    Dim Results As Variant
    Dim r As Long, c As Long
    
    If Map.Count = 0 Then
        ReDim Results(1 To 1, 1 To ListObject.ListColumns.Count)
    Else
        ReDim Results(1 To Map.Count, 1 To ListObject.ListColumns.Count)
        For Each Row In Map
            r = r + 1
            For c = 1 To UBound(Results, 2)
                Results(r, c) = Row.Cells(1, c).Value
            Next
        Next
    End If
    
    ListObjectVisibleData = Results
End Function

【讨论】:

  • 哇。像一个魅力。我对某事感到好奇。什么是“ReDim”?我没见过太多,但我绝对没见过。当然,这不是辅导课...
  • ReDimRedimension 的缩写。它允许您设置数组的维度。您应该在代码模块中键入 Redim,然后按 F1 导航到帮助文档。
猜你喜欢
  • 1970-01-01
  • 2017-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多