Can you set a value to a variable outside a sub? (1 Viewer)

Zak14

Registered User.
Local time
Today, 08:04
Joined
Jun 27, 2014
Messages
166
If I set a variable inside of a subroutine, it is set to nothing upon the end of the sub.
Can I set a variable outside a sub and set its value, so that you can use it within subs?
I'm new to coding.
 
Last edited:

pbaldy

Wino Moderator
Staff member
Local time
Today, 00:04
Joined
Aug 30, 2003
Messages
36,125
Declare it at the top of a form/report module for use anywhere within that form/report, in a standard module for use anywhere in the app.
 

Zak14

Registered User.
Local time
Today, 08:04
Joined
Jun 27, 2014
Messages
166
You can declare it, but can you set a value to it?
I ask this because I watched a video once where it said you can declare it but not set its value.
 

pbaldy

Wino Moderator
Staff member
Local time
Today, 00:04
Joined
Aug 30, 2003
Messages
36,125
Yes of course. Wouldn't be much use if you couldn't set the value. Perhaps you're thinking of a constant.
 

Zak14

Registered User.
Local time
Today, 08:04
Joined
Jun 27, 2014
Messages
166
Let me quote the section of the tutorial:

One thing you can't do, is assign a value to a global variable in the declaration section

And then, an example is shown.
This is typed in above the first subroutine:
Code:
Dim dblRate As Double
dblRate = 0.03

And then, when one of the code modules was run, a message box displays:
"Compile error: Invalid outside procedure."
 
Last edited:

pbaldy

Wino Moderator
Staff member
Local time
Today, 00:04
Joined
Aug 30, 2003
Messages
36,125
The dim would be at the top, the assignment would be in a procedure. If you want a fixed value, use a constant.
 

Zak14

Registered User.
Local time
Today, 08:04
Joined
Jun 27, 2014
Messages
166
Thanks, I'll have a look at what constants are.
 

pbaldy

Wino Moderator
Staff member
Local time
Today, 00:04
Joined
Aug 30, 2003
Messages
36,125
I have an app open that has a few. This type of thing in a standard module:

Public Const g_sDriverInfoPW As String = "password"
 

gemma-the-husky

Super Moderator
Staff member
Local time
Today, 08:04
Joined
Sep 12, 2006
Messages
15,651
note that when using variables within subs, it is better/clearer to pass the argument into the sub

so

declarations
dim myvar as string
myvar = "test"

[call] testvar1

this works
sub testvar1
msgbox(myvar)
end sub



and this works
[call] testvar2(myvar)

sub testvar2(arg as string)
'the variable myvar is now aliased as arg within the sub
msgbox(arg)
end sub


the latter usage is possibly better, as it makes the use of the variables easier to follow, and makes the code blocks more reuseable.

slight variantion
sub testvar2(byref arg as string)
sub testvar2(byval arg as string)

in the former of these two (byref - which is the default), if you change arg in the sub, the orginal value of arg changes. In the latter, arg is a temporary value, and changes are not retained after the sub ends. Personally, I think byval is better and safer, and a lot of languages have byval as the default. Note that some (complex) argument types are actually passed byref irrespective of whether you use byref or byval.
 
Last edited:

vbaInet

AWF VIP
Local time
Today, 08:04
Joined
Jan 22, 2010
Messages
26,374
ByVal isn't necessarily safer than ByRef. It's down to the developer to know which one applies to the situation. A developer should know what the default is and should know the effects of both as you've just briefly explained.

Post #5 indicates that the poster wants a constant value to which pbaldy rightly replied that a Constant is the way to go and I'm of the same opinion. In addition, if the rates are going to vary then perhaps the poster wants to save these values in a table.
 

Mile-O

Back once again...
Local time
Today, 08:04
Joined
Dec 10, 2002
Messages
11,316
If I set a variable inside of a subroutine, it is set to nothing upon the end of the sub.
Can I set a variable outside a sub and set its value, so that you can use it within subs?

One thing not mentioned yet is the ability to dimension a static variable inside a subroutine or function. This will retain the value after the routine or function has ended. It is still only usable within that subroutine or function's scope.

Code:
Static MyVar As Long
 

rsACC99

New member
Local time
Today, 01:04
Joined
Feb 3, 2011
Messages
4
I have never been able to declare a Public Variable that is available to another module. The instructions seem simple: use the word 'Public' and and put the declaration in the Declaration section, but I always get the 'Variable Not Defined' error

Questions:

Is the Declaration section the part at the top that says:
'Option Compare Database 'Use database order for string comparisons
Option Explicit' ?

Should the declaration precede the above or follow?

Can you declare a Public in a form module and have it be available to modules not associated with a specific form and vice versa? I group various functions that multiple forms use in a section that VBA Project Explorer calls 'Modules'

Is there some Access setting that I need to change?

Thanks for any suggestions
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 02:04
Joined
Feb 28, 2001
Messages
27,167
First, you must declare public things in General Modules in order to have them visible in a true sense of the word "public." The declaration area is that part that sits between the phrases "Option Compare Database" and "Option Explicit." In a class module, you can say it is public, but it really isn't public.

I just use Dim Public Constant 12345 as Long (or some similar syntax).

Second, in a class module definition, your issue is that the class dissolves when the associated object (form, report) closes. A static definition in a class module might persist but its definition is part of (a property of) the class module; those properties and definitions are not visible unless the class object is open.

Third, you CAN do a declaration of a public constant - but you CANNOT (DARE NOT) reference it with ByRef - because (if I remember this correctly) it is in a protected section of memory that cannot be modified. It is not that you modify it, but that you attempt to access it by a method that COULD modify it.

OK, it has been a while and this might have changed since the last time I tried this, but I recall something like a memory access violation being associated with a ByRef on a declared global constant. On the other hand, I haven't tried this since Access version 2 (yes, before they started calling it Acc95, Acc97, etc. etc.)

The syntax for ByVal makes a copy of the referenced object and that is up to you to diddle as you wish. Therefore, ByVal of a declared constant is not a problem.

I have never had problems in modifying the contents of a public variable declared in a general module. The updated value persists across all forms and reports that correctly reference the object by its public name. Warning, though... if you want to keep your program clean, don't duplicate names between two different general modules. Otherwise you will have to remember to qualify the reference - as ModuleA.Myname vs. ModuleB.Myname - and you use "." syntax because in that context, variables are PROPERTIES of the module and the "." is property syntax.
 

rsACC99

New member
Local time
Today, 01:04
Joined
Feb 3, 2011
Messages
4
Thanks for this clear info. I think I've got this working now.
 

gemma-the-husky

Super Moderator
Staff member
Local time
Today, 08:04
Joined
Sep 12, 2006
Messages
15,651
module1
'declarations
dim var1 as string 'private to module1
const con1 = 12 'private to module1
public var2 as string ' public throughout your app
public const con2 = 25 'public throughout your app

module2
'declarations
dim var1 as string 'legal
const con1 = 12 'legal
public var2 as string 'error - already declared in module1
public const con2 = 25 'error - already declared in module1

form module2
'declarations
dim var1 as string 'legal
const con1 = 12 'legal
public var2 as string 'error - already declared in module1
public const con2 = 25 'error - already declared in module1


note: the same variable names can be dimmed inside the modules, but not made public, as you then have duplicate declarations. because of the possibility of the same name being used for multiple declarations, you need to be careful that when you refer to a variable, you are aware of the scope of the variable

hence this usage

Code:
 function myfunc(variable1 as long)
 ...
 ...
 end function
  
 call myfunc(var1)
is always better, as the function myfunc is clearly using the variable "variable1", and there can be no side effects caused by addressing the "wrong" variable within myfunc. The aim is to make myfunc a "black-box", that doesn't need to know anything about your app - just the values that are passed in to it, thereby making it reusable in other applications.


so for instance I have a function that writes a log file

Code:
function writelog(logfile as string, loginfo as string, optional openlog as Boolean=false) as Boolean
...
...
'return true or false for success/failure of the log
end function

the function writes the string loginfo into the named logfile, and immediately opens it for viewing if the openlog argument is set to true. the app does not need to know how this is achieved, and the function does not need to use any variables with scope outside of itself.
 
Last edited:

Users who are viewing this thread

Top Bottom