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

时间:2018-04-03 15:22:43

标签: excel vba excel-vba autofilter

我继承了一些在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(已保存(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

1 个答案:

答案 0 :(得分:0)

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

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

这是一个很糟糕的解决方案,但是可以解决问题