Read our blogs, tips and tutorials
Try our exercises or test your skills
Watch our tutorial videos or shorts
Take a self-paced course
Read our recent newsletters
License our courseware
Book expert consultancy
Buy our publications
Get help in using our site
546 attributed reviews in the last 3 years
Refreshingly small course sizes
Outstandingly good courseware
Whizzy online classrooms
Wise Owl trainers only (no freelancers)
Almost no cancellations
We have genuine integrity
We invoice after training
Review 30+ years of Wise Owl
View our top 100 clients
Search our website
We also send out useful tips in a monthly email newsletter ...
So far in this lesson, we've declared and used variables within a single subroutine. This part of the lesson explains how to make variables available to every procedure in a single module.
You can click here to download the file for this page.
You can click here to download a file containing the completed code.
Extract and open the workbook linked to in the Files Needed section above. In the VBE you'll find a copy of the subroutine we've used in the previous parts of this lesson:
The subroutine has four variables declared within it. Note the inclusion of the Option Explicit statement at the top of the module, meaning that we must explicitly declare each variable that we want to use.
In earlier parts of this course we've created separate subroutines and called them from a main routine to break a long procedure into smaller parts. Here we'll use the same approach to create a separate subroutine to calculate the BMI for each character.
Calculating the BMI takes only the single line of code shown highlighted here.
Start by creating a new subroutine called CalculateBMI and copy and paste the line of code shown above into it:
The complete subroutine is shown here.
Now replace the original line of code in the ProcessBMIList subroutine with a call to the new subroutine:
The relevant part of the ProcessBMIList subroutine should now look like this.
Now try running the ProcessBMIList subroutine. You should immediately encounter an error message:
The error message appears as shown here. The name of the WeightKg variable will also be highlighted in the CalculateBMI subroutine.
The error message shown above indicates that the WeightKg variable has not been declared. Of course, we have declared the variable, just not in a way that allows the CalculateBMI subroutine to access it. When you declare a variable within a subroutine, it is only accessible within that subroutine. The variable's scope is said to be local to the procedure:
All four variables are declared within a single subroutine. Their scope is local to the ProcessBMIList subroutine.
One way to solve this problem is to extend the scope of the required variables so that they can be accessed by every subroutine in the module. Both the ProcessBMIList and CalculateBMI subroutines need to be able to access the WeightKg, HeightM and BMI variables. Start by cutting the Dim statements for these variables from the ProcessBMIList subroutine:
Cut the three variable declarations shown highlighted here.
Paste the cut lines of code at the top of the module below the Option Explicit statement but before the start of any subroutine:
Paste the cut lines of code and tidy up the formatting so that the top of the module looks like this.
We've now extended the scope of the three variables to the level of the module. Try running the ProcessBMIList subroutine again to show that everything works:
Click the top button on the worksheet to check that the code now works.
Module-level variables behave a little differently in the Locals Window. Try stepping through the ProcessBMIList procedure using the F8 key:
By default, the Locals Window only shows variables whose scope is local to the procedure you are currently stepping through.
You can click the + symbol shown next to the module name in the Locals Window to show variables scoped to the module:
After clicking the + symbol next to the module name, you'll see a list of module-level variables.
You may also notice that module-level variables retain the last values they contained, even when the code has stopped running. Variables with a scope that is local to a procedure will lose their values when the procedure ends.
Rather than using the Dim keyword to declare a module-level variable, you can use the Private keyword instead. This is optional but is a good way to show, at a glance, that a variable has a wider scope than a local variable in a subroutine:
The Private keyword indicates that a variable is only available to procedures within the same module.
To practise using module-level variables:
Sub CalculateBMIBand()
End Sub
Sub CalculateBMIBand()
BMIBand = Switch( _
BMI < 18.5, "Underweight", _
BMI < 25, "Healthy weight", _
BMI < 30, "Overweight", _
BMI >= 30, "Obese")
End Sub
Sub ProcessBMIList()
Dim BMIBand As String
Range("A3").Select
Do Until ActiveCell.Value = ""
WeightKg = ActiveCell.Offset(0, 1).Value
HeightM = ActiveCell.Offset(0, 2).Value
CalculateBMI
'Call the new subroutine here
CalculateBMIBand
ActiveCell.Offset(0, 3).Value = BMI
ActiveCell.Offset(0, 4).Value = BMIBand
ActiveCell.Offset(1, 0).Select
Loop
End Sub
Click OK to clear the error message.
Option Explicit
Private WeightKg As Double
Private HeightM As Double
Private BMI As Double
Dim BMIBand As String
Sub ProcessBMIList()
Option Explicit
Private WeightKg As Double
Private HeightM As Double
Private BMI As Double
Private BMIBand As String
Sub ProcessBMIList()
Click the first button on the worksheet to ensure that everything is working.
Kingsmoor House
Railway Street
GLOSSOP
SK13 2AA
Landmark Offices
99 Bishopsgate
LONDON
EC2M 3XD
Holiday Inn
25 Aytoun Street
MANCHESTER
M1 3AE
© Wise Owl Business Solutions Ltd 2024. All Rights Reserved.