MS Office Forum

Ask Question   UnAnswered
Home » Forum » MS Office       RSS Feeds

Fundamental Q: passing/returning variables

  Asked By: Pamela    Date: Mar 02    Category: MS Office    Views: 862

Actually just returning variables...and declaring variables in a sub
statement. It appears that the two ways to get variables *out of* a
sub is with a global/Public variable, or through a spreadsheet cell,
but not through the argument list. At least not like I've seen in
the past (a limited view)

I'm doing serial I/O, and successfully, I might add (I got the
working code elsewhere and am adding features).

In this line of code which gets status of a port (never called in the
original code I got):

Public Sub StatComPort(lPortHandle As Long,_
lRxBuffer As Long, lTxBuffer As Long)

... this appears to be a way of passing variables back "up" to the
calling routine. Here's what appears to be true.

As it is used, 'lPortHandle' is defined (in an OpenPort sub) and
passed here by the calling routine, but the other two are not defined
elsewhere outside this sub (they appear nowhere else, but in this
sub. Not even in a Dim). However I WANT THEM!

The following has to be the case...

Are the variables 'lRxBuffer' and 'lTxBuffer' being declared
here? [[ If so, does this style of declaration have a name like
included or intrinsic declaration or something? ]]

Is the "Public" declaration for the sub, at the same time, making
these *variables* also public/global?

Is it equivalent to putting:

Dim lRxBuffer, lTxBuffer As Long
in a public procedure...
Public Dim lRxBuffer, lTxBuffer As Long
in the right place...

Then starting the sub with:

Public Sub StatComPort(lPortHandle As Long,_
lRxBuffer, lTxBuffer)

instead of the way it was ?



11 Answers Found

Answer #1    Answered By: Angel Watkins     Answered On: Mar 02

These variables  are being declared here, and have scope only within the

They are built to pass arguments into the sub alone and if you want to
keep them globally, it's best to just pass global values to them. Let me
give you a little analogy in code:

----start of module
Global str_gl_Colour as String
Global str_gl_Animal as String
Global str_gl_Sentence as String
Sub CallString
str_gl_Colour = "Yellow"
str_gl_Animal = "Dog"
MakeString(str_gl_Colour, str_gl_Animal)
End Sub
Public Sub MakeString(myColour, myAnimal)
str_gl_Sentence = "I would love to own a " & myColour & " " & myAnimal
End Sub
----end of module

Answer #2    Answered By: Burkett Bernard     Answered On: Mar 02

which this wasn't and I don't have a problem with, and Greg gave TOO
much information. Yikes! I'm not familiar with all that, so it's
lost on me.
Let's try this.
Method, Object and talk like that makes my brain start to glow as a
result of all the thinking to convert into something I can get my
arms around.

Now, I do know about and the difference between Functions and
Procedures and Sub(routines) generally speaking. And I do know that,
in general, there can/may be several ways to pass parameters in
higher level languages.

My question is only about _returning_ variables  _from_ a Sub for use
in the _calling_ Sub.
SO… in VBA, if I call a sub, how can I gat a variable  OUT OF that
sub, not into? Let's try Ray's code. Look here '****

----start of module
Global str_gl_Colour as String
Global str_gl_Animal as String
Global str_gl_Sentence as String
Sub CallString
str_gl_Colour = "Yellow"
str_gl_Animal = "Dog"
MakeString(str_gl_Colour, str_gl_Animal)
'**** Right here. How can I get
'**** the value of str_gl_Sentence
'**** Perhaps to do this:
Debug.Print str_gl_Sentence
End Sub
Public Sub MakeString(myColour, myAnimal)
str_gl_Sentence = "I would love to own a " & myColour & " " & myAnimal
End Sub
----end of module

SO, Is a Global (I thought it was called  "Public" in VB) the ONLY

Part of the confusion on my part is that I seem to remember that in
some long past  language, (??? Fortran perhaps ??) you put _returned_
variables in the same variable list  at the beginning of the sub, as
the passed variables. I keep wanting to have my returned variable in
that list at the start of the sub. Like this:
Dims here or wherever they're needed.
Sub StartHere
A = 4
B = 2
Call DoSomething(A, B, C)
Answer = C ' where Answer now contains 8
End Sub

Sub DoSomething(X, Y, Z)
Z = X * Y
End Sub
A and B are passed TO and C is returned from, or am I in on the wrong

Aside from using a spreadsheet  cell, do I hafta' make C global and
just do this:
Public C As…
. . .
Call DoSomething(A, B)
Answer = C ' where Answer now contains 8
End Sub

Sub DoSomething(X, Y)
Private X, Y As. . . ' This may be wrong, but just to show that they
C = X * Y
End Sub

Answer #3    Answered By: Perdita Lopez     Answered On: Mar 02

PMFJI & FWIW... If I understand what you are saying, I actually do
this fairly regularly though I don't think it's regarded as "kosher"

If I need to get a variable  out of a sub call and I don't want to use
a global, I include the variable in the call and update it. This
sometimes means I include a dummy variable in the call.

say I want a sub that "returns" an array from a string... which I have
done and know works. I call the sub so

subReturnArray slString,slArray

The sub splits the string with SPLIT say and then massages the result,
redims the given array slArray, fills it and closes down.

The array slArray is "passed back" to the calling  routine.

It's all to do with what Greg said but the default is ByVal which
should be what you want.

If you want some specific code  I can send you some.

Answer #4    Answered By: Faith Hughes     Answered On: Mar 02

And that could be built as an example of passing  an argument
ByRef so that only a single memory location would be modified instead.

Answer #5    Answered By: Dinh Tran     Answered On: Mar 02

It appears that you can
actually define a variable  (allocate space for the variable and
assign a symbol) in the sub entry line. The "dummy" variable doesn't
have to be defined  in a DIM in the *calling* routine.

Answer #6    Answered By: Ann Evans     Answered On: Mar 02

It has to be defined  *somewhere*. Here is the "sequence"...

' ------------------------------------
sub Main()

dim LocalToMainParameter1
dim LocalToMainParameter2

subToCall LocalToMainParameter1, LocalToMainParameter2

MsgBox LocalToMainParameter2

end sub
' ------------------------------------
sub subToCall(LocalToSubParameter1, LocalToSubParameter2)

' Do stuff to initialise and set LocalToSubParameter2
' according to LocalToSubParameter1.

end sub
' ------------------------------------

In this, and leaving out the details though, FOUR variables  are
defined. The 2 for Main() are Local to that procedure only and are
passed to subToCall which instantiates another TWO. The VALUES of the
varaibles are passed here. After setting up the 2nd variable  the sub
stops. The VALUE of LocalToSubParameter2 is then passed back  to
LocalToMainParameter2 and I've used  MsgBox to display it with nods to
Greg about Debug.Print :-) As Greg says you can set things up to save
a bit of space and processing by just passing  the address of the first

When subToCall stops competely it hands anything it's used back to the
system and the LocalToMainParameter1 and LocalToMainParameter2 are no
more... they go to meet their maker... dead... deceased... definately
not just sleeping or resting with their eyes closed.

If you want a full code  example just shout and I'll try and do one...
that may take a bit though but I have no problems with you asking.

Answer #7    Answered By: Dan Romero     Answered On: Mar 02

I will search again, but I am certain that the code  I am starting
with and trying to understand does not have anything equivalent to
your line  below that I marked with **** -- no declaration/dim in the
main routine

The only places I can find the variable  in question are marked below
by $$$$$$ -- except all places where $$$$ appears is the SAME
symbol, not two different ones as you show.

I changed the variable names below to represent what I have (that is
working). My original post has the code as well.

It appears that this is an "Implicit" way to *both* define a
global/Public variable AND pass it by reference (address) - *in* the
sub entry point. There is a type declaration in the sub entry
statement as I show.

I am still a little shaky on the definitions of "By Ref" and "By
Value" If I think hard...
By Ref="Here's the address, go ahead and muck about with my variable".
By Value = "Here's my value (a copy). You know what it is, but I'll
keep my variable intact.

Answer #8    Answered By: Clint Garcia     Answered On: Mar 02

I entered the ** and $$ comments into *YOUR*
code at the bottom of the post (your previous). They show up there
on eh Web.
And I re-verified that the variable  is not defined  in a DIM, yet it
appears to act global.

Answer #9    Answered By: Wilfred Young     Answered On: Mar 02

Do you use Option Explicit at the top of your module?

VBA will automaticly instantiate a variable  type=variant for you if
you leave out the Dim. When you 'compile' though, if Option Explicit
is there it will tell you that the variable isn't defined... hasn't
got a Dim... otherwise it just goes ahead and works with the variant.

Answer #10    Answered By: William Bouchard     Answered On: Mar 02

Option Explicit is at the top of the comm module where the code
appears (as well as others) but not all modules.

On the "auto Variant" vs. Dim error, neither happens. This module
has Option Explicit in the Definitions and if I run the Sub, the vars
what are on the left of an = sigh, always =0 -- no error. Wierd. I
asked serial  I/O questions on code  Guru and wrox.......

So... Option Explicit forces definitions in the current module only...

Answer #11    Answered By: Jean Bell     Answered On: Mar 02

That structure is pretty common as a ByRef value return of a function. As
you know, functions are unique in that they return a result. In other
languages, there is no such thing as a subroutine as all code  structures
return a result. The particular routine  declaration you're referring to is
bubbling up an internal result and that is common for DLLs to do
(including API references).

The Public declaration in this case also makes the call possible from
outside the DLL itself. This is often called  an Export from the DLL. It
may have other internal calls defined  as Private and these won't be
accessible from external applications.

http://support.microsoft.com/kb/142840/EN-US/ might be helpful because it
explains what VB expects to work with when a DLL exports a function. And
I'm betting you're already aware of this end-to-end tutorial about writing
VB code to control hardware but I'll add  it anyway:
http://www.boondog.com/%5Ctutorials%5Cdlltutor%5Cdlltutor.htm. Also, here
is one of my favorites because it comes as close to how I learned as
anything I've seen: http://www.thevbzone.com/secrets.htm

And from all that, here's a basic rule set to have in mind about returned
values, etc. DLL exports require a single method for accessing them and
that is the use of a Private Declaration pointing directly to the DLL. The
behavior of such a call is similar to that of referencing a COM object (by
far, the most common way of accessing an export within VB). When a ByRef
variable is passed or retrieved, what is really happening is the exchange
of a pointer to a location in memory where the calling  App and the called
DLL store information. This location is passed back  and forth By Reference
to that location.

When a ByVal variable  is used, the caller and called don't share the
location in memory. Instead, the called DLL gets the value it stored in
memory and passes the result back to the caller. This means, of course,
that only one of the partners in this relationship can change what's in
that memory location.

Didn't find what you were looking for? Find more on Fundamental Q: passing/returning variables Or get search suggestion and latest updates.