0

I have the following VBA code.

Option Explicit Sub problem1() Dim speedmph As Double, speedkph As Double, speedfts As Double speedmph = Val(InputBox("Enter a speed (mph)")) Call convert(speedmph, speedkph, speedfts) MsgBox "The speed is " & speedkph & " km/hr and " & speedfts & "ft/s." End Sub Sub convert(speedmph, speedkph, speedfts) speedkph = speedmph * 1.609 speedfts = speedmph * 1.467 End Sub 

I've noticed that when I called the convert procedure as it is shown above, it worked. But if I tried to insert a value for speedkph (e.g. 0), the convert procedure does not override that and MsgBox prints out 0 for speedkph.

Why doesn't convert override the 0 even though it forces the variable to change in its function definition?

6
  • 1
    What kind of "placeholder" are you talking about? Commented Dec 27, 2016 at 19:29
  • Do you mean something similar to string.Format("{0}{1}", foo, bar) in .NET? Commented Dec 27, 2016 at 19:33
  • @Comintern I don't know what you mean. By placeholder, I meant instead of running Call convert(speedmph, speedkph, speedfts) I use Call convert(speedmph, 0, speedfts). Commented Dec 27, 2016 at 19:35
  • I have no idea what you mean. In that context, 0 is a number, not a variable. If you need to pass the value back by reference, speedkph is the "placeholder". Commented Dec 27, 2016 at 19:39
  • Ok I took out the word placeholder. Sorry for the confusion. Commented Dec 27, 2016 at 19:47

1 Answer 1

4

Regarding scope, the parameters for a Function or Sub only have scope within the Function or Sub that they are declared in. The same thing holds true for variables declared with the keyword Dim (or ReDim for arrays). For undeclared variables, the scope is the next highest scope if a matching identifier exists (module level private variables, then global variables). If no identifier with a greater scope exists, it is implicitly declared as a Variant in local scope. So, in this line...

Sub convert(speedmph, speedkph, speedfts) 

...the parameters speedmph, speedkph, and speedfts are all local to Sub convert (and are implicitly Variant because there aren't As statements), and in this line...

Dim speedmph As Double, speedkph As Double, speedfts As Double 

...the parameters speedmph, speedkph, and speedfts are all local to Sub problem1().


That out of the way, let's address why your MsgBox shows anything at all. The default method of passing parameters is ByRef, so if you were to actually specify all of the implicit parts of your Sub declaration, it would look like this:

Public Sub convert(ByRef speedmph As Variant, ByRef speedkph As Variant, _ ByRef speedfts As Variant) 

When you call it like this...

Call convert(speedmph, speedkph, speedfts) 

...you pass it references to the local variables speedmph, speedkph, speedfts you declared in Sub problem1(). The Sub convert assigns values to those references, but each procedure only holds it's own copy of the reference in local scope. The identifiers are completely irrelevant at this point. In fact, this works exactly the same as your sample code (only the identifiers have been changed):

Sub problem1() Dim speedmph As Double, speedkph As Double, speedfts As Double speedmph = Val(InputBox("Enter a speed (mph)")) Call convert(speedmph, speedkph, speedfts) MsgBox "The speed is " & speedkph & " km/hr and " & speedfts & "ft/s." End Sub Sub convert(foo, bar, baz) bar = foo * 1.609 baz = foo * 1.467 End Sub 

Now to answer your specific question, the reason you can't use a "placeholder" value of 0 is that 0 isn't a variable - it's a literal. When it's passed to Sub convert, the only place the reference exists is as a variable on the call stack - Sub problem1() doesn't hold a reference to it, so there's no way for Sub problem1() to tell what Sub convert does with it. The stack variable is destroyed when Sub convert returns and the call stack unwinds. Basically, passing a literal to a ByRef parameter is functionally equivalent to passing it ByVal.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the detailed response.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.