我正在编写一个脚本,它将循环遍历 Excel 电子表格并查找所选单元格是否有重复项。如果存在重复项,则该函数将返回一个数组,其中的行是重复的,并创建一条注释来告诉我这些行。
我已经能够处理错误 0,但现在当我使用 UBound 函数检查数组中是否有元素时,出现错误 9。
如何验证整数数组是否为空?
Function IsArrayEmpty(anArray As Variant) As Boolean
Dim i As Integer
On Error Resume Next
i = UBound(anArray, 1)
Select Case (Err.Number)
Case 0
IsArrayEmpty = True
Case 9
IsArrayEmpty = True
Case Else
IsArrayEmpty = False
End Select
End Function
尝试检查空数组:
Dim arr() As String
If (Not arr) = -1 Then
Debug.Print "empty"
Else
Debug.Print "UBound is " & UBound(X)
End If
哈!
您的函数失败,因为如果
UBound()
没有引发错误(即数组已确定尺寸),则 Err.Number
为 0 并且:
Case 0
IsArrayEmpty = True
执行后返回错误结果。
最简单的方法就是捕获错误:
Function IsArrayEmpty(anArray As Variant) As Boolean
On Error GoTo IS_EMPTY
If (UBound(anArray) >= 0) Then Exit Function
IS_EMPTY:
IsArrayEmpty = True
End Function
你的数组变体是Empty还是Empty()?
'Empty' 是一个未初始化的变体:IsEmpty(myVar) 将返回 true...并且您可能会被愚弄,认为您有一个空数组(这是 'Empty()',而不是 'Empty' - 尝试跟上,在这堂课之后将会有一个简短的测试)因为 IsEmpty(myArray) 也返回 True。
Dim myVar as Variant '当前为空,Ubound 返回错误
Dim myArray() asvariant ' this is current Empty(), and Ubound returns an errorRedim myVar(0 to 0) '这不再是空的,并且有一个有效的 Ubound
Redim myArray(0 to 0) ' 这不再是空的,并且有一个有效的 Ubound
检查 myVar 的可靠方法是 TypeName(myVar) - 如果它是数组,则名称包含括号:
如果 Instr(Typename(myVar), "(") > 0 那么 '我们现在知道它是一个数组 如果不是 IsEmpty(myVar) 那么 '我们现在可以检查它的尺寸 如果 Ubound(myVar) > 0 ' 在此插入无错误的代码 万一 万一 万一
完整答案是 Excellerando 上的“检测 Excel VBA 中的数组变体”。
Chip Pearson 几年前就给出了答案,现在仍然有效。这是我的图书馆已经使用了近四年的功能。
Public Function IsArrayEmpty(arr As Variant) As Boolean
Dim lb As Long
Dim ub As Long
Err.Clear
On Error Resume Next
If IsArray(arr) = False Then
' we weren't passed an array, return True
IsArrayEmpty = True
End If
' Attempt to get the UBound of the array. If the array is
' unallocated, an error will occur.
ub = UBound(arr, 1)
If (Err.Number <> 0) Then
IsArrayEmpty = True
Else
''''''''''''''''''''''''''''''''''''''''''
' On rare occasion, under circumstances I
' cannot reliably replicate, Err.Number
' will be 0 for an unallocated, empty array.
' On these occasions, LBound is 0 and
' UBound is -1.
' To accommodate the weird behavior, test to
' see if LB > UB. If so, the array is not
' allocated.
''''''''''''''''''''''''''''''''''''''''''
Err.Clear
lb = LBound(arr)
If lb > ub Then
IsArrayEmpty = True
Else
IsArrayEmpty = False
End If
End If
Err.Clear
End Function
基本上,它检查以确保您传递了一个数组,然后尝试查找上限(如果数组为空,则会抛出错误),最后将下限与上限进行比较以确保数组确实不空。
..我仍然收到错误 #9 脚本 超出范围
如果您收到错误#9...这是否意味着您正在获取所需的信息(数组为空)?
您始终可以使用“isArray()”函数
Dim yourArray as variant
if not isArray(your_array) then
msgbox("empty")
else
msgbox("with data")
end if
您可以通过使用 JScript 的
VBArray()
对象检索总元素计数来检查数组是否为空(适用于变体类型、单维或多维数组):
Sub Test()
Dim a() As Variant
Dim b As Variant
Dim c As Long
' Uninitialized array of variant
' MsgBox UBound(a) ' gives 'Subscript out of range' error
MsgBox GetElementsCount(a) ' 0
' Variant containing an empty array
b = Array()
MsgBox GetElementsCount(b) ' 0
' Any other types, eg Long or not Variant type arrays
MsgBox GetElementsCount(c) ' -1
End Sub
Function GetElementsCount(aSample) As Long
Static oHtmlfile As Object ' instantiate once
If oHtmlfile Is Nothing Then
Set oHtmlfile = CreateObject("htmlfile")
oHtmlfile.parentWindow.execScript ("function arrlength(arr) {try {return (new VBArray(arr)).toArray().length} catch(e) {return -1}}"), "jscript"
End If
GetElementsCount = oHtmlfile.parentWindow.arrlength(aSample)
End Function
对我来说,每个元素大约需要 0.3 mksec + 15 msec 初始化,因此 10M 元素的数组大约需要 3 秒。可以通过
ScriptControl
ActiveX 实现相同的功能(它在 64 位 MS Office 版本中不可用,因此您可以使用像 this 这样的解决方法)。
UBound 和 LBound 将返回给定数组的上下边界。因此,如果 Ubound(arr) 等于 LBound(arr),则它为空。
Dim arr() As String
If UBound(arr) = LBound(arr) Or UBound(arr) <= 0 Then
Debug.Print "empty"
Else
Debug.Print "not empty"
End If
在 MS Excel(Office 365 64 位)中编写 VBA 宏时,我遇到了这个“下标超出范围”问题...
在
VarType()
调用之前添加对 UBound()
的调用解决了这个奇怪的问题:
Dim arr() As String ' Empty array - UBound() should return -1 but throws error 9 instead
Dim VT As VbVarType: VT = VarType(arr)
Dim upper_bound: upper_bound = UBound(arr)