Question

Some functions such as Split() will return an array with -1 for the upper bound and zero for the lower bound if the array has no items, eg:

Dim s() As String
s = Split("", ",")
Debug.Print UBound(s)
Debug.Pring LBound(s)

In this case UBound(s) will equal -1 and LBound(s) will equal 0. I have a fair amount of code checking for -1 on the upper bound to see if the array has values or not. This works great.

The problem is that I now want to change the array data type from string to long. I cannot seem to create an array of longs with an upper bound of -1 and a lower bound of 0, and the Split() and Join() functions only operate on string arrays.

I would like to be able to return a long array with an upper bound of -1. Is this possible?

Was it helpful?

Solution

I don't think you can do it in VB6 it self. However, if you're willing to use the Windows API function SafeArrayCreateVector you can do it:

Private Declare Function LongSplitEmulator Lib "OLEAUT32.DLL" Alias "SafeArrayCreateVector" _
    (Optional ByVal vt As VbVarType = vbLong, _
     Optional ByVal low As Long = 0, _
     Optional ByVal count As Long = 0) As Long()

Dim a() As Long
a = LongSplitEmulator()
MsgBox UBound(a)

If you need to do it for other datatypes you can change the vt parameter.

Please note, I think I originally found out about this from Vi2's answer to this discussion.

OTHER TIPS

You could write your own split function to do this:

Private Sub SplitLongs(ByVal strData As String, ByRef lng() As Long)
    Dim i As Integer
    Dim s() As String
    s = Split(strData, ",")
    If UBound(s) = -1 Then
        ReDim lng(-1 To -1)
    Else
        ReDim lng(LBound(s) To UBound(s))
        For i = LBound(s) To UBound(s)
            If IsNumeric(s(i)) Then lng(i) = s(i)
        Next
    End If
End Sub

One problem with VB6 is there is no way to reliably create or detect an empty (or uninitialized) array. Sometimes, it is possible to detect an uninitialized array by checking whether the upper-bound is greater than the lower-bound; however, this is neither elegant nor documented. The best way to accomplish such a thing properly is to enclose the array in a Variant, and set the Variant to Empty to deinitialize the array. You may then use a check such as If VarType(v) = vbEmpty ...

Another way is a strongly typed "factory" function:

Private Declare Function SafeArrayRedim Lib "oleaut32.dll" (ByVal ArrayPtr As Long, ByRef DataPtr As tagSAFEARRAYBOUND) As Long

Private Type tagSAFEARRAYBOUND
  cElements As Long
  lLbound As Long
End Type

Public Type Feed
  ID As String
  Name As String
  Active As Boolean
  BasePath As String
End Type

Public Sub EmptyFeedArray(ByRef Arr() As Feed)
Dim Data As tagSAFEARRAYBOUND
Dim lngErr As Long

  'Redim to one item
  ReDim Arr(0 To 0)
  'Reset the safe array to empty
  lngErr = SafeArrayRedim(Not Not Arr, Data)
  'Raise any errors
  If lngErr <> 0 Then Err.Raise lngErr
End Sub

I think this also works with integral types.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top