使用 xlFilterValues 恢复自动筛选会引发错误 13 如果 Len(Criteria1(i))>255 类型不匹配?

Posted

技术标签:

【中文标题】使用 xlFilterValues 恢复自动筛选会引发错误 13 如果 Len(Criteria1(i))>255 类型不匹配?【英文标题】:Restoring AutoFilter with xlFilterValues raises error 13 Type mismatch if Len(Criteria1(i))>255? 【发布时间】:2018-09-12 23:51:43 【问题描述】:

我继承了一些尝试在 Excel 2010-2016 中 save and restore filters 的 VBA 代码(我正在 Excel 2016 - 32 位、16.0.4549.1000 上进行测试)。我已经知道这是 pretty much impossible to do properly 并且以一种理智的方式(例如 Get Date Autofilter in Excel VBA),但它可能失败的不同方式的数量让我感到惊讶。

特别是一个xlFilterValues过滤器,它选择值超过254个字符的单元格,似乎无法保存和恢复

.Criteria1(i) 中的值在读取时被截断为 256 个字符, 如果您保存条件数组 (saved = .Criteria1) 并稍后尝试通过.AutoFilter Criteria1:=saved ... 恢复它,.AutoFilter 将报告“运行时错误 '13' 类型不匹配”如果有 Len(saved(i) ) >= 256

下面列出了可以在空工作簿中运行的测试用例。

每个人都可以复制吗?对绕过此限制的简单方法有何想法?

Sub test()
    Const CRITERIA_LEN = 257 ' 255 or less works, 256 throws error


    Dim ws As Worksheet: Set ws = ActiveSheet
    Dim filtRng As Range: Set filtRng = ws.Range(ws.Cells(1, 1), ws.Cells(5, 1))
    Dim s100 As String: s100 = "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
    Const PREFIX_LEN = 2 ' the length of the "=X" prefix in Criteria1(i)
    Dim longStr As String: longStr = Mid(s100 & s100 & s100, 1, CRITERIA_LEN - PREFIX_LEN)

    ws.Cells(1, 1).Value2 = "header"
    ws.Cells(2, 1).Value2 = "A" & longStr
    ws.Cells(3, 1).Value2 = "B" & longStr
    ws.Cells(4, 1).Value2 = "C" & longStr
    ws.Cells(5, 1).Value2 = "another value"
    If Not ws.AutoFilterMode Then
        filtRng.AutoFilter
    End If




    SET_BREAKPOINT_HERE = 1
    ' after hitting the breakpoint use the autofilter to select the three long values by typing '123' into the autofilter search




    Dim fs As Filters: Set fs = ws.AutoFilter.Filters
    If Not fs.Item(1).On Then Exit Sub
    Debug.Print "Operator = " & fs.Item(1).Operator ' should be xlFilterValues (7)
    Debug.Print "Len(.Criteria1(1)) = " & Len(fs.Item(1).Criteria1(1)) ' this is never larger than 256
    Debug.Print "Len(.Criteria1(2)) = " & Len(fs.Item(1).Criteria1(2))
    Debug.Print "Len(.Criteria1(3)) = " & Len(fs.Item(1).Criteria1(3))

    ' Save the filter
    Dim crit As Variant
    crit = fs.Item(1).Criteria1
    'crit = Array("=A" & longStr, "=B" & longStr, "=C" & longStr)   ' This line has the same effect

    ws.AutoFilter.ShowAllData ' reset the filter

    ' Try to restore
    filtRng.AutoFilter Field:=1, _
        Criteria1:=crit, _
        Operator:=xlFilterValues
    ' => Run-time error '13'       Type Mismatch
End Sub

【问题讨论】:

有趣的事实:我使用的是 Excel 2016(桌面)。运行宏后(没有更改),没有错误。但是,过滤器过滤掉了所有内容——不仅仅是原来的过滤行——所以不再有任何可见的数据。 @Mistella,感谢您的关注!只是为了确认一下,调试输出中有 Operator=7, Len(Criteria1(1/2/3))=256 吗? 是的。它是。我发现有趣的是结果的不同,因为(如果我理解正确的话)你得到一个运行时错误并且宏从未完成。虽然对我来说,宏已完成并过滤,但由于条件与任何“数据”都不匹配,因此这些行都不可见。 @Mistella,对。因此,我们都看到标准在读取时被截断(使工作变得不愉快),但尝试过滤长字符串对我们来说表现不同。我刚刚发现我的 Excel 版本已经快一年了,如果我用不同的版本得到不同的结果,我会更新这个问题。再次感谢! Excel 2016 (Desktop) 代码运行和过滤结果是 3* len 256 & 1* "another value" 的字符串。不得不注释掉 SET_BREAKPOINT_HERE = 1 所以不知道我是否遗漏了什么。 【参考方案1】:

我今天也遇到了这个问题。真的很不幸,这有这个限制。我认为我们能做的最好的事情就是以下。

Function MakeValid(ByVal sSearchTerm as string) as string
  if len(sSearchTerm) > 255 then
    MakeValid = Left(sSearchTerm,254) & "*"
  else
    MakeValid = sSearchTerm
  end if
End Function
Sub Test()
  ActiveSheet.ListObjects("Table1").Range.AutoFilter Field:=1, Criteria1:= MakeValid(sSearchTerm), Operator:=Excel.XlAutoFilterOperator.xlFilterValues
End Sub

最终,它的工作方式是通过使用模式搜索绕过问题(因此匹配前 253 个字符,然后从那里搜索任何模式)。这并不总是奏效,事实上它在某些时候肯定不会奏效,但似乎这是我们拥有的最佳选择(除了围绕这个问题设计我们的系统)

似乎这也适用于数组:

Function MakeValid(ByVal sSearchTerm as string) as string
  if len(sSearchTerm) > 255 then
    MakeValid = Left(sSearchTerm,254) & "*"
  else
    MakeValid = sSearchTerm
  end if
End Function
Sub Test()
  Dim i as long
  for i = lbound(sSearchTerms) to ubound(sSearchTerms)
    sSearchTerms(i) = MakeValid(sSearchTerms(i))
  next

  ActiveSheet.ListObjects("Table1").Range.AutoFilter Field:=1, Criteria1:= sSearchTerms, Operator:=Excel.XlAutoFilterOperator.xlFilterValues
End Sub

这是一个糟糕的解决方案,但它有点工作

【讨论】:

对我来说,仅当Criteria1 是长度Criteria1:=Array("=foo*", "=bar*", "=baz*") 不会为我选择“foo123”...跨度> @Nickolay 感谢您提出这个问题。我会检查一下,因为我也担心可能是这种情况,但没有完全测试。

以上是关于使用 xlFilterValues 恢复自动筛选会引发错误 13 如果 Len(Criteria1(i))>255 类型不匹配?的主要内容,如果未能解决你的问题,请参考以下文章

PHP 通过按特定字段筛选从数据库中恢复字段

通过按特定字段筛选,从数据库中恢复字段

r语言lasso回归变量怎么筛选

Excel VBA自动筛选器会继续删除与条件不匹配的数据

VBA 宏搜索自动筛选

自动化测试