But I want a pure VBA solution to paste into my projects, so here is some code. We use the CopyMemory technique because this avoids using On Error Resume Next.
Option Explicit
Option Private Module
'http://stackoverflow.com/questions/24613101/vba-check-if-array-is-one-dimensional/26555865#26555865
Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByVal Destination As Long, _
ByVal Source As Long, ByVal Length As Integer)
Public Function GetDimsAndBounds(VarSafeArray As Variant) As Scripting.Dictionary
Dim dic As Scripting.Dictionary
Set dic = New Scripting.Dictionary
Dim lDims As Long
lDims = GetDims(VarSafeArray)
Dim lDimLoop As Long
For lDimLoop = 1 To lDims
ReDim bounds(0 To 1)
bounds(0) = LBound(VarSafeArray, lDimLoop)
bounds(1) = UBound(VarSafeArray, lDimLoop)
dic.Add lDimLoop, bounds
Next
Set GetDimsAndBounds = dic
End Function
Public Function GetDims(VarSafeArray As Variant) As Integer
Dim variantType As Integer
Dim pointer As Long
Dim arrayDims As Integer
CopyMemory VarPtr(variantType), VarPtr(VarSafeArray), 2& 'the first 2 bytes of the VARIANT structure contain the type
If (variantType And &H2000) > 0 Then 'Array (&H2000)
'If the Variant contains an array or ByRef array, a pointer for the SAFEARRAY or array ByRef variant is located at VarPtr(VarSafeArray) + 8
CopyMemory VarPtr(pointer), VarPtr(VarSafeArray) + 8, 4&
'If the array is ByRef, there is an additional layer of indirection through another Variant (this is what allows ByRef calls to modify the calling scope).
'Thus it must be dereferenced to get the SAFEARRAY structure
If (variantType And &H4000) > 0 Then 'ByRef (&H4000)
'dereference the pointer to pointer to get the actual pointer to the SAFEARRAY
CopyMemory VarPtr(pointer), pointer, 4&
End If
'The pointer will be 0 if the array hasn't been initialized
If Not pointer = 0 Then
'If it HAS been initialized, we can pull the number of dimensions directly from the pointer, since it's the first member in the SAFEARRAY struct
CopyMemory VarPtr(arrayDims), pointer, 2&
GetDims = arrayDims
Else
GetDims = 0 'Array not initialized
End If
Else
GetDims = 0 'It's not an array... Type mismatch maybe?
End If
End Function
No comments:
Post a Comment