【问题标题】:Filtering multiple tables at once via a search box on excel通过excel上的搜索框一次过滤多个表
【发布时间】:2016-08-03 00:18:54
【问题描述】:

我有一个包含 13 张工作表的 excel 工作簿(一年中每个月一张 + 一张主工作表),每张工作表都有一个相同的员工统计数据表。员工统计表以其对应的月份命名,并具有相同的列标题。 我在主工作表上有一个仪表板,其中包含从其他表格中提取的图表。

我想创建一个搜索框,让您可以一次过滤各自工作表中的所有表格

这是我无法弄清楚的代码行。我正在尝试使过滤器范围引用多个表。

 Set DataRange = sheets.ListObjects("January""February""March").Range 

是否有任何方法可以对搜索框进行编码以引用多个工作表中的多个表?我需要确定工作表名称和表名称。我不知道该怎么做

作为参考,一月是工作表中标题为“一月”的表格。

这是我使用的完整代码:

 Sub SearchBox()
  Dim dict as Object
  Set dict = CreateObject("Scripting.Dictionary")

 Dim i as Long
 For 1 = 3 to 14
 Set dict(i) = Worksheets(i).ListObjects(1).Range

   Dim myButton As OptionButton
   Dim MyVal As Long
   Dim ButtonName As String
   Dim sht As Worksheet
   Dim myField As Long
   Dim DataRange As Range
   Dim mySearch As Variant

  'Load Sheet into A Variable
   Set sht = ActiveSheet

 'Unfilter Data (if necessary)
  On Error Resume Next
  sht.ShowAllData
  On Error GoTo 0

 'Filtered Data Range (include column heading cells)

   dict(i).Autofilter_

   Field:=myField,_
   Criteria1:="=*" & mySearch & "*", _
   Operator:=xlAnd

   Next

  'Retrieve User's Search Input
   mySearch = sht.Shapes("StaffLookUp").TextFrame.Characters.Text 'Control Form


   'Loop Through Option Buttons
    For Each myButton In ActiveSheet.OptionButtons
    If myButton.Value = 1 Then
    ButtonName = myButton.Text
    Exit For
      End If
     Next myButton

  'Determine Filter Field
   On Error GoTo HeadingNotFound
   myField = Application.WorksheetFunction.Match(ButtonName,          DataRange.Rows(1), 0)
  On Error GoTo 0

  'Filter Data
   DataRange.AutoFilter _
     Field:=myField, _
     Criteria1:="=*" & mySearch & "*", _
     Operator:=xlAnd

  'Clear Search Field
   sht.Shapes("UserSearch").TextFrame.Characters.Text = "" 'Control Form


Exit Sub

'ERROR HANDLERS
HeadingNotFound:
 MsgBox "The column heading [" & ButtonName & "] was not found in cells " &        DataRange.Rows(1).Address & ". " & _
 vbNewLine & "Please check for possible typos.", vbCritical, "Header Name Not Found!"

 End Sub

【问题讨论】:

    标签: vba excel


    【解决方案1】:

    您应该能够使用 Range(Name) 按名称引用 ListObjects。

    我将过滤过程提取到它自己的子程序中。我还添加了一个可选参数 ClearFilters。这将为您提供堆叠过滤器的选项。

    Sub ApplyFilters()
        Dim FieldName As String, mySearch As Variant
        Dim myButton As OptionButton
        Dim m As Integer
    
        For Each myButton In ActiveSheet.OptionButtons
            If myButton.Value = 1 Then
                FieldName = myButton.Text
                Exit For
            End If
        Next myButton
    
        mySearch = ActiveSheet.Shapes("StaffLookUp").TextFrame.Characters.Text    'Control Form
        mySearch = "=*" & mySearch & "*"
    
        For m = 1 To 12
    
           FilterTable MonthName(m), FieldName, mySearch, True
    
        Next
    
    End Sub
    
    
    Sub FilterTable(TableName As String, FieldName As String, mySearch As Variant, Optional ClearFilters As Boolean = False)
        Dim DataRange As Range, FilterColumn As Integer
    
        On Error Resume Next
        Set DataRange = Range(TableName)
        On Error GoTo 0
    
        If DataRange Is Nothing Then
            MsgBox TableName & " not found"
            Exit Sub
        End If
    
        If ClearFilters Then
            On Error Resume Next
            DataRange.Worksheet.ShowAllData
            On Error GoTo 0
        End If
    
        On Error Resume Next
        FilterColumn = DataRange.ListObject.ListColumns(FieldName).Index
        On Error GoTo 0
    
        If FilterColumn = 0 Then
            MsgBox TableName & ": " & FieldName & " not found"
            Exit Sub
        End If
    
        DataRange.AutoFilter _
                Field:=FilterColumn, _
                Criteria1:=mySearch, _
                Operator:=xlAnd
    
    End Sub
    

    【讨论】:

    • 嗨@Thomas Inzinia 感谢您的解决方案,但是我在mySearch = "=*" & mySearch "*" 之后收到一条错误消息,提示“预期:语句结束”
    • 您的示例应如下所示:mySearch = "=*" & mySearch & "*"。我的回答是正确的。
    • 嗨@Thomas,抱歉。我没有注意到我的错字。我放入了您的整个解决方案,当我运行它时,会弹出一条错误消息,告诉我FilterTable MonthName (m), FieldName, mySearch. True 行的“需要对象”。 m = 1 to 12 行是如何工作的?可以编辑此代码以仅列出 12 个列表对象吗?
    • MonthName 接受一个从 1 到 12 的数字,并根据该数字返回月份的名称(例如 Month(1) returns January)。
    • 我假设您的表格是以月份命名的。表名是什么?
    【解决方案2】:

    是否有任何方法可以对搜索框进行编码以引用多个工作表中的多个表?

    不。正如您可能已经收集到的那样,您的尝试不起作用,但我认为我理解您正在尝试做什么就足够了:

    设置 DataRange = sheet.ListObjects("January""February""March").Range

    由于多种原因,它是无效的语法(您可能已经知道),但您也不能分配跨越多个工作表的范围。您正在寻找的内容将在一个循环中完成,而不是 1 个范围,您将拥有 13 个范围(或者您需要的任意数量)。

    我需要确定工作表名称和表名称。我是 不知道该怎么做

    您可以按名称或索引来引用工作表,例如:

    Worksheets(1) '## Refers to the first sheet in the book
    

    或者:

    Worksheets("January") '## Refers to worksheet named 'January' or raise error if sheet name doesn't exist
    

    您需要做的是一个For/Each 循环,并依次处理每个工作表,如果您想要处理它们各自的所有范围,请将它们转储到集合或字典中:

    Dim dict as Object
    Set dict = CreateObject("Scripting.Dictionary")
    
    Dim i as Long
    For i = 1 to 13 'Modify as needed
        '## Assumes only 1 ListObject table on each sheet; if there are multiple,
        '  you should refer to the ListObjects by name instead of index
        Set dict(i) = Worksheets(i).ListObjects(1).Range
    Next
    

    然后,稍后您将在类似的循环中应用过滤器。由于dict 的值 范围,您可以像这样直接使用dict 对象:

    For i = 1 to 13
        dict(i).AutoFilter ...
    
    
    Next
    

    【讨论】:

    • 嗨@David Zemens 感谢您的周到回答。我在原始问题中编辑了我的代码......但可能有一些语法错误。它告诉我Filter Data 下的最后三行语法不正确。我究竟做错了什么? (我是vba新手)
    • 我如何通过名称而不是索引 ## 来引用列表对象?
    • AutoFilter_ 后面不能有空行,去掉空行应该可以避免编译错误。 ListObject 有一个名称,除非您手动完成,否则它可能类似于“Table1”等,但您应该能够从“表格工具”功能区中看到这些名称,并在需要时也可以在此处进行编辑:@987654321 @
    猜你喜欢
    • 2019-08-15
    • 1970-01-01
    • 1970-01-01
    • 2014-07-11
    • 2016-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    相关资源
    最近更新 更多