Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

optional string array 1

Status
Not open for further replies.

1DMF

Programmer
Jan 18, 2005
8,795
GB
Hi,

I'm rewriting an email function to handle multiple attachements, I want to have an argument that is a string array and is optional, it will hold the full path and document names depending of if you require the email to have any attachments.

However, I am getting the following error...
Optional argument must be Variant or intrinsic type with default value

Why can I not declare it as a String, that's the data type I want?

What does 'Intrinsic Type' mean?

Why does it need a default value, I thought the whole point of declaring it as 'Optional' means it doesn't have to be provided nor given a value?

Cheers,
1DMF



"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!"

Google Rank Extractor -> Perl beta with FusionCharts
 
I do not know why, but that is the way Microsoft developed it. It probably has to with being able to determine if it isempty.
Code:
Public Sub optFunction(Optional aPaths As Variant)
  Dim aPath As Variant
  If Not IsMissing(aPaths) Then
    For Each aPath In aPaths
      Debug.Print aPath
    Next aPath
  Else
    Debug.Print "None Passed"
  End If
End Sub

Public Sub testPaths()
  Dim aPaths() As String
  aPaths = Split("a,b,cded,fghge", ",")
  optFunction aPaths
  optFunction
End Sub
 
The word intrinsic refers to the vb built in datatypes. So basically anything but users defined datatypes. So the message would be clearer if it stated

You can use optional with variant datatypes without a default value, or you can use it with other vb native datatypes if you supply a default value. You can not use it with user defined datatypes.

So with an optional array it has to be a variant I believe because there is no way to give it an optional value. Normally other datatypes you would do something like

optional str As String = ""
optional bln as boolean = False
optional num as long = 0
 
Thanks MajP.

I have found VBA arrays to be rather annoying compared to other languages!

It's crazy to have the ability to state an argument/parameter to a function as optional and then require a default value.

There seems no easy way to just define an array and then add elements to it eithe, you have to mess about with ubound and then redim and then add element explicitly with an index.

I got the function working where I have dimensioned an array with element size
Code:
Dim aFile(0 To 0) As String

Added the file string to it
Code:
aFile(0) = myString

And then in the function that I pass aFile as an argument

I just have the header declared as
Code:
optional vFile As Variant

It all seems to be working fine.

Regards,
1DMF



"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!"

Google Rank Extractor -> Perl beta with FusionCharts
 
Out of curiosity what languages allow optional parameters with no defaults? I do not code in many languages. I know in Java you can define multiple procedures/constructors with different amount of parameters. That would be nice in VB. And in C Sharp you still have to define a default.
 
Well in Java you can do what is know as 'Overloading' defining the same named function but with different parameters known as a 'method signature' but I don't you can omit any argument, if it's expected it MUST be supplied AFAIK.

The other languages comment I made was referring to the way VB handles arrays not the optional keyword.

But perl allows you to supply as many or as little arguments to a subroutine.

any argument you pass is comma separated and it is simply placed into a local @_ (array) variable.

Of course as there is no 'pop up' telling you what arguments the sub expects nor do you declare the required parameters in the method header, you need to know exactly what the sub does and what position the arguments and value types are expected.

If someone hasn't put any decent comments in the sub it can be a real pain, so I always do the following
Code:
##############################
###### SENDMAIL ROUTINE ######
##############################
# USING MIME::Lite;
sub send_mail {

#_[0] = To
#_[1] = From
#_[2] = Subject
#_[3] = Body Text
#_[4] = Filename
#_[5] = File
#_[6] = Type

So when you come back in a few months time you don't need to read the entire code to work out what arguments are being used or their position / value types.

Having said that from my Java course arrays aren't too flexible in Java either, you need to create a collection object to get the ease of using dynamic type arrays or value/pairs etc.


"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!"

Google Rank Extractor -> Perl beta with FusionCharts
 
There are a lot of user defined functions to make working with arrays a lot easier. Here are some to dynamically add an element or determine if the array is dimensioned. But google to find ones that
reorder
sort
add at specified location
erase
delete from a specified location

once you get a good library it makes working with arrays a lot easier.

Code:
Public Sub TestAddElement()
  Dim aVar() As Variant
  Dim aStr() As String
  'array not dimensioned
  aVar = AddElement(aVar, "a")
  PrintArray (aVar)
  aVar = AddElement(aVar, "b")
  PrintArray (aVar)
  aStr = Split("x,y,z", ",")
  aStr = AddElement(aStr, "w")
  PrintArray (aStr)
  
End Sub

Public Sub PrintArray(aStr As Variant)
  Dim i As Integer
  For i = LBound(aStr) To UBound(aStr)
    Debug.Print aStr(i)
  Next i
End Sub
Public Function AddElement(ByVal vArray As Variant, ByVal vElem As Variant) As Variant
      ' This function adds an element to a Variant array
      ' and returns an array with the element added to it.
      Dim vRet As Variant ' To be returned
      If IsEmpty(vArray) Or Not IsDimensioned(vArray) Then
          ' First time through, create an array of size 1.
          vRet = Array(vElem)
      Else
          vRet = vArray
          ' From then on, ReDim Preserve will work.
          ReDim Preserve vRet(UBound(vArray) + 1)
          vRet(UBound(vRet)) = vElem
      End If
      AddElement = vRet
  End Function
Public Function IsDimensioned(ByRef TheArray) As Boolean
      If IsArray(TheArray) Then ' we need to test it! otherwise will return false if not an array!
                      ' If you put extensive use to this function then you might modify
                      ' it a lil' bit so it "takes in" specific array type & you can skip IsArray
                      ' (currently you can pass any variable).
        On Error Resume Next
            IsDimensioned = ((UBound(TheArray) - LBound(TheArray)) >= 0)
        On Error GoTo 0
        'FYI: Erros are not always generated by Ubound & LBOund
        '     when array is empty (when arrays are "made" empty in some "specic way").
        '     So we cant use usual "decide" logic: bool = (err.number <> 0))
        'ie.:
        '    str = VBA.StrConv("", vbFromUnicode) 'generally you should use strconv when
        '                                          you plan converting string to bytearray,
        '                                          (here StrConv actually not needed for "",
        '                                          it's length is 0 anyway)
        '    ByteArr() = str
        '     UBound(ByteArr) => -1
        '     LBound(ByteArr) => 0
        'but:
        '    Erase ByteArr
        '     UBound(ByteArr) => Causes Error
        '     LBound(ByteArr) => Causes Error
        ' NOTE: I'm not sure, but I'm guessing (based on OnErr0r "knowledge" - > [url]http://www.xtremevbtalk.com/showthread.php?threadid=105700[/url])
        '    that "ByteArr() = str" will cause ByteArray point to SAFEARRAY in any case,
        '    even if "str" is empty while "Erase ByteArr" will remove that.
        ' QUESTION: can we make some how empty SAFEARRAYS for other types than
        '           ByteArrays as well????  I can't fiqure it out right now...
        '           Maybe doing something in low level...
    Else
        'IsDimensioned = False ' is already false by default
        Call Err.Raise(5, "IsDimensioned", "Invalid procedure call or argument. Argument is not an array!")
    End If
End Function

Public Function HasDimension(ByRef TheArray, Optional ByRef Dimension As Long = 1) As Boolean
    Dim isDim As Boolean
    Dim ErrNumb As Long
    Dim lb As Long
    Dim errDesc As String
    'HasDimension = False
    
    If (Dimension > 60) Or (Dimension < 1) Then
        Call Err.Raise(9, "HasDimension", "Subscript out of range. ""Dimension"" parameter is not in its legal borders (1 to 60)! Passed dimension value is: " & Dimension)
        Exit Function
    End If
    
    On Error Resume Next
        isDim = IsDimensioned(TheArray) 'IsArray & IsDimensioned in one call. If Err 5 will be generated if not Array
        ErrNumb = Err.Number
        If ErrNumb <> 0 Then
            errDesc = Err.Description
        End If
    On Error GoTo 0
    
    Select Case ErrNumb
        Case 0
            If isDim Then
                On Error Resume Next
                    lb = LBound(TheArray, Dimension) 'just try to retrive Lbound
                    HasDimension = (Err.Number = 0)
                On Error GoTo 0
            End If
        Case 5
            Call Err.Raise(5, "HasDimension", "Invalid procedure call or argument. Argument is not an array!")
        Case Else
            Call Err.Raise(vbObjectError + 1, "HasDimension", _
                "This is unexpected error, caused when calling ""IsDimensioned"" function!" & vbCrLf & _
                "Original error: " & ErrNumb & vbCrLf & _
                "Description:" & errDesc)
    End Select
End Function
 
I guess I need to look into finding some decent libraries.

Frameworks are something I've not really used much, it's been my Java course that exsposed me to the main concept, but java has many built into the actual language, so it's slightly different.

I get tugged between learning frameworks such as JQuery, and the problem of cargo-cult programming.

I'm always reluctant to use code I don't understand that isn't built into the standard language or API.

But as i'm learning with OO programing, you can't know everything about the underlying code, in some ways you're not meant to, just as long as you understand the object's state and protocol and how to use it to reach your particular goal.



"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!"

Google Rank Extractor -> Perl beta with FusionCharts
 
Anyway, why not simply use a ParamArray in your function ?

Hope This Helps, PH.
FAQ219-2884
FAQ181-2886
 
because i've never heard of them before.

I'll have to check it out.

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!"

Google Rank Extractor -> Perl beta with FusionCharts
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top