假设我有一个单维数组(为了保持简单)。有没有一种简单的方法来判断明确赋值的元素的最高索引是什么?除了循环和计数? 我知道Ubound找到了数组的最高维度,但这不是我需要的。是否有类似Ubound的东西,但它只计算数组的填充元素,或填充的最高索引?
我的数组包含字符串。 此外,如果数组是多维的,那该怎么办呢。
我在excel vba工作。
答案 0 :(得分:4)
简而言之,没有内置机制可以做到这一点,但如果你正在寻找一种方法来破解它,那么请继续阅读。
这取决于你如何填充数组。如果它是顺序的,最简单的就是有一个计数器。
如果它是随机的,那么你找到最后一个元素的确切索引会遇到更大的挑战。一个想法是从最大值开始并开始倒计时。
如果数组已初始化,则可以计算默认值并从ubound中减去。
还有其他想法,但您需要更清楚地定义问题,以便给我们更好的回答机会。最好是一个例子。
答案 1 :(得分:2)
我建议在填充数组时使用ReDim Preserve。因此,UBound将很适合你。只有多维数组中的最后一个维度可以重新调整。
答案 2 :(得分:2)
你可以倒退一个循环,直到找到第一个不空的数组元素 这相当于" last"填充元素。
Function HighestPopIdx(ByRef arr) As Long
For HighestPopIdx = UBound(arr) To LBound(arr) Step -1
If Not IsEmpty(arr(HighestPopIdx)) Then Exit Function
Next
End Function
要获取 数组中最高的填充元素 ,我会使用 For..Next
循环 { {1}} 功能。
(为了演示,这个例子过于复杂了。)
IsEmpty
...或反过来(第一个例子可能会更快,具体取决于你的情况。
除了@ jtolle' answer之外,Sub demo() '(Hit CTRL+G in the VBE to view the output in the Immediate window.)
'Make a test ARRAY of 5 elements:
Dim arr(1 To 5)
Erase arr '(just to make sure the test is starting 'fresh')
arr(1) = "X"
arr(2) = 99
arr(4) = "Y" '3 of the 5 elements have data (highest one is 4)
Dim elIdx As Long, highestPopEl As Long
For elIdx = LBound(arr) To UBound(arr)
If Not IsEmpty(arr(elIdx)) Then highestPopEl = elIdx
Next elIdx
Debug.Print "The highest populated element index is " & highestPopEl 'Returns 4
End Sub
和Count
工作表函数都不起作用:
CountA
...还有评论,显示数组&细胞范围的功能相似,但不相同:
With Application.WorksheetFunction
Debug.Print "Array WS CountA", .CountA(arr) 'returns 5 (Counts cells)
Debug.Print "Array WS Count", .Count(arr) 'returns 1 (Counts numbers)
End With
另一方面,如果我的"实际"目标是对数组中的每个元素执行某些操作,我会将 'Make a test RANGE of 5 cells
Dim rge As Range
Set rge = Range("A1:A5")
rge.Clear '(maker sure we're starting fresh)
Range("A1") = "X"
Range("A2") = 99
Range("A4") = "Y" '3 of the 5 cells have data
With Application.WorksheetFunction
Debug.Print "Range WS CountA", .CountA(rge) 'returns 3 (Counts values)
Debug.Print "Range WS Count", .Count(rge) 'returns 1 (Counts numbers)
End With
'... and the VBA [Range.Count] method behaves differently:
Debug.Print "Range VBA .Count", rge.Count 'returns 5 (Counts cells)
循环与 For..Each
函数一起使用。
IsEmpty
完成输出:
'if my actual purpose is to ***do something*** to an ARRAY...
Debug.Print: Debug.Print "Array [For..Next] :"
Dim elCnt As Long, el
For Each el In arr
If Not IsEmpty(el) Then _
elCnt = elCnt + 1: Debug.Print "#" & elCnt & ": Element value =", el
Next el ' (returns "X", 99, "Y")
'...and the identical method can be used on a RANGE of cells
Debug.Print: Debug.Print "Range [For..Next] :"
Dim clCnt As Long, cl
For Each cl In rge
If Not IsEmpty(cl) Then _
clCnt = clCnt + 1: Debug.Print "#" & clCnt & ": Cell value =", cl
Next cl ' (returns "X", 99, "Y")
End Sub
答案 3 :(得分:1)
您可以考虑使用包含数组变量的自定义类,将数据项添加到数组中的代码也会修改另一个变量以跟踪“已使用”的索引号。然后你可以包含一个函数来返回存储的“最高索引”数字。
答案 4 :(得分:-1)
2018年的注释:这在Excel 365中是错误的,在Excel 2000中可能是错误的。请参阅注释。但是我把它作为一个例子来说明如何使用VBA中的Application.WorksheetFunction()
与使用工作表中的公式完全不同。
当然,循环确实没什么问题,但是......
说你有这个:
Public Sub test()
Dim a(1 To 3)
a(1) = 1
a(2) = "stuff"
Debug.Print Application.WorksheetFunction.CountA(a)
End Sub
这将打印'2' [ *不,它会打印3
- 请参阅注释***],因为第三个元素具有默认值'空'。 (请注意,您的数组必须声明为Variant类型才能工作,但它可以包含String类型的元素。如果您的数组类型为String,则没有任何空格!)当然,这假设您知道你的所有容器都在最后,因为它只是在计算,而不是实际返回一个索引。出于同样的原因,您必须知道二维数组中值的分布才有意义。
我认为这正是您所需要的,基于您的编辑。