How to return the number of dimensions of a (Variant) variable passed to it in VBA [duplicate] How to return the number of dimensions of a (Variant) variable passed to it in VBA [duplicate] vba vba

How to return the number of dimensions of a (Variant) variable passed to it in VBA [duplicate]


Function getDimension(var As Variant) As Long    On Error GoTo Err    Dim i As Long    Dim tmp As Long    i = 0    Do While True        i = i + 1        tmp = UBound(var, i)    LoopErr:    getDimension = i - 1End Function

That's the only way I could come up with. Not pretty….

Looking at MSDN, they basically did the same.


To return the number of dimensions without swallowing errors:

#If VBA7 Then  Private Type Pointer: Value As LongPtr: End Type  Private Declare PtrSafe Sub RtlMoveMemory Lib "kernel32" (ByRef dest As Any, ByRef src As Any, ByVal Size As LongPtr)#Else  Private Type Pointer: Value As Long: End Type  Private Declare Sub RtlMoveMemory Lib "kernel32.dll" (ByRef dest As Any, ByRef src As Any, ByVal Size As Long)#End IfPrivate Type TtagVARIANT    vt As Integer    r1 As Integer    r2 As Integer    r3 As Integer    sa As PointerEnd TypePublic Function GetDims(source As Variant) As Integer    Dim va As TtagVARIANT    RtlMoveMemory va, source, LenB(va)                                            ' read tagVARIANT              '    If va.vt And &H2000 Then Else Exit Function                                   ' exit if not an array         '    If va.vt And &H4000 Then RtlMoveMemory va.sa, ByVal va.sa.Value, LenB(va.sa)  ' read by reference            '    If va.sa.Value Then RtlMoveMemory GetDims, ByVal va.sa.Value, 2               ' read cDims from tagSAFEARRAY 'End Function

Usage:

Sub Examples()    Dim list1    Debug.Print GetDims(list1)    ' >> 0  '    list1 = Array(1, 2, 3, 4)    Debug.Print GetDims(list1)    ' >> 1  '    Dim list2()    Debug.Print GetDims(list2)    ' >> 0  '    ReDim list2(2)    Debug.Print GetDims(list2)    ' >> 1  '    ReDim list2(2, 2)    Debug.Print GetDims(list2)    ' >> 2  '    Dim list3(0 To 0, 0 To 0, 0 To 0)    Debug.Print GetDims(list3)    ' >> 3  'End Sub


@cularis and @Issun have perfectly adequate answers for the exact question asked. I'm going to question your question, though. Do you really have a bunch of arrays of unknown dimension count floating around? If you're working in Excel, the only situation where this should occur is a UDF where you might get passed either a 1-D array or a 2-D array (or a non-array), but nothing else.

You should almost never have a routine that expects something arbitrary though. And thus you probably shouldn't have a general "find # of array dimensions" routine either.

So, with that in mind, here is the routines I use:

Global Const ERR_VBA_NONE& = 0Global Const ERR_VBA_SUBSCRIPT_OUT_OF_RANGE& = 9'Tests an array to see if it extends to a given dimensionPublic Function arrHasDim(arr, dimNum As Long) As Boolean    Debug.Assert IsArray(arr)    Debug.Assert dimNum > 0    'Note that it is possible for a VBA array to have no dimensions (i.e.    ''LBound' raises an error even on the first dimension). This happens    'with "unallocated" (borrowing Chip Pearson's terminology; see    'http://www.cpearson.com/excel/VBAArrays.htm) dynamic arrays -    'essentially arrays that have been declared with 'Dim arr()' but never    'sized with 'ReDim', or arrays that have been deallocated with 'Erase'.    On Error Resume Next        Dim lb As Long        lb = LBound(arr, dimNum)        'No error (0) - array has given dimension        'Subscript out of range (9) - array doesn't have given dimension        arrHasDim = (Err.Number = ERR_VBA_NONE)        Debug.Assert (Err.Number = ERR_VBA_NONE Or Err.Number = ERR_VBA_SUBSCRIPT_OUT_OF_RANGE)    On Error GoTo 0End Function'"vect" = array of one and only one dimensionPublic Function isVect(arg) As Boolean    If IsObject(arg) Then        Exit Function    End If    If Not IsArray(arg) Then        Exit Function    End If    If arrHasDim(arg, 1) Then        isVect = Not arrHasDim(arg, 2)    End IfEnd Function'"mat" = array of two and only two dimensionsPublic Function isMat(arg) As Boolean    If IsObject(arg) Then        Exit Function    End If    If Not IsArray(arg) Then        Exit Function    End If    If arrHasDim(arg, 2) Then        isMat = Not arrHasDim(arg, 3)    End IfEnd Function

Note the link to Chip Pearson's excellent web site: http://www.cpearson.com/excel/VBAArrays.htm

Also see: How do I determine if an array is initialized in VB6?. I personally don't like the undocumented behavior it relies on, and performance is rarely that important in the Excel VBA code I'm writing, but it's interesting nonetheless.