Does a function in VBscript take variable number of arguments? - syntax

For example, if I have a function in VBscript:
Function sum(a, b, c)
sum = a + b + c
End function
Now, in the main, I make two variables and pass them into the function sum as the following:
Dim a : a = 1
Dim b : b = 2
Call sum(a, b)
Will this work or not, and why? Thanks.

It will not work, VBScript doesn't support optional arguments.
I'd use a function that takes an array of numbers instead vary number of arguments to getting sum.
Function sum(nums)
Dim i, out
For i = 0 To UBound(nums)
out = out + nums(i)
Next
sum = out
End function
Call sum(Array(1, 2, 3, 4))

According to this, VBscript does not support optional arguments. You can do what they suggest and pass null values to your function.

I hope this might help.
I use dictionary object to pass variables to function so I can add new arguments without the need for refactoring existing code.
dim params
set params = CreateObject("Scripting.Dictionary")
'...when I want to call a function
params.add "variable_name", value: params.add "variable_name_2", value ': ...
call fn_function_name(params)
'...declaring a function
function fn_function_name(byRef params_in)
'here I usually make sure that variable is of correct type, or that is set
params_in("variable_name") = fn_check(params_in("variable_name"), "number") ' fn_check is a separate function
' ... function code goes here ...
' in order to user external dictionary "params" multiple times, I empty dictionary before exiting the function. This is possible because I set it as a reference (byRef) instead of value
params_in.removeAll()
end function

VBScript doesn't support optional arguments or method overloading. You can pass in null values to your function call, however.

Related

How to check if a value of an array is empty

I am writing a chess program and has to see whether certain value are empty. I tried
aPiece is an array of CommandButtons. cmdSquare is a control array of shapes.
Private aPiece(63) As CommandButton
...
For p = 0 To 63
If IsEmpty(aPiece(p)) Then
aPiece(p).Left = cmdSquare(p).Left
aPiece(p).Top = cmdSquare(p).Top
End If
Next p
All variable are declared and is seem to be IsEmpty function which is not working.
The IsEmpty method only returns meaningful information for variants. Since the array contains objects, you need to check like this:
If aPiece(p) Is Nothing Then
However, this seems like only part of the answer. The above logic is saying "If there is no piece in my array then update it's location". That doesn't make sense to me and will generate an error. You also need to add Not like below:
For p = 0 To 1
If Not aPiece(p) Is Nothing Then
aPiece(p).Left = cmdSquare(p).Left
aPiece(p).Top = cmdSquare(p).Top
End If
Next p
It depends on the datatype of aPiece. If it is a variant and you haven't assigned a value to it, IsEmpty will return true. However, if it is a String, Date, Integer, etc. those are automatically initialized (String will be an empty string, Integer will be 0) so IsEmpty will return false.
A pretty good reference is this page: IsEmpty Function - Visual Basic 6.0

Elegant way to pass as an optional parameter to make the subroutine work as if it was omitted?

In VB6, the function Mid(string, start, [length]) has an optional parameter length. If omitted, the whole characters after the start bound will be passed.
Say I want this default behaviour only in a certain condition:
s = Mid(s, i, IIf(condition, j, TheValue)) ' What could be TheValue?
Since length is of Variant type, I tried Empty. It didn't work. Neither did -1 and Nothing.
I didn't want to duplicate to Mid call in an If-Then-Else clause or somehow else. Is this possible?
Here is a working sample with OP's s = Mid(s, i, IIf(condition, j, TheValue)) line
Option Explicit
Property Get TheValue(Optional RetVal As Variant)
TheValue = RetVal
End Property
Private Sub Form_Load()
Dim s As String
Dim i As Long
Dim j As Long
Dim condition As Boolean
s = "test test test"
i = 6: j = 3
condition = False
s = Mid(s, i, IIf(condition, j, TheValue)) '<--- this works!
Debug.Print s
End Sub
Notice how TheValue returns a "missing" Variant i.e. one which tests positive for IsMissing and can be used in place of optional parameters instead of not passing actual argument.
No such value exists. When you omit the length parameter, the compiler chooses a different path through the VBRT -- it produces different code. If you want to emulate that, you need to do the same thing, using an If-Else or similar construct to handle the two cases, like #ÉtienneLaneville suggests
As an alternative to #Étienne's solution, VB provides the IsMissing method:
Public Function Mid(p_sString As String, p_iStart As Integer, Optional p_iLength As Integer) As String
If IsMissing(p_iLength) Then
Mid = VBA.Mid(p_sString, p_iStart)
Else
Mid = VBA.Mid(p_sString, p_iStart, p_iLength)
End If
End Function
And as this wrapper method returns a string, I suggest using the String verions of Mid, which is Mid$. The later is slightly faster than the Variant version (Mid)
This was nicely explained at this site, but at the time of this posting, the request times out. Not sure if gone forever or just a temporary problem.
You could define your own Mid function:
Public Function Mid(p_sString As String, p_iStart As Integer, Optional p_iLength As Integer = -1) As String
If p_iLength < 0 Then
Mid = VBA.Mid(p_sString, p_iStart)
Else
Mid = VBA.Mid(p_sString, p_iStart, p_iLength)
End If
End Function
This should work with the code from your question, using -1 (or any negative integer) as TheValue.
In c++, std::string these optional arguments are represented by either 0 when the default effect is zero position or length or std::string::npos when it is "infinite" length. You can explicitly supply that value and get the same behaviour.
I don't know what the equivalent constant is in m/s strings [In fact it is a different function definition, so there isn't one]. The alternative would be to pass in the string length, as that is the longest length currently possible.
The ?: ternary operator is an easy way to present 2 values with a condition to choose between them.

VB6 redim error "This array is fixed or temporarily locked"

I have a global array variable g () which starts with 3 object values.
I then call a sub that uses as input one of the items in g, and that needs to create additional items in g, plus update the item provided.
Something along the lines of
Declaration:
Public g() As branch
Initialization:
ReDim g (1 To 3)
Set g(1) = br1
Set g(2) = br2
Set g(3) = br3
Code call of sub
Call chg (g(2))
Sub
Public Sub chg (ByRef br As branch)
r = UBound(g)
ReDim g (1 To r + 2)
... (rest of the code)
End Sub
The code errors on the Redim statement, with error text "This array is fixed or temporarily locked".
Why can't I change the size of the array in this sub? What to do different?
From the MSDN documentation:
You tried to redimension a module-level dynamic array, in which one
element has been passed as an argument to a procedure. For example, in
the following code, ModArray is a dynamic, module-level array whose
forty-fifth element is being passed by reference to the Test procedure.
There is no need to pass an element of the module-level array in this
case, since it's visible within all procedures in the module. However,
if an element is passed, the array is locked to prevent a deallocation
of memory for the reference parameter within the procedure, causing
unpredictable behavior when the procedure returns.
Dim ModArray() As Integer ' Create a module-level dynamic array.
Sub AliasError()
ReDim ModArray(1 To 73) As Integer
Test ModArray(45) ' Pass an element of the module-level array to the Test procedure.
End Sub
Sub Test(SomeInt As Integer)
ReDim ModArray (1 To 40) As Integer ' Error occurs here.
End Sub
One idea would be to pass the index of the array instead of the object itself.

vbscript Type mismatch error when calling function

I am running into the Type Mismatch error when I attempt to call a function I created.
Example:
Function DoThis(paramA, paramB, paramC)
If paramA = "Something" Then
DoThis = DoSomething
ElseIf paramA = "This" Then
DoThis = DoSomethingDifferent
Else
DoThis = DoThisOtherThing
End If
End Function
Dim result: result = DoThis(valueA, ValueB, ValueC)
Can anyone see what my mistake could be? Other functions are working correctly. I have double checked the spelling by actually copying and pasting the function name where I call it. I have verified that the function name is not used anywhere else, i.e., as a constant or something else.
Note that when debugging this the ValType for all arguments is vbString. Also I am never able to enter the function, so it is not like I am debugging the function, enter it and then get the type mismatch.
ty.
VBScript has only one data type called a Variant. A Variant is a special kind of data type that can contain different kinds of information, depending on how it is used. Because Variant is the only data type in VBScript, it is also the data type returned by all functions in VBScript.
There are some subtypes of data that a Variant can contain (e.g. Empty, Null, string, integer, object, array etc.) You can use some conversion functions to convert data from one subtype to another, if that conversion is not implicit in VBScript. Now, pay your attention to real, factual data subtype of True and vbTrue.
The True keyword (boolean literal) has a value (inner representation) equal to -1.
On the other hand, vbTrue is one of few built-in constants and, in despite of it's name, has a subtype of Integer! It's one of so-called Tristate Constants:
Constant Value Description
vbUseDefault -2 Use default from computer's regional settings.
vbTrue -1 True
vbFalse 0 False
I hope next code could make clear all above statements:
Wscript.Echo _
vbTrue, CStr( vbTrue), VarType( vbTrue), TypeName( vbTrue) , _
vbNewLine, True, CStr( True), VarType( True), TypeName( True)
However, used with If _condition_ Then ..., there are some particularities; in brief:
The Then part of the If ... statement conditionally executes groups of statements only when a single test If condition is not False, i.e. any non-zero number esteems to be true, not only -1. Therefore you are able to use whatever variable or expression (numeric or string) you choose as long as the result is numeric...
Summarizing: If _expr_ Then ... is the same as
If CBool(_expr_) Then ...
The reason why retval is retuning mismatch error because it has a numeric value and an alpha value and wsh does not like that.
A sure way to get a type mismatch error for the published code is to define DoSomething etc. as Subs (which seems probable, given the names).
I cannot explain why this was a problem, but today I reduced the function down to a simple boolean return value and I still got the type mismatch error.
So I then created a new function with the same parameters and such. When I changed the call to the new function the error goes away.
My original function with the simple boolean return:(MISMATCH ERROR)
Function IsInstalledCheck(valueToCheck, expectedValue, checkType)
IsInstalledCheck = vbFalse
End Function
My new function with the a simple return:(Works)
Function IsItemInstalled(valueToCheck, expectedValue, checkType)
IsItemInstalled = vbFalse
End Function
EDIT
Note that I had tried this with the standard True / False values as well. The solution was to simply recreated the same function with a new name and for whatever magical reason that worked. The function signature was the same, the order of variables, variable names, the test conditions, everything in the body of the new function is the same.

Variable number of arguments in VB

How to create a function with variable number of arguments in visual basic?
ex.
x = Sum(1,2,3)
y = Sum(1,2)
Function Sum('how to declare argument here')
'Is there any special argument manipulation inside function before it is usable?
End Function
Have a look at Passing a Variable Number of Arguments
Function Sum(ParamArray Vals() As Variant)
Dim intLoopIndex As Integer
For intLoopIndex = 0 To UBound(Vals)
Next intLoopIndex
End Function
Use optional arguments, like:
Function Sum(Optional X1 As Integer=0, Optional X2 As Integer=0)
or universally variable arguments syntax
Function Sum(ParamArray XArr() As Variant)
(I may have messed with some syntax elements - feel free to correct.)
The answers here are great. In my application I required an arbitrarily long list of optional arguments after a required initial argument.
You can do this by simply adding the required arguments before the ParamArray entry.
For example:
Function Arithmetic(FuncType As String, ParamArray Terms() As Variant)

Resources