I realized that my original answer could be simplified, not VARIANT and SAFEARRAY , which are defined as VBA types, all that is needed is a few CopyMemory to get pointers and finally the result of Integer.
Here is the simplest full GetDims that checks dimensions directly through variables in memory:
Option Explicit Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByVal Destination As Long, ByVal Source As Long, ByVal Length As Integer) 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 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 not an array... Type mismatch maybe? End If End Function
Blackhawk Oct 24 '14 at 20:35 2014-10-24 20:35
source share