Reputation:
I have a subroutine as below
Public Sub updateStagesTable(sName As String, percentageValue As Double)
stageName = "'" & sName & "'"
sSQL = "INSERT INTO StagesT ([Stage Name], [Stage Value In Percentage]) VALUES (" & stageName & "," & percentageValue & ");"
DoCmd.SetWarnings False
DoCmd.RunSQL sSQL
End Sub
and I call it from another subroutine as below
economy = 3.53
updateStagesTable ("Economy", economy)
But I get this compile error
Compile Error: expected: =
I don't understand what I am doing wrong here. Please help.
Upvotes: 19
Views: 59703
Reputation: 85
Apparently this is an area of confusion!
For one thing, wrapping the input argument in parentheses seems to work for some subroutine calls. And, furthermore, the tooltips in the VBA Editor mirror the statement defining the procedure, which includes parentheses!
So what is behind the confusion? Below is some basic code to explore this.
' Simple subroutine with two input arguments.
Sub twoInputs(in1, in2)
Debug.Print in1 & " eats "; in2 & "!"
End Sub
' Simple subroutine with one input argument.
Sub oneInput(in1)
Debug.Print in1 & " eats pizza!"
End Sub
' Routine to test various syntaxes for calling subroutines.
Sub subCallingTest()
'twoInputs("Cat", "fish") 'FAILS. Parentheses cannot be ignored here.
twoInputs "Cat", "fish" 'Works.
twoInputs ("Cat"), ("fish") 'Works, but only because parentheses can be ignored here!
Call twoInputs("Cat", "fish") 'Works.
'Call twoInputs "Cat", "fish" 'FAILS. Parentheses are required here.
oneInput "Daughter" 'Works.
oneInput ("Daughter") 'Works, but only because parentheses can be ignored here!
Call oneInput("Daughter") 'Works.
'Call oneInput "Daughter" 'FAILS. Parentheses are required here.
End Sub
It turns out that the parentheses are tolerated for a single input argument if the procedure/code only cares about the value of the inputs (see counter-example at the end), because they can be ignored in the same way as they can be when they are wrapped around individual numbers — but not when they are wrapped around several numbers.
debug.print 1 + 2 * 10 ' Answer is 21.
debug.print (1) + (2) * 10 ' Answer is 21.
debug.print (1 + 2) * 10 ' Answer is 30.
There is one very subtle clue as to when the parentheses are expected, which is in the spacing. Notice that the Editor inserts a space after the procedure's name in oneInput ("Daughter")
, but not in Call oneInput("Daughter")
.
—DIV
P.S. If a procedure has no arguments at all, then parentheses are not used to invoke it (neither with nor without the call
statement).
P.P.S. A subroutine can be guaranteed to only care about the values of the input arguments if the inputs are explicitly marked as ByVal
in the defining Sub
statement. In my examples above there is no explicit designation of the input arguments, so the arguments have defaulted to ByRef
; however, it is apparent from the above examples that the performance will nevertheless be unaffected. A simple counter-example would be as follows.
Sub oneInputMod(in1)
in1 = UCase(in1)
Debug.Print in1 & " eats pizza!"
End Sub
Sub subCallingTestMod()
person = "everyone" ' Set a local variable's value.
oneInputMod person ' Works.
Debug.Print person ' Output is "EVERYONE", as nominally intended.
person = "everyone" ' Reset a local variable's value.
oneInputMod (person) ' Seems to work, judging by immediately visible output (which was not affected by the parentheses).
Debug.Print person ' Output is "everyone", which is nominally unintended.
person = "everyone" ' Reset a local variable's value.
Call oneInputMod(person) ' Works.
Debug.Print person ' Output is "EVERYONE", as nominally intended.
End Sub
Upvotes: 2
Reputation: 271
I have never liked this peculiarity of VB so I always use the alternate CALL syntax, in your case this would be:
Call updateStagesTable("Economy", economy)
which does allow the parentheses that all other languages expect
Upvotes: 27
Reputation: 166885
updateStagesTable ("Economy", economy)
should be
updateStagesTable "Economy", economy
with no parentheses
See related: Unexpected results from typename
Upvotes: 44