Declare a 0-Length String Array in VBA - Impossible?

前端 未结 3 557
旧巷少年郎
旧巷少年郎 2021-01-12 21:31

Is it really not possible to declare a 0-length array in VBA? If I try this:

Dim lStringArr(-1) As String

I get a compile error saying rang

3条回答
  •  忘掉有多难
    2021-01-12 21:48

    As noted in the comments, you can do this "natively" by calling Split on a vbNullString, as documented here:

    expression - Required. String expression containing substrings and delimiters. If expression is a zero-length string(""), Split returns an empty array, that is, an array with no elements and no data.

    If you need a more general solution (i.e., other data types, you can call the SafeArrayRedim function in oleaut32.dll directly and request that it re-dimensions the passed array to 0 elements. You do have to jump through a couple of hoops to get the base address of the array (this is due to a quirk of the VarPtr function).

    In the module declarations section:

    'Headers
    Private Type SafeBound
        cElements As Long
        lLbound As Long
    End Type
    
    Private Const VT_BY_REF = &H4000&
    Private Const PVDATA_OFFSET = 8
    
    Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias _
        "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, _
        ByVal length As Long)
    
    Private Declare Sub SafeArrayRedim Lib "oleaut32" (ByVal psa As LongPtr, _
        ByRef rgsabound As SafeBound)
    

    The procedure - pass it an initialized array (any type) and it will remove all elements from it:

    Private Sub EmptyArray(ByRef vbArray As Variant)
        Dim vtype As Integer
        CopyMemory vtype, vbArray, LenB(vtype)
        Dim lp As LongPtr
        CopyMemory lp, ByVal VarPtr(vbArray) + PVDATA_OFFSET, LenB(lp)
        If Not (vtype And VT_BY_REF) Then
            CopyMemory lp, ByVal lp, LenB(lp)
            Dim bound As SafeBound
            SafeArrayRedim lp, bound
        End If
    End Sub
    

    Sample usage:

    Private Sub Testing()
        Dim test() As Long
        ReDim test(0)
        EmptyArray test
        Debug.Print LBound(test)    '0
        Debug.Print UBound(test)    '-1
    End Sub
    

提交回复
热议问题