【问题标题】:Excel 2013: VBA Code to filter worksheet data from multiple listbox selectionsExcel 2013:用于从多个列表框选择中过滤工作表数据的 VBA 代码
【发布时间】:2015-07-10 13:49:49
【问题描述】:

我已经花了 3 天的时间寻找解决方案,我知道我已经接近了,但我就是不明白我的问题以及为什么会发生。

首先,我有一个电子表格,其中包含员工姓名(A 列,从第 5 行开始)和 B 列到 HG 的资源计划数据(项目的缩写)。每个列 - 除了 A 列 - 代表日历的 1 天(列标题是日期)。

我还有一个包含 3 个列表框(多选)的用户表单。 LB1 = 员工姓名,LB2 = 项目缩写,LB3 暂时无所谓。我在这个用户表单上还有 3 个按钮,1 个用于重置 LB 选择,1 个用于将过滤器应用于电子表格,1 个用于重置电子表格上的过滤器。

我用于重置 LB 选择和电子表格上的过滤器的代码工作正常。应用过滤器的那个不会按预期的方式工作。到目前为止,此按钮的代码如下所示(目前仅尝试处理 1 LB):

' Apply filter to spreadsheet
Private Sub CB_FilterActive_Click()
    Dim arrMitarbeiter() As Variant
    Dim i As Integer, count As Integer

    count = 1
    For i = 0 To ListBox1.ListCount - 1
        If ListBox1.Selected(i) = True Then
            ReDim Preserve arrMitarbeiter(count)
            arrMitarbeiter(count) = ListBox1.List(i)
            count = count + 1
        End If
    Next i
    Worksheets("Einsatzplan").UsedRange.Cells.AutoFilter field:=1, Criteria1:=Array(arrMitarbeiter)
End Sub

事情是这样的:

点击“应用过滤器按钮”会使电子表格中包含数据的所有行消失。当我尝试调试代码时,我看到自动过滤器的数组在 LB 选择方面得到了正确填充。当我点击工作表上应用的过滤器的下拉菜单并转到“textfilter -> equals”并查看填充的过滤条件时,它就在那里。它只是不会显示相应的行。我尝试了很多东西,我只是不知道问题出在哪里。另外,我只是一个试图解决问题的 VBA 初学者。因此,任何帮助都将不胜感激(以及当我想组合所有 3 个列表框的选择以将其交给自动过滤器的情况)!

真诚地, 小窝

编辑:

这就是我当前的代码的样子,重写它以确保算法。我也调试了整个事情。有趣的是:在调试过程中(选择listbox1 中的一项),数组包含这个精确值。应用过滤器并转到filter options dropdown -> textfilter -> equals 后,那里没有任何值,这让我认为这就是它隐藏所有行的原因。但是为什么值在数组中并且之后没有应用于过滤器?此外,Field:= 应该是有关 Microsoft 文档的可选参数,但是当我忽略它时,它会给我一个运行时错误(错误# 1004:无法执行范围对象的 AutoFilter 方法)。
Option Explicit

' Apply Filter to Sheet
Private Sub CommandButton2_Click()
    Dim x() As String, r() As String, k() As String
    Dim i As Integer, j As Integer, s As Integer

    ReDim x(0)

    Application.ScreenUpdating = False
    ActiveSheet.UsedRange.AutoFilter

    ' Filter Array for ListBox1
    For i = 0 To ListBox1.ListCount - 1
        If Me.ListBox1.Selected(i) = True Then
            x(UBound(x)) = Me.ListBox1.List(i)
            ReDim Preserve x(UBound(x) + 1)
        End If
    Next i
    If UBound(x) <> 0 Then
        Worksheets("Tabelle1").Range("A1").AutoFilter Field:=1, Criteria1:=x, Operator:=xlFilterValues
        ReDim Preserve x(UBound(x) - 1)
    End If

    ReDim r(0)

    ' Filter Array for ListBox2
    For j = 0 To ListBox2.ListCount - 1
        If Me.ListBox2.Selected(j) = True Then
            r(UBound(r)) = Me.ListBox2.List(j)
            ReDim Preserve r(UBound(r) + 1)
        End If
    Next j
    If UBound(r) <> 0 Then
        ReDim Preserve r(UBound(r) - 1)
        Worksheets("Tabelle1").Range("B1 : HG1").AutoFilter , Criteria1:=r, Operator:=xlFilterValues
    End If

    ReDim k(0)

    ' Filter Array for ListBox3
    For s = 0 To ListBox3.ListCount - 1
        If Me.ListBox3.Selected(s) = True Then
            k(UBound(k)) = Me.ListBox3.List(s)
            ReDim Preserve k(UBound(k) + 1)
        End If
    Next s
    If UBound(k) <> 0 Then
        ReDim Preserve k(UBound(k) - 1)
        Worksheets("Tabelle1").AutoFilter , Criteria1:=k, Operator:=xlFilterValues
    End If

    Application.ScreenUpdating = True

End Sub

' Reset Filter Mask
Private Sub CommandButton1_Click()
    Dim iCount1 As Integer
    Dim iCount2 As Integer
    Dim iCount3 As Integer

    For iCount1 = 0 To Me!ListBox1.ListCount - 1
        Me!ListBox1.Selected(iCount1) = False
    Next iCount1

    For iCount2 = 0 To Me!ListBox2.ListCount - 1
        Me!ListBox2.Selected(iCount2) = False
    Next iCount2

    For iCount3 = 0 To Me!ListBox3.ListCount - 1
        Me!ListBox3.Selected(iCount3) = False
    Next iCount3
End Sub

' Delete Filter from Sheet
Private Sub CommandButton3_Click()
    On Error Resume Next
    ActiveSheet.ShowAllData
End Sub

【问题讨论】:

  • 您是否尝试过获取与UsedRange 不同的范围?我想UsedRange 从第 1 行获取单元格。如果在 1 和 5 之间有空行,过滤器可能会显示一些奇怪的行为。我应该考虑尝试Range("A5:HG")
  • 我已经尝试了不同的手动定义范围。这根本不会改变任何事情。
  • 如果您的目标不完全是学习 VBA。还可以考虑使用Pivot Table。 (插入/数据透视表)。它会自动过滤和计算很多东西,有时它比 VBA 更容易。
  • 数据透视表对我不起作用。是的,我确实想学习 VBA。
  • 在那里找到了你的答案。如果我可以建议的话,我会在一张表中保留一份姓名列表,并在第二张表中添加只有三列(姓名、日期、项目),我在其中添加姓名、项目和日期,每行一个日期(姓名可以重复,日期可以重复,项目可以重复)。这样,您就可以使用数据透视表(我总是更喜欢编码)

标签: excel vba listbox multi-select autofilter


【解决方案1】:

里面有两个问题:

1 - arrMitarbeiter 已经是您在 Dim arrMitarbeiter() As Variant 中定义的数组

因此,您不能将Array(arrMitarbeiter) 传递给过滤器,而只能传递arrMitarbeiter

2 - 如果您不使用xlFilterValues 运算符,它将仅过滤数组的最后一项,因此添加此运算符。

只修复这一行(我做了两行只是为了阅读):

Worksheets("Einsatzplan").UsedRange.Cells.AutoFilter 
     field:=1, Criteria1:=arrMitarbeiter, Operator:=xlFilterValues

【讨论】:

  • 我刚刚认识到,如果我手动设置过滤器(而不是通过用户表单),然后从过滤器选项的下拉菜单中将过滤器值输入到“textfilter -> equals -> value” ,它会正确过滤。这里可能是什么问题?整列被格式化为文本。看起来有些事情搞砸了,但我不明白是什么。
  • 我也调试了整个事情。有趣的是:在调试期间(选择列表框中的一项),数组包含这个确切的值。应用过滤器并转到过滤器选项下拉菜单 -> textfilter -> equals 后,其中没有任何值,这让我认为这就是它隐藏所有行的原因。但是为什么值在数组中并且之后没有应用于过滤器?
  • 您是否进行了我建议的更改?它们有效(经过测试)如果您有一个空值,并且该空值是数组中的最后一个,那么过滤器的结果将为空。
  • 是的,我确实尝试过这个,并没有改变任何更好的东西。我将我当前的代码添加到我在上一条评论中提到的 OP 中。也许你可以帮我解决这个问题。
  • 我有一种强烈的感觉,即 VBA 中的所有索引都是从 1 开始的,而不是从零开始的。您使用从零开始的数组,但您与从 1 开始的列表进行比较。
猜你喜欢
  • 1970-01-01
  • 2017-01-05
  • 2019-07-26
  • 1970-01-01
  • 2021-05-16
  • 2018-07-07
  • 1970-01-01
  • 2011-03-15
  • 2018-01-03
相关资源
最近更新 更多