【问题标题】:AutoFilter NOT seeing numerical data in Filtered view (Multiple Values)自动筛选在筛选视图中看不到数字数据(多个值)
【发布时间】:2021-09-03 19:25:50
【问题描述】:

一段时间以来一直在研究这个自动过滤代码。就它而言,它运作良好。如果我在“报价”中使用我的搜索条件替换 FilterCriteria,它每次都有效。但是,当尝试在 FilterCriteria 中传递数字时,每次都无法在我的范围内找到任何内容(仅限 A:D!)。它可以很好地找到 Colums E:G 中的所有文本字段,因为它们都是文本。 A:D 列不返回任何内容。我尝试将 A:D 格式化为文本而不是数字,但过滤时它仍然什么也看不到。希望在末尾显示示例范围。

Sub FindProduct()

  'Note: This macro uses the function LastRow at end of Module
  ' Highly moded code from Ron de Bruin

    'To define My_Range
       Dim My_Range As Range
       Dim CalcMode As Long
       Dim ViewMode As Long
       Dim CCount As Long
    'To define New Sheet and Range
       Dim WSNew As Worksheet
    'Use for column and filter data selection
       Dim FilterCriteria As String
       Dim PickCol As String

    'Set filter range on ActiveSheet
       Set My_Range = Range("A1:G" & LastRow(ActiveSheet))
       My_Range.Parent.Select

 '  ************************************
    My_Range.Parent.AutoFilterMode = False
       '  Unprotect sheet, turn off AutoFilter, Show All
          With ActiveSheet
             .Unprotect
             On Error Resume Next
             .ShowAllData
          End With
    '  Code to check if workbook is protected here. Redundant.
 '  ****************************************
     'Turn off ScreenUpdating, Calculation, EnableEvents code here
  '  +++++++++++++++++++++++++++++++++++
       '  Use this to pick a Column to search and your FilterCriteria
       PickCol = InputBox("What Column do you want to search in " & vbCrLf _
       & "(A=1,B=2,C=3,D=4,E=5,F=6,G=7)?" _
       & vbCrLf & vbCrLf, "Select Column to Search")
          '  Input error check
       '  ######################
       FilterCriteria = InputBox("What are you looking for?" _
       & vbCrLf & vbCrLf & "This will work with partial Information.", _
       "Enter Filter Parameter")
          '  Input error check
 '  *********************************************************
    '  Insert PickCol and FilterCriteria variables
    My_Range.AutoFilter Field:=PickCol, Criteria1:="=*" & FilterCriteria & "*"

    'Check if there are not more then 8192 areas (limit of areas that Excel can copy)
    CCount = 0
    On Error Resume Next
    CCount = My_Range.Columns(1).SpecialCells(xlCellTypeVisible).Areas(1).Cells.Count
    On Error GoTo 0
      If CCount = 0 Then
          MsgBox "There are more than 8192 areas:" _
               & vbCrLf & "It is not possible to copy the visible data."
      Else
        '  ***********************************************
           'Delete "Filtered Data" sheet if it exists code here
        '  ***********************************************
        '  ------------------------------
          'Add a new Worksheet
           Set WSNew = Worksheets.Add(After:=Sheets(ActiveSheet.Index))
           On Error Resume Next
           WSNew.Name = "Filtered Data"
        '  ------------------------------
        '  ///////////////////////////////////////////////////
           'Copy/paste the visible data to the new worksheet
           My_Range.Parent.AutoFilter.Range.Copy
             ' Paste copied range starting at Cell("A2")
             With WSNew.Range("A2")
                 .PasteSpecial Paste:=8
                 .PasteSpecial xlPasteAll
                 .PasteSpecial xlPasteFormats
                 Application.CutCopyMode = False
                 .Select
             End With
        ' ///////////////////////////////////////////////////
        ' *****************************************
          'Adds Formatted Text to Cell ("A1") code here
        ' *****************************************
      End If

    ' Turn off AutoFilter
    My_Range.Parent.AutoFilterMode = False

'  ******************************************************
   'More finishing code here
'  ******************************************************

End Sub

 Function LastRow(Sh As Worksheet)
     On Error Resume Next
     LastRow = Sh.Cells.Find(What:="*", _
                        After:=Sh.Range("A1"), _
                        Lookat:=xlPart, _
                        LookIn:=xlValues, _
                        SearchOrder:=xlByRows, _
                        SearchDirection:=xlPrevious, _
                        MatchCase:=False).Row
     On Error GoTo 0
 End Function

样本数据:

    A        B     C         D          E         F           G
Date Rvd    Qty   File#    P.O.#    Cust Name    Vend Name   Carrier
02/14/15    210   41680    38565    Some Tech    John        DHL
03/08/15    458   17017    38569    Them Guys    Donn        Fedx
03/12/15    350   16736    38541    Some Guys    Teri        UPS
03/24/15    236   42630    38655    Some Tech    John        DHL
04/08/15    458   56985    85693    Them Guys    Donn        Fedx
04/12/15    350   12345    43851    Some Guys    Teri        UPS
04/18/15    838   56685    85693    Them Guys    Donn        Fedx
05/05/15    110   13245    43851    Some Guys    Teri        UPS

无论出于何种原因,当它使用 A:D 的任何数字运行自动过滤器时,它都无法提供任何过滤后的数据。正如我所说,如果我在 AutoFilter 行中放置我想要的确切值,它将返回过滤后的数据。

很确定这条线是我的问题/问题: My_Range.AutoFilter Field:=PickCol, Criteria1:="=" & FilterCriteria & ""

有什么想法吗?

我想现在我必须弄清楚如何真正做到这一点。在工作表上正确使用自动过滤器可以正常工作。如果我必须按照文章显示的那样做,那么我必须再添加 4 列,并且我必须在生成此列表的表单上重写 SaveLog 代码中的代码。听起来我需要大幅增加所有代码的大小。对于像我这样的新手来说,在这一点上我当然不知所措。

【问题讨论】:

  • 将数字单元格格式化为文本不足以使 Excel 停止将它们视为数字。从这里:mrexcel.com/forum/excel-questions/…“使用数据 | 文本到列...菜单命令进行所需的转换。在第 3 步(共 3 步)中指定文本格式。”

标签: vba excel


【解决方案1】:

这个问题的核心是不能将文本比较运算符与数字一起使用。 当您将通配符 * 添加到搜索条件时,您将强制执行文本比较。

如果您希望它与数字和文本一起使用并具有可变列选择,则需要添加一些检查以正确构建标准。这将涉及在选择数字列时删除*。要记住的主要事情是,每种数据类型只有某些可用的过滤器。要检查这些,请单击普通过滤器菜单中的箭头,查看Number FiltersDate FiltersText Filters 下列出的内容。

鉴于所有这些,如果您想过滤Contains 上的这些数字列,您需要将其转换为文本。

根据comment by @Tim Williams,您可以使用Data->Text to Columns 功能将您的数字转换为文本。如果您知道需要转换哪些范围,则可以使用 VBA 自动执行此步骤。

使其工作所需的最小参数数似乎是DataTypeFieldInfoFieldInfo 是强制转换的重要一环。

Sub ConvertColumnNumberToText()

    Dim rng_column As Range
    For Each rng_column In Range("B:D").Columns
        rng_column.TextToColumns DataType:=xlDelimited, FieldInfo:=Array(1, 2)
    Next rng_column

End Sub

查看TextToColumns 的文档以查看参数是什么。它一次只能作用于一列,因此是循环。

此外,多次运行此代码并没有什么坏处,只要它只在仅包含数字的列上运行即可。如果您不小心在可以拆分为列的列上运行它(默认包含TAB),您将开始覆盖其他列。

【讨论】:

  • 那么为什么通过菜单栏访问的 AutoFilter 对我的日期和数字有效,但在使用 VBA 代码时却失败了?
  • “有效”是什么意思?你绝对不能在一个号码上做contains。您可以进行equals 或其他一些比较。
  • Contains 不起作用,但通过下拉菜单显示列表中的数字。我可以选择数字并将其过滤掉,以便我看到它。也许这就是我在尝试使用 Contains 时遇到的问题。
  • 是的,这就是问题所在——这就是上面加粗的原因:)。如果您想将contains 转换为文本。如果您想要平等,请从条件中删除 *。如果您希望 contains 用于文本,equality 用于数字,则需要在代码中处理这两种情况,因为它们是不同的标准;键入该列中第二行的列号或数据类型,或选择正确的条件字符串。
  • 没错。最快的解决方案是简单地检查列号并使用硬编码比较。最简单的方法是使用Select...Case,因为它允许指定范围。查看the MS support article on that construction。您知道列2 to 4 是数字。默认大小写为文本。
【解决方案2】:

它并不漂亮,我确信这段代码还有很多改进空间,但这是我要使用的。我将“FilterCriteria”调暗为 Variant,并将紧跟在“PickCol”和“FilterCriteria”输入框之后的单行替换为以下 Select - Case 例程:

    '  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    ' Determines whether "FilterCriteria" is Date, Numerical or text input
    Select Case PickCol
       Case 1
         ' "PickCol" - Column "A" (1) is Date
           ' Define for Numeric
             My_Range.AutoFilter Field:=PickCol, Criteria1:=FilterCriteria

       Case 2 To 4
         ' "PickCol" - Column "B:D" (2-4) Are Numerical
             ' Define for Numeric
           My_Range.AutoFilter Field:=PickCol, Criteria1:=FilterCriteria
           ' This column CAN have mixed Numeric and Text data. So-> Evaluate that
             If IsNumeric(FilterCriteria) Then
             ' Define for Numeric
                My_Range.AutoFilter Field:=PickCol, Criteria1:=FilterCriteria
             Else
             ' Redefine for Text instead
                My_Range.AutoFilter Field:=PickCol, Criteria1:="=*" & FilterCriteria & "*"
             End If
       Case Else
         ' "PickCol" - Column "E:G" (5-7) Are Text
             ' Define for Text
                My_Range.AutoFilter Field:=PickCol, Criteria1:="=*" & FilterCriteria & "*"
       End Select
    '  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

就像我说的。 “它可能不漂亮,但它确实有效。”

感谢@Byron 的建议

这确实允许在 E:G 中使用通配符(部分)输入,尽管 A:D 必须与所写的完全相同。我仍然必须捕获输入的不存在数据的错误,否则它会崩溃。与其他步骤相比,这是一小步。在工作中为我再吃一块饼干。好东西,因为我饿了。哈哈

【讨论】:

  • 这是Select...Case 的一个非常干净的实现,键入列号。很高兴你能把它们放在一起。
  • @拜伦。如您所见,我没有完全使用您的建议,但他们确实让我想到了一种方法来做到这一点,而不必重做两个不同工作簿中的所有代码。感谢您的指导。
【解决方案3】:

不完全是问题的答案,但对我来说,只需将 numberformat 设置为 text 就足以能够过滤带有数字的字段,例如带有字符串的字段。

Columns("M").NumberFormat = "@"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-14
    • 2019-02-02
    • 2013-10-02
    • 1970-01-01
    • 2021-12-03
    • 2020-07-22
    • 1970-01-01
    相关资源
    最近更新 更多