将数组作为要查找的参数时在 INDEX(MATCH()) 中达到的限制
Limits reached in INDEX(MATCH()) when taking array as argument to look in
我使用这个公式:
=IFERROR(IF(MATCH(transf(E7);transf(Sheet2!$C:$C648);0)>0;"YES");"no")
transf
是一个 UDF,它只是 converts/transforms 将单元格中的实际文本值转换为小写并执行其他一些操作(不是该问题的主题)。
通常情况下,如果transf(E7)
的值在构成的数组transf(Sheet2!$C:$C648)
中找到,公式returnsYES
,如果没有-no
。
UDF本身效果不错,经过多次测试。 问题是这次不行了。返回的答案是no
,不正确。这个公式失败是否与 66k+ 项的大数组有关?用作数组公式的 UDF 有哪些限制?
编辑 1
这是我的 UDF 的简化版本:
Public Function transf(ByVal vText As Variant) As Variant
Dim aText() As Variant
Dim j As Long
On Error GoTo ErrH
If TypeName(vText) = "String" Then
'...some code...
ElseIf TypeName(vText) = "Variant()" Then
'...some code...
ElseIf TypeName(vText) = "Range" Then ' <<< both instances of the UDF fall here
ReDim aText(1 To vText.Count)
For j = 1 To vText.Count
aText(j) = Trim(LCase(vText(j)))
Next
transf = Application.Transpose(aText) ' <<< this line causes an error 13
Else
transf = CVErr(xlErrValue)
End If
ErrH:
'This was created not for the current case, but the error the UDF gets has the same #
If Err.Number = 13 Then
Err.Clear
Resume Next
End If
End Function
如果您发现性能方面的任何其他缺陷,请告诉我。
编辑 2
我正在使用 Excel 2010。没有兼容模式,文件本身 - .xlsm,UDF 在 .xlam 加载项文件中。
Transpose
函数有一个限制,具体取决于您使用的 Excel 版本。在大多数情况下,它等于工作表中可能的列数——尽管在最新版本中它可能更大(我没有检查过)。
我建议您填充 aText
这样您就不必进行转置。虽然,只是为了在数组中找到一个值,您根本不必转置它。当然,您可能会对结果做其他事情。
例如:对于垂直阵列:
ReDim aText(1 To vText.Count, 1 to 1)
For j = 1 To vText.Count
aText(j,1) = Trim(LCase(vText(j)))
Next
编辑: 在与 ZygD 讨论和一些测试之后,将工作表函数应用于变量数组似乎还有另一个限制。除了上面提到的 TRANSPOSE 限制外,第一维中似乎存在 65536 个元素的大小限制,如下面的代码所示。
我们用数字填充 A:A
范围。
然后我们生成这个范围的变体数组,它要么包含整个列,要么只包含 65,536 个元素。从输出可以看出,在整列的情况下,使用Range对象为lookup_array
,宏按预期执行;但是使用变体数组作为“lookup_array”会导致错误,如果它大于 65,536 个元素。
使用INDEX函数也出现类似的错误;其他的我没有测试过。
Option Explicit
Sub Tester()
TestArr Range("A1:A65536")
TestArr Range("A1:A65537")
End Sub
Sub TestArr(R As Range)
Dim V
V = R
On Error Resume Next
Debug.Print "Array Size: " & R.Rows.Count
Debug.Print "Variant Array: " & WorksheetFunction.Index(V, 147, 1)
If Err.Number <> 0 Then
Debug.Print "Variant array: Error " & Err.Number, Err.Description
Err.Clear
End If
Debug.Print "Range Array: " & WorksheetFunction.Index(R, 147, 1)
Debug.Print vbLf
End Sub
我使用这个公式:
=IFERROR(IF(MATCH(transf(E7);transf(Sheet2!$C:$C648);0)>0;"YES");"no")
transf
是一个 UDF,它只是 converts/transforms 将单元格中的实际文本值转换为小写并执行其他一些操作(不是该问题的主题)。
通常情况下,如果transf(E7)
的值在构成的数组transf(Sheet2!$C:$C648)
中找到,公式returnsYES
,如果没有-no
。
UDF本身效果不错,经过多次测试。 问题是这次不行了。返回的答案是no
,不正确。这个公式失败是否与 66k+ 项的大数组有关?用作数组公式的 UDF 有哪些限制?
编辑 1
这是我的 UDF 的简化版本:
Public Function transf(ByVal vText As Variant) As Variant
Dim aText() As Variant
Dim j As Long
On Error GoTo ErrH
If TypeName(vText) = "String" Then
'...some code...
ElseIf TypeName(vText) = "Variant()" Then
'...some code...
ElseIf TypeName(vText) = "Range" Then ' <<< both instances of the UDF fall here
ReDim aText(1 To vText.Count)
For j = 1 To vText.Count
aText(j) = Trim(LCase(vText(j)))
Next
transf = Application.Transpose(aText) ' <<< this line causes an error 13
Else
transf = CVErr(xlErrValue)
End If
ErrH:
'This was created not for the current case, but the error the UDF gets has the same #
If Err.Number = 13 Then
Err.Clear
Resume Next
End If
End Function
如果您发现性能方面的任何其他缺陷,请告诉我。
编辑 2
我正在使用 Excel 2010。没有兼容模式,文件本身 - .xlsm,UDF 在 .xlam 加载项文件中。
Transpose
函数有一个限制,具体取决于您使用的 Excel 版本。在大多数情况下,它等于工作表中可能的列数——尽管在最新版本中它可能更大(我没有检查过)。
我建议您填充 aText
这样您就不必进行转置。虽然,只是为了在数组中找到一个值,您根本不必转置它。当然,您可能会对结果做其他事情。
例如:对于垂直阵列:
ReDim aText(1 To vText.Count, 1 to 1)
For j = 1 To vText.Count
aText(j,1) = Trim(LCase(vText(j)))
Next
编辑: 在与 ZygD 讨论和一些测试之后,将工作表函数应用于变量数组似乎还有另一个限制。除了上面提到的 TRANSPOSE 限制外,第一维中似乎存在 65536 个元素的大小限制,如下面的代码所示。
我们用数字填充 A:A
范围。
然后我们生成这个范围的变体数组,它要么包含整个列,要么只包含 65,536 个元素。从输出可以看出,在整列的情况下,使用Range对象为lookup_array
,宏按预期执行;但是使用变体数组作为“lookup_array”会导致错误,如果它大于 65,536 个元素。
使用INDEX函数也出现类似的错误;其他的我没有测试过。
Option Explicit
Sub Tester()
TestArr Range("A1:A65536")
TestArr Range("A1:A65537")
End Sub
Sub TestArr(R As Range)
Dim V
V = R
On Error Resume Next
Debug.Print "Array Size: " & R.Rows.Count
Debug.Print "Variant Array: " & WorksheetFunction.Index(V, 147, 1)
If Err.Number <> 0 Then
Debug.Print "Variant array: Error " & Err.Number, Err.Description
Err.Clear
End If
Debug.Print "Range Array: " & WorksheetFunction.Index(R, 147, 1)
Debug.Print vbLf
End Sub