Get lengte van de reeks?

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

UBoundalleen niet de beste methode om de lengte van elke reeks zoals arrays VBA kan beginnen op verschillende indices, bijvoorbeeld Dim arr(2 to 10)

UBoundzullen 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 Stringwerkt, dan kan een meer specifieke oplossing vele malen sneller zijn.


Veel snellere oplossing:
De Arrayvan 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 Variantto Arraylijken 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

Other episodes