我继承了一些在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
答案 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
这是一个很糟糕的解决方案,但是可以解决问题