Ik ben op zoek naar de lengte van een array te krijgen, maar ik krijg steeds deze fout:
Object vereist
Doe ik iets verkeerd?
Dim columns As Variant
columns = Array( _
"A", "ID", _
"D", "Name")
Debug.Print columns.Length ' Error: Object required
Antwoord 1, Autoriteit 100%
lengte van een array:
UBound(columns)-LBound(columns)+1
UBound
alleen niet de beste methode om de lengte van elke reeks zoals arrays VBA kan beginnen op verschillende indices, bijvoorbeeld Dim arr(2 to 10)
UBound
zullen gewenste resultaten opgeleverd indien de array 1 gebaseerde (start indexeren 1 bijvoorbeeld Dim arr(1 to 10)
. Het verkeerd resultaten terug andere omstandigheden bijvoorbeeld Dim arr(10)
Meer over de VBa Array in deze VBa Array les .
Antwoord 2, Autoriteit 30%
Functie
Public Function ArrayLen(arr As Variant) As Integer
ArrayLen = UBound(arr) - LBound(arr) + 1
End Function
gebruik
Dim arr(1 To 3) As String ' Array starting at 1 instead of 0: nightmare fuel
Debug.Print ArrayLen(arr) ' Prints 3. Everything's going to be ok.
Antwoord 3, Autoriteit 12%
Als variant leeg wordt een fout wordt geworpen. Kogelvrij code is de volgende:
Public Function GetLength(a As Variant) As Integer
If IsEmpty(a) Then
GetLength = 0
Else
GetLength = UBound(a) - LBound(a) + 1
End If
End Function
Antwoord 4
Probeer CountA
:
Dim myArray(1 to 10) as String
Dim arrayCount as String
arrayCount = Application.CountA(myArray)
Debug.Print arrayCount
Antwoord 5
Compileer antwoorden hier en daar is hier een complete set ARA-gereedschappen om het werk te krijgen:
Function getArraySize(arr As Variant)
' returns array size for a n dimention array
' usage result(k) = size of the k-th dimension
Dim ndims As Long
Dim arrsize() As Variant
ndims = getDimensions(arr)
ReDim arrsize(ndims - 1)
For i = 1 To ndims
arrsize(i - 1) = getDimSize(arr, i)
Next i
getArraySize = arrsize
End Function
Function getDimSize(arr As Variant, dimension As Integer)
' returns size for the given dimension number
getDimSize = UBound(arr, dimension) - LBound(arr, dimension) + 1
End Function
Function getDimensions(arr As Variant) As Long
' returns number of dimension in an array (ex. sheet range = 2 dimensions)
On Error GoTo Err
Dim i As Long
Dim tmp As Long
i = 0
Do While True
i = i + 1
tmp = UBound(arr, i)
Loop
Err:
getDimensions = i - 1
End Function
Antwoord 6
Ubound en Lbound werken niet als we een niet-geïnitialiseerde dynamische array hebben.
Ik heb er geen oplossingen voor gevonden, dus heb ik de fout behandeld. Nu werkt het voor al mijn scriptsituaties:
Public Function SizeOf(arr As Variant) As Integer
On Error GoTo IsEmpty
SizeOf = UBound(arr) - LBound(arr) + 1
Exit Function
IsEmpty:
SizeOf = 0
End Function
Antwoord 7
Kopieer/pasta-oplossing:
Het meest voorkomende antwoord is dit:
UBound(myItems) - LBound(myItems) + 1
Hoewel het +90% van de tijd werkt, mislukt die andere 10% met vervelende ongeplande fouten wanneer een client/gebruiker het uitvoert. Dat komt omdat er een aantal randgevallen zijn die deze oplossing niet dekt.
Algemene oplossing:
De onderstaande oplossing omvat alle randgevallen die ik tot nu toe heb gevonden. En het elimineert alle runtime-fouten wanneer een client/gebruiker het uitvoert.
'Generic solution using Variant
Public Const SIZE_NOT_ARRAY As Long = -1
Public Const SIZE_EMPTY As Long = 0
'Return Value:
' -1 - Not an Array
' 0 - Empty
' > 0 - Defined
Public Function size( _
ByVal values As Variant _
, Optional ByVal dimensionOneBased As Long = 1 _
) As Long
Dim result As Long: result = SIZE_NOT_ARRAY 'Default to not an Array
Dim lowerBound As Long
Dim upperBound As Long
On Error GoTo NormalExit
If (IsArray(values) = True) Then
result = SIZE_EMPTY 'Move default to Empty
lowerBound = LBound(values, dimensionOneBased) 'Possibly generates error
upperBound = UBound(values, dimensionOneBased) 'Possibly generates error
If (lowerBound < upperBound) Then
result = upperBound - lowerBound + 1 'Size greater than 1
Else
If (lowerBound = upperBound) Then
result = 1 'Size equal to 1
End If
End If
End If
NormalExit:
size = result
End Function
Public Function isEmpty( _
ByVal values As Variant _
, Optional ByVal dimensionOneBased As Long = 1 _
) As Boolean
isEmpty = size(values, dimensionOneBased) = 0
End Function
Public Function isDefined( _
ByVal values As Variant _
, Optional ByVal dimensionOneBased As Long = 1 _
) As Boolean
isDefined = size(values, dimensionOneBased) > 0
End Function
Voorbehoud:
Hoewel de bovenstaande “algemene” oplossing werkt en robuust is, is deze niet de meest performante. IOW, als men weet dat men met Dim strings() As String
werkt, dan kan een meer specifieke oplossing vele malen sneller zijn.
Veel snellere oplossing:
De Array
van String
-oplossing hieronder is vele malen sneller dan de “algemene oplossing” hierboven. Waarom? Omdat de extra instructies (standaard SIZE_NOT_ARRAY
, IsArray
, IsEmpty
, etc.) en de conversies rondom van Variant
to Array
lijken aanzienlijke kosten met zich mee te brengen. Bij mijn testen kan de onderstaande oplossing meer dan 10 keer sneller zijn.
'Specifically Typed solution for String
Public Const SIZE_EMPTY As Long = 0
'Return Value:
' -1 - Not an Array
' 0 - Empty
' > 0 - Defined
Public Function size( _
ByRef r_values() As String _
, Optional ByVal dimensionOneBased As Long = 1 _
) As Long
Dim result As Long: result = SIZE_EMPTY 'Default to Empty
Dim lowerBound As Long
Dim upperBound As Long
On Error GoTo NormalExit
lowerBound = LBound(r_values, dimensionOneBased) 'Possibly generates error
upperBound = UBound(r_values, dimensionOneBased) 'Possibly generates error
If (lowerBound < upperBound) Then
result = upperBound - lowerBound + 1 'Size greater than 1
Else
If (lowerBound = upperBound) Then
result = 1 'Size equal to 1
End If
End If
NormalExit:
size = result
End Function
Public Function isEmpty( _
ByRef r_values() As String _
, Optional ByVal dimensionOneBased As Long = 1 _
) As Boolean
isEmpty = size(r_values, dimensionOneBased) = 0
End Function
Public Function isDefined( _
ByRef r_values() As String _
, Optional ByVal dimensionOneBased As Long = 1 _
) As Boolean
isDefined = size(r_values, dimensionOneBased) > 0
End Function