Наивысший заполненный элемент массива
Вы можете шагать назад по циклу, пока не найдете первый элемент массива, который не пуст.
Это эквивалент «последнего» заполненного элемента.
Краткий ответ:
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
с IsEmpty
функция.
(Этот пример немного сложнее, ради демонстрации.)
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
... или наоборот (первый пример может быть быстрее в зависимости от вашей ситуации.
Другие примечания:
В дополнение к ответу @ jtolle , ни 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
Полный вывод:
The highest populated element index is 4.
Array WS CountA 5
Array WS Count 1
Range WS CountA 3
Range WS Count 1
Range VBA .Count 5
Array [For..Next] :
#1: Element value = X
#2: Element value = 99
#3: Element value = Y
Range [For..Next] :
#1: Cell value = X
#2: Cell value = 99
#3: Cell value = Y
Подробнее: