T
Terry
How can I test if array() as variant has not been dim/redim'd, eg 'empty'
I've tried a few things but not found an answer yet.
Regards
I've tried a few things but not found an answer yet.
Regards
Sergey Poberezovskiy said:You can use the following function:
Public Function IsInitialized(ByVal testArray As Variant)
As Boolean
Dim result As Boolean
On Error Resume Next
result = UBound(testArray) > -1
IsInitialized = result
End Function
HTH
like: (watch out for line wrap)Dan Artuso said:Hi,
The easiest way is to use UBound and trap the error you'll get if it
hasen't been dimensioned.
Alternatively, I found this code and did a quick test with access 97 and immediately
got a page fault. I'll post it though and you can troubleshoot it if you
(lpDest As Any, lpSource As Any, ByVal cBytes As Long)This will go in a standard module:
Option Compare Database
Option Explicit
Type SAFEARRAYBOUND
cElements As Long ' # of elements in the array dimension
lLbound As Long ' lower bounds of the array dimension
End Type
Public Type SAFEARRAY
cDims As Integer ' // Count of dimensions in this array.
fFeatures As Integer ' // Flags used by the SafeArray
' // routines documented below.
cbElements As Long ' // Size of an element of the array.
' // Does not include size of
' // pointed-to data.
cLocks As Long ' // Number of times the array has been
' // locked without corresponding unlock.
pvData As Long ' // Pointer to the data.
' Should be sized to cDims:
rgsabound() As SAFEARRAYBOUND ' // One bound for each dimension.
End Type
Const VT_BYREF = &H4000&
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory"
ArrayInfo.cDims * Len(.rgsabound(1))Public Function GetArrayInfo(TheArray As Variant, ArrayInfo As SAFEARRAY) As Boolean
Dim lp As Long, VType As Integer
If Not IsArray(TheArray) Then Exit Function
With ArrayInfo
' Get the VARTYPE value from the first 2 bytes of the VARIANT structure
CopyMemory ByVal VarPtr(VType), ByVal VarPtr(TheArray), 2
' Get the pointer to the array descriptor (SAFEARRAY structure)
' NOTE: A Variant's descriptor, padding & union take up 8 bytes.
CopyMemory ByVal VarPtr(lp), ByVal (VarPtr(TheArray) + 8), 4
' Test if lp is a pointer or a pointer to a pointer.
If (VType And VT_BYREF) <> 0 Then
' Get real pointer to the array descriptor (SAFEARRAY structure)
CopyMemory ByVal VarPtr(lp), ByVal lp, 4
End If
' Fill the SAFEARRAY structure with the array info
' NOTE: The fixed part of the SAFEARRAY structure is 16 bytes.
CopyMemory ByVal VarPtr(ArrayInfo.cDims), ByVal lp, 16
' Ensure the array has been dimensioned before getting SAFEARRAYBOUND information
If ArrayInfo.cDims > 0 Then
' Size the array to fit the # of bounds
ReDim .rgsabound(1 To .cDims)
' Fill the SAFEARRAYBOUND structure with the array info
CopyMemory ByVal VarPtr(.rgsabound(1)), ByVal lp + 16,
Terry said:How can I test if array() as variant has not been dim/redim'd, eg 'empty'
I've tried a few things but not found an answer yet.
Regards
like: (watch out for line wrap)Dan Artuso said:Hi,
The easiest way is to use UBound and trap the error you'll get if it
hasen't been dimensioned.
Alternatively, I found this code and did a quick test with access 97 and immediately
got a page fault. I'll post it though and you can troubleshoot it if you
(lpDest As Any, lpSource As Any, ByVal cBytes As Long)This will go in a standard module:
Option Compare Database
Option Explicit
Type SAFEARRAYBOUND
cElements As Long ' # of elements in the array dimension
lLbound As Long ' lower bounds of the array dimension
End Type
Public Type SAFEARRAY
cDims As Integer ' // Count of dimensions in this array.
fFeatures As Integer ' // Flags used by the SafeArray
' // routines documented below.
cbElements As Long ' // Size of an element of the array.
' // Does not include size of
' // pointed-to data.
cLocks As Long ' // Number of times the array has been
' // locked without corresponding unlock.
pvData As Long ' // Pointer to the data.
' Should be sized to cDims:
rgsabound() As SAFEARRAYBOUND ' // One bound for each dimension.
End Type
Const VT_BYREF = &H4000&
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory"
ArrayInfo.cDims * Len(.rgsabound(1))Public Function GetArrayInfo(TheArray As Variant, ArrayInfo As SAFEARRAY) As Boolean
Dim lp As Long, VType As Integer
If Not IsArray(TheArray) Then Exit Function
With ArrayInfo
' Get the VARTYPE value from the first 2 bytes of the VARIANT structure
CopyMemory ByVal VarPtr(VType), ByVal VarPtr(TheArray), 2
' Get the pointer to the array descriptor (SAFEARRAY structure)
' NOTE: A Variant's descriptor, padding & union take up 8 bytes.
CopyMemory ByVal VarPtr(lp), ByVal (VarPtr(TheArray) + 8), 4
' Test if lp is a pointer or a pointer to a pointer.
If (VType And VT_BYREF) <> 0 Then
' Get real pointer to the array descriptor (SAFEARRAY structure)
CopyMemory ByVal VarPtr(lp), ByVal lp, 4
End If
' Fill the SAFEARRAY structure with the array info
' NOTE: The fixed part of the SAFEARRAY structure is 16 bytes.
CopyMemory ByVal VarPtr(ArrayInfo.cDims), ByVal lp, 16
' Ensure the array has been dimensioned before getting SAFEARRAYBOUND information
If ArrayInfo.cDims > 0 Then
' Size the array to fit the # of bounds
ReDim .rgsabound(1 To .cDims)
' Fill the SAFEARRAYBOUND structure with the array info
CopyMemory ByVal VarPtr(.rgsabound(1)), ByVal lp + 16,