Discussion:
Ubound
(too old to reply)
Billy
18 years ago
Permalink
I want to use UBound to check the upper bound of an array, so I can loop
round the array and get the information, but if the array is empty, I get an
error

"Subscript out of range"

So...bearing in mind I need to loop through the array, how do I check if the
array is populated or not. I don't reallyw ant to put an empty index in
there...kind of defetas the object of the ubound...

Thx
Jim Mack
18 years ago
Permalink
Post by Billy
I want to use UBound to check the upper bound of an array, so I can
loop round the array and get the information, but if the array is
empty, I get an error
"Subscript out of range"
So...bearing in mind I need to loop through the array, how do I check
if the array is populated or not. I don't reallyw ant to put an empty
index in there...kind of defetas the object of the ubound...
There are at least three ways of dealing with this, but the simplest and 'most VB' way is just to trap the error. Something like (air code):

On Error Resume Next
ub = UBound(Arr)
If Err.Number = (subscript error) Then
ub = -1 'whatever
End If
Err.Clear

Some folks get hung up on the 'error' part of this, but that's just semantics. Errors are information you can use.
--
Jim Mack
MicroDexterity Inc
www.microdexterity.com
Bob O`Bob
18 years ago
Permalink
Post by Jim Mack
Some folks get hung up on the 'error' part of this, but that's just semantics. Errors are information you can use.
Absolutely!


When you believe in things
that you don't understand,
then you suffer,
SUPERSTITION is to blame!

-Stevie Wonder (slightly paraphrased)


All that stuff with CopyMemory and SafeArray API calls ... yeah, it can probably
get you there, eventually ... With 10x to 50x as much code as a simple error trap.



Bob
--

Phill W.
18 years ago
Permalink
Post by Billy
I want to use UBound to check the upper bound of an array, so I can loop
round the array and get the information, but if the array is empty, I get an
error
With VB "Proper", you can cheat. When you do, say

Dim s( 10 ) as String

you actually get /eleven/ elements, numbered zero through ten.

By [Re]Dim'ing your array to zero to start with, you can add
"meaningful" elements from position 1 upwards.

Dim s() As String
ReDim s(0)

? UBound(s)
0

ReDim s(2)
s(1) = ...
s(2) = ...

? UBound(s)
2

For iSub = 1 To UBound(s)
...
Next

The fly in this particular ointment is that built-in functions like
Split() insist on using that zero-th element as part of the returned
data, which is a bit of a Pain, but you can work around it.

Failing all of that, either trap the error and deal with it, or use a
different sort of data storage.

HTH,
Phill W.
Sinna
18 years ago
Permalink
Post by Billy
I want to use UBound to check the upper bound of an array, so I can loop
round the array and get the information, but if the array is empty, I get an
error
"Subscript out of range"
So...bearing in mind I need to loop through the array, how do I check if the
array is populated or not. I don't reallyw ant to put an empty index in
there...kind of defetas the object of the ubound...
Thx
Check out
http://www.codehound.com/groups/default.asp?t=1,14,3,***@tkmsftngp07_14
but as it contains a caveat, just copy the code underneath, based on the
link mentioned and http://www.vbadvance.com/arrays.htm (down at the
moment?).

<code>
Private Const S_OK As Long = &H0
Private Const DISP_E_BADINDEX As Long = &H8002000B
Private Const E_INVALIDARG As Long = &H80070057

Private Const VT_BYREF As Integer = &H4000
Private Const VARIANT_DATA_OFFSET As Long = 8

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
Destination As Any, Source As Any, ByVal Length As Long)

Private Declare Function SafeArrayGetDim Lib "oleaut32.dll" ( _
ByVal psa As Long) As Long

Private Declare Function SafeArrayGetLBound Lib "oleaut32.dll" ( _
ByVal psa As Long, ByVal nDim As Long, ByRef plLbound As Long) As Long

Private Declare Function SafeArrayGetUBound Lib "oleaut32.dll" ( _
ByVal psa As Long, ByVal nDim As Long, ByRef plUbound As Long) As Long

'-------------------------------------------------------------------------------------------'

Public Function LBoundEx(ByRef vArray As Variant, _
Optional ByVal lDimension As Long = 1) As Long
Dim iDataType As Integer
Dim psa As Long
Dim lRetval As Long

'Make sure an array was passed in:
If IsArray(vArray) Then
'Try to get the pointer:
CopyMemory psa, ByVal VarPtr(vArray) + VARIANT_DATA_OFFSET, 4

If psa Then
'If ByRef then dereference the pointer to get the actual
"pointer:
CopyMemory iDataType, vArray, 2
If iDataType And VT_BYREF Then CopyMemory psa, ByVal psa, 4

If psa Then
'Make sure this is a valid array dimension:
If lDimension > 0 And _
lDimension <= SafeArrayGetDim(psa) Then
'Get the LBound:
lRetval = SafeArrayGetLBound( _
psa, lDimension, LBoundEx)

If lRetval <> S_OK Then LBoundEx = -1
Else
Err.Raise vbObjectError Or 10000, _
"LBoundEx", "Invalid Dimension"
End If
Else
LBoundEx = -1
End If
Else
LBoundEx = -1
End If
Else
Err.Raise vbObjectError Or 10000, "LBoundEx", "Not an array"
End If
End Function

Public Function UBoundEx(ByRef vArray As Variant, _
Optional ByVal lDimension As Long = 1) As Long
Dim iDataType As Integer
Dim psa As Long
Dim lRetval As Long

'Make sure an array was passed in:
If IsArray(vArray) Then
'Try to get the pointer:
CopyMemory psa, ByVal VarPtr(vArray) + VARIANT_DATA_OFFSET, 4

If psa Then
'If ByRef then dereference the pointer to get the actual
'pointer:
CopyMemory iDataType, vArray, 2
If iDataType And VT_BYREF Then CopyMemory psa, ByVal psa, 4

If psa Then
'Make sure this is a valid array dimension:
If lDimension > 0 And _
lDimension <= SafeArrayGetDim(psa) Then
'Get the UBound:
lRetval = SafeArrayGetUBound( _
psa, lDimension, UBoundEx)

If lRetval <> S_OK Then UBoundEx = -1
Else
Err.Raise vbObjectError Or 10000, _
"UBoundEx", "Invalid Dimension"
End If
Else
UBoundEx = -1
End If
Else
UBoundEx = -1
End If
Else
Err.Raise vbObjectError Or 10000, "UBoundEx", "Not an array"
End If
End Function
</code>

Sinna
Continue reading on narkive:
Loading...