programing

어레이 길이를 가져오시겠습니까?

sourcejob 2023. 4. 9. 21:26
반응형

어레이 길이를 가져오시겠습니까?

어레이 길이를 확인하려고 하는데 계속 다음 오류가 나타납니다.

필요한 객체

내가 뭘 잘못하고 있나요?

Dim columns As Variant
columns = Array( _
"A", "ID", _
"D", "Name")
Debug.Print columns.Length  ' Error: Object required

어레이 길이:

UBound(columns)-LBound(columns)+1

UBoundVBA의 어레이는 다른 인덱스에서 시작할 수 있기 때문에 모든 어레이의 길이를 취득하는 최선의 방법은 아닙니다.Dim arr(2 to 10)

UBound는 어레이가 1 베이스일 경우에만 올바른 결과를 반환합니다(예:1의 인덱스). Dim arr(1 to 10)다른 상황에서는 잘못된 결과가 반환됩니다. Dim arr(10)

VBA 어레이에 대한 자세한 내용은 이 VBA 어레이 튜토리얼을 참조하십시오.

기능.

Public Function ArrayLen(arr As Variant) As Integer
    ArrayLen = UBound(arr) - LBound(arr) + 1
End Function

사용.

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.

배리언트가 비어 있는 경우는, 에러가 발생합니다.방탄 코드는 다음과 같습니다.

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

해라CountA:

Dim myArray(1 to 10) as String
Dim arrayCount as String
arrayCount = Application.CountA(myArray)
Debug.Print arrayCount

복사/파스타 솔루션:
가장 일반적인 대답은 다음과 같습니다.

UBound(myItems) - LBound(myItems) + 1

90% 이상의 시간 동안 작동하지만 클라이언트/사용자가 실행 중일 때 나머지 10%는 계획되지 않은 심각한 오류로 인해 실패합니다.이 솔루션에서는 커버하지 않는 엣지 케이스가 다수 존재하기 때문입니다.


범용 솔루션:
아래 솔루션은 지금까지 제가 발견한 모든 엣지 케이스를 대상으로 합니다.또한 클라이언트/사용자가 실행 중일 때 발생하는 모든 런타임 장애를 제거합니다.

'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

경고:
위의 "일반적인" 솔루션은 기능하고 견고하지만 가장 뛰어난 성능은 아닙니다.차용증, 만약 누군가가 다른 사람과 함께 일하고 있다는 것을 안다면Dim strings() As String보다 구체적인 솔루션은 몇 배나 고속화할 수 있습니다.


훨씬 더 빠른 솔루션:
ArrayString아래 솔루션은 위의 "일반 솔루션"보다 몇 배나 더 빠릅니다.왜일까요?추가 명령(기본값:SIZE_NOT_ARRAY,IsArray,IsEmpty( 등) 및 그 주위의 변환.Variant로.Array상당한 비용이 드는 것 같다.제 테스트에서는 아래 솔루션이 10배 이상 빨라질 수 있습니다.

'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

다음은 작업을 수행하기 위한 완전한 도구 세트입니다.

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

초기화되지 않은 다이내믹 어레이가 있는 경우 UBound 및 LBound는 작동하지 않습니다.
해결책을 찾지 못해 오류를 해결했습니다.이제 모든 스크립트 상황에서 작동합니다.

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

언급URL : https://stackoverflow.com/questions/30574814/get-length-of-array

반응형