Call variable by string in other module - excel

I have a user form allowing users for option. The options should be saved until the excel file is closed. Before that, the options will be recorded even the user form is closed. In the user form, I have 11 checkboxes.
So I put 11 global variables under "sheet1"(renamed to DataBase) module:
Public chk1Last As Boolean
Public chk2Last As Boolean
Public chk3Last As Boolean
Public chk4Last As Boolean
Public chk5Last As Boolean
Public chk6Last As Boolean
Public chk7Last As Boolean
Public chk8Last As Boolean
Public chk9Last As Boolean
Public chk10Last As Boolean
Public chk11Last As Boolean
And I use the following code in a class to record the checkbox status to the global variable under sheet1(renamed to DataBase):
Private Sub Chk_Change()
Select Case Chk.Name
Case "chk1"
DataBase.chk1Last = Chk
Case "chk2"
DataBase.chk2Last = Chk
Case "chk3"
DataBase.chk3Last = Chk
Case "chk4"
DataBase.chk4Last = Chk
Case "chk5"
DataBase.chk5Last = Chk
Case "chk6"
DataBase.chk6Last = Chk
Case "chk7"
DataBase.chk7Last = Chk
Case "chk8"
DataBase.chk8Last = Chk
Case "chk9"
DataBase.chk9Last = Chk
Case "chk10"
DataBase.chk10Last = Chk
Case "chk11"
DataBase.chk11Last = Chk
End Select
'Do other things beneath'
And in the main module, I use the following code to initialize the user form", if the user form is first loaded, all checkboxes will be enabled, if not, the checkboxes will follow the lase status:
Private Sub UserForm_Activate()
If Not DataBase.Activated Then
For i = 1 To 11
Controls("chk" & i) = True
Next i
Else
chk1 = DataBase.chk1Last
chk2 = DataBase.chk2Last
chk3 = DataBase.chk3Last
chk4 = DataBase.chk4Last
chk5 = DataBase.chk5Last
chk6 = DataBase.chk6Last
chk7 = DataBase.chk7Last
chk8 = DataBase.chk8Last
chk9 = DataBase.chk9Last
chk10 = DataBase.chk10Last
chk11 = DataBase.chk11Last
End If
'Do other things beneath'
What I am trying to do is to simplify the code under class module something like below:
In sheet1(renamed to DataBase):
Controls("DataBase." & Chk.name & "Last") = Chk
And under main to simplify the code with for loop and controls() something like below:
Private Sub UserForm_Activate()
If Not DataBase.Activated Then
For i = 1 To 11
Controls("chk" & i) = True
Next i
Else
For i = 1 to 11
Controls("chk" & i) = Controls("DataBase.chk" & i & "Last")
Next i
End If
'Do other things beneath'
But it failed, what is the correct syntax if I want to call the variable in other modules by controls()?
Thank you very much for all of your sincere help.

Instead of
Public chk1Last As Boolean
Public chk2Last As Boolean
'etc etc
use:
Public ChkLast(1 to 11) As Boolean
Then you can address the values in the same loop as you do for the controls.
You cannot build a string to address a public variable by name. You can do certain things such as using CallByName() if your variables are properties in an instance of a class, but for cases such as yours an array makes more sense and avoids the extra complications.

Related

Error handling of multiple class attributes

I have a class that holds data in separate attributes (I chose this design instead of an array or scripting.dictionary because I will be using these data for the construction of a decision tree and I want to make use of IntelliType while I construct it.).
The data are loaded from an excel spreadsheet in the form of floats, so I am storing them in a long datatype, but from time to time it happens so that a value is missing and is replaced by an "NA" string.
I would like to create an error-handling routine, that, if a non-numeric value is encountered, would replace the content with a value -1.
I know I could do this with checking with IsNumeric() or error-handling, but I don't know how to make it work for every one of the many attributes the class holds and I don't really like the solution to write a specific error-handling code for every one of them (storing each of them in a separate attribute is not elegant as well, but I find this a price I am willing to pay for the advantage of shorter syntax in the decision tree).
Is there a way to pass a value to a variable, that just encountered a type-mismatch error, by the error-handling code independent of the variable name?
A simple example with several of the attributes:
Option Explicit
Dim B_LYM As Long
Dim B_mem As Long
Dim B_CXCR3 As Long
Dim B_CXCR4_MFI As Long
Public Sub SetData(data as Range)
On Error Goto err_handler
B_LYM = data.Cells(1, 1)
B_mem = data.Cells(1, 2)
B_CXCR3 = data.Cells(1, 3)
B_CXCR4_MFI = data.Cells(1, 4)
err_handler:
'I need something like this:
'if valuebeingstored = "NA" then targetvariable = -1
End Sub
It could be that some other approach could be better and I am gladly open to options, I only want to emphasize that I would really like make use of IntelliType when constructing the decision tree. I was considering using scripting.dictionary, but the syntax will bloat the code very quickly.
You said you have a Class and therefore could include the function to check the input and return -1 inside the class and use the Get and Let properties to call the function.
Here is an example class (named clsDataStuff) demonstrating this:
Option Explicit
Private c_B_LYM As Double
Private c_B_mem As Double
Private c_B_CXCR3 As Double
Private c_B_CXCR4_MFI As Double
Public Property Let B_LYM(varValue As Variant)
c_B_LYM = ParseDouble(varValue)
End Property
Public Property Get B_LYM()
B_LYM = c_B_LYM
End Property
Public Property Let B_mem(varValue As Variant)
c_B_mem = ParseDouble(varValue)
End Property
Public Property Get B_mem()
B_mem = c_B_mem
End Property
Public Property Let B_CXCR3(varValue As Variant)
c_B_CXCR3 = ParseDouble(varValue)
End Property
Public Property Get B_CXCR3()
B_CXCR3 = c_B_CXCR3
End Property
Public Property Let B_CXCR4_MFI(varValue As Variant)
c_B_CXCR4_MFI = ParseDouble(varValue)
End Property
Public Property Get B_CXCR4_MFI()
B_CXCR4_MFI = c_B_CXCR4_MFI
End Property
Private Function ParseDouble(varValue As Variant) As Double
If IsNumeric(varValue) Then
ParseDouble = CDbl(varValue)
Else
ParseDouble = -1
End If
End Function
Noting that:
the Let property expects a Variant because you say your input could be a number, or a string
the Get property returns Double as you said your inputs are floats so Double is better than Long
the ParseDouble function simply checks for a numeric input and returns -1 otherwise
Then, in your module code:
Option Explicit
Dim B_LYM As Long
Dim B_mem As Long
Dim B_CXCR3 As Long
Dim B_CXCR4_MFI As Long
Public Sub Test()
Dim objDataStuff As clsDataStuff
Set objDataStuff = New clsDataStuff
objDataStuff.B_LYM = 1 'data.Cells(1, 1)
objDataStuff.B_mem = 2 'data.Cells(1, 2)
objDataStuff.B_CXCR3 = "a" 'data.Cells(1, 3)
objDataStuff.B_CXCR4_MFI = True 'data.Cells(1, 4)
Debug.Print objDataStuff.B_LYM
Debug.Print objDataStuff.B_mem
Debug.Print objDataStuff.B_CXCR3
Debug.Print objDataStuff.B_CXCR4_MFI
End Sub
Returns an output of:
1
2
-1
-1
Intellisense is available and you get validation of the input:
Edit - regarding the comment on dynamically setting a target variable.
Your class can be:
Option Explicit
Public B_LYM As Double
Public B_mem As Double
Public B_CXCR3 As Double
Public B_CXCR4_MFI As Double
Public Sub SetVar(ByVal strVarName As String, ByVal varValue As Variant)
Dim dblValue As Double
Dim strToEval As String
If Not MemberExists(strVarName) Then Exit Sub
dblValue = ParseDouble(varValue) ' do the parse
CallByName Me, strVarName, VbLet, dblValue ' dynamically assign the value
End Sub
Private Function ParseDouble(varValue As Variant) As Double
If IsNumeric(varValue) Then
ParseDouble = CDbl(varValue)
Else
ParseDouble = -1
End If
End Function
Private Function MemberExists(strVarName) As Boolean
Dim blnTest As Boolean
Dim varValue As Variant
On Error GoTo ErrHandler
varValue = CallByName(Me, strVarName, VbGet)
blnTest = True
GoTo ExitFunction
ErrHandler:
blnTest = False
ExitFunction:
MemberExists = blnTest
End Function
Where:
All the variables are Public and you still get Intellisense but avoid all the repetitive Let and Get code
A single SetVar method uses CallByName to dynamically set a target variable
Two problems:
You need the clunky MemberExists function to prevent SetVar trying to assign a value to a member that does not exist - otherwise this generates an error (438) but perhaps this is something you need in your logic ?
You can still assign values to the target variable with e.g. objDataStuff.B_CXR3 = "foo" which alsos produces an error for anything other than a number.
The example code shows the problem below. But sticking with SetVar method will produce the same output as above.
Option Explicit
Dim B_LYM As Long
Dim B_mem As Long
Dim B_CXCR3 As Long
Dim B_CXCR4_MFI As Long
Public Sub Test()
Dim objDataStuff As clsDataStuff
Set objDataStuff = New clsDataStuff
objDataStuff.SetVar "B_LYM", 1
objDataStuff.SetVar "B_mem", 2
objDataStuff.SetVar "B_CXCR3", -1
objDataStuff.SetVar "B_CXCR4_MFI", True
objDataStuff.SetVar "foobar", 999
' working around SetVar here generates an error
objDataStuff.B_CXCR3 = "bad"
Debug.Print objDataStuff.B_LYM
Debug.Print objDataStuff.B_mem
Debug.Print objDataStuff.B_CXCR3
Debug.Print objDataStuff.B_CXCR4_MFI
End Sub

Dictionary compile error: method or data member not found

Not sure why getting the above error. I have a class module named clsRemit with code:
Sub clsRemit()
Public vendor As String
Public amount As Long
Public invoices As String
End Sub
Then in my module, I have:
For Each v In dictlist.Keys
If InStr(1, .Cells(q, "B").Value2, v, vbTextCompare) Then
vendor = .Cells(q, "B").Value2
If dict.Exists(vendor) = True Then
Set oVend = dict(vendor)
Else
Set oVend = New clsRemit
dict.Add vendor, oVend
End If
oVend.vendor = vendor 'error here
oVend.invoices = oVend.invoices & vbCrLf & .Cells(q, "F")
oVend.amount = oVend.amount + .Cells(q, "G").Value
End If
Next
oVend.vendor = vendor 'error here
That's a red herring. The real problem is here:
Sub clsRemit()
Public vendor As String
Public amount As Long
Public invoices As String
End Sub
Public (or Private, for that matter) is illegal in a procedure scope. Remove the procedure scope, the code should compile:
Option Explicit
Public vendor As String
Public amount As Long
Public invoices As String

Techniques for binding object properties to Sheet Cells

Edit:
The three main things I'm looking to accomplish here are:
To be able to encapsulate properties/methods into a class (easy enough)
Use excel ranges as a user input for users to manipulate class property values.
(bonus) Send user changes back up to a database.
I've been playing with the idea of building something in vba that would allow me to bind an object's property(ies) to a Range. Basically turning a cell into a bound control.
Some basic requirements I might be after include:
A change to the object property would update the cell value
A change to the cell would update the object property
The object property may be bound/unbound without losing the value of the property.
My initial thought is to build a BindRange class that simply gets its value from a range and sets its value to that range.
BindRange.cls:
Option Explicit
Private p_BoundCell As Range
Public Property Get Value() As String
If Me.IsBound Then Value = p_BoundCell.Value
End Property
Public Property Let Value(Val As String)
If Me.IsBound Then p_BoundCell.Value = Val
End Property
Public Property Get IsBound() As Boolean
If BoundToDeletedCell Then
Set p_BoundCell = Nothing
End If
IsBound = Not (p_BoundCell Is Nothing)
End Property
Public Sub Bind(Cell As Range)
Set p_BoundCell = Cell(1, 1)
End Sub
Private Function BoundToDeletedCell() As Boolean
Dim sTestAddress As String
On Error Resume Next
TRY:
If p_BoundCell Is Nothing Then
Exit Function
'// returns false
End If
sTestAddress = p_BoundCell.Address
If Err.Number = 424 Then 'object required
BoundToDeletedCell = True
End If
End Function
Then, I can set up my custom object with a pair of fields to manage the updates. I would also need a method to expose setting the range to be bound.
TestObject.cls:
Option Explicit
Private p_BindId As BindRange
Private p_Id As String
Public Property Get Id() As String
If p_BindId.IsBound Then
p_Id = p_BindId.Value
End If
Id = p_Id
End Property
Public Property Let Id(Val As String)
p_Id = Val
If p_BindId.IsBound Then
p_BindId.Value = p_Id
End If
End Property
Public Sub Id_Bind(Cell As Range)
p_BindId.Bind Cell
End Sub
Private Sub Class_Initialize()
Set p_BindId = New BindRange
End Sub
Private Sub Class_Terminate()
Set p_BindId = Nothing
End Sub
This could be annoying because any property I want to make "Bindable" I'll have to manage Get/Set and Bind for each. I'm also not too sure if this will cause any memory issues: making class-properties with variant typed values....
Also considering building a service-like class that keeps track of objects and their bound ranges in a dictionary-like structure?
Anyways, just curious if anyone has done something like this before or if you have any thoughts on how you might design this.
Binding individual cells to properties would be very cumbersome. I think a better technique would be to create a table to act as a property sheet and a PropertySheetWatcher that raise a PropertyChange event.
Let's say for instance that we wanted to create a simple game on a userform call Stack OverKill. Our game will have its Hero Class and multiple Enemies classes (e.g. Turtle, Rhino, Wolf). Although each class has its own business logic they all share common properties (Name, HP, ClassName, Left, Right ...etc). Naturally, since they all sure the same basic set of properties they should all Implement a common Interface (e.g. CharacterInterface). The beauty of this is they can all share the same Property Sheet Table.
Mock Property Sheet Table
PropertySheetWatcher:Class
Private WithEvents ws As Worksheet
Public Table As ListObject
Public Event PropertyChange(ByVal PropertyName As String, Value As Variant)
Public Sub Init(ByRef PropertySheetTable As ListObject)
Set ws = PropertySheetTable.Parent
Set Table = PropertySheetTable
End Sub
Private Sub ws_Change(ByVal Target As Range)
Dim PropertyName As String
If Not Intersect(Target, Table.DataBodyRange) Then
PropertyName = Intersect(Target.EntireColumn, Table.HeaderRowRange).Value
RaiseEvent PropertyChange(PropertyName, Target.Value)
End If
End Sub
Public Sub UpdateProperty(ByVal PropertyName As String, Name As String, Value As Variant)
Application.EnableEvents = False
Dim RowIndex As Long
RowIndex = Table.ListColumns("Name").DataBodyRange.Find(Name).Row
Table.ListColumns(PropertyName).DataBodyRange.Cells(RowIndex).Value = Value
Application.EnableEvents = True
End Sub
Hero:Class
Implements CharacterInterface
Private Type Members
Name As String
HP As Single
ClassName As String
Left As Single
Right As Single
Top As Single
Bottom As Single
Direction As Long
Speed As Single
End Type
Private m As Members
Public WithEvents Watcher As PropertySheetWatcher
Private Sub Watcher_PropertyChange(ByVal PropertyName As String, Value As Variant)
Select Case PropertyName
Case "Speed"
Speed = Value
Case "HP"
'....More Code
End Select
End Sub
Public Property Get Speed() As Single
Speed = m.Speed
End Property
Public Property Let Speed(ByVal Value As Single)
m.Speed = Speed
Watcher.UpdateProperty "Speed", m.Name, Value
End Property
Private Property Get CharacterInterface_Speed() As Single
CharacterInterface_Speed = Speed
End Property
Private Property Let CharacterInterface_Speed(ByVal Value As Single)
Speed = Value
End Property
The classes above give are a quick muck-up of how the notification system can be implemented. But wait there is more!!!
Look how easy it is to setup a Factory to reproduce all of out Characters based off the saved setting.
CharacterFactory:Class
Function AddCharacters(Watcher As PropertySheetWatcher) As CharacterInterface
Dim Table As ListObject
Dim data As Variant
Dim RowIndex As Long
With Table
data = .DataBodyRange.Value
For RowIndex = 1 To UBound(data)
Select Case data(RowIndex, .ListColumns("Class").Index)
Case "Hero"
Set AddCharacters = AddCharacter(New Hero, Table, RowIndex)
Case "Turtle"
Set AddCharacters = AddCharacter(New Turtle, Table, RowIndex)
Case "Rhino"
Set AddCharacters = AddCharacter(New Rhino, Table, RowIndex)
Case "Wolf"
Set AddCharacters = AddCharacter(New Wolf, Table, RowIndex)
End Select
Next
End With
End Function
Private Function AddCharacter(Character As CharacterInterface, Table As ListObject, RowIndex As Long) As Object
With Character
.Speed = Table.ListColumns("Speed").DataBodyRange.Cells(RowIndex).Value
'....More Coe
End With
Set AddCharacter = Character
End Function
It may seem like I wrote a lot of original content but I didn't. The whole setup is an adaptation of concepts taken from different popular design patterns.

Set variable with a loop using the variables name as a string

My application requires variables to be set and retrieved multiple times in different forms and subs. Instead of writing the code multiple times i was hoping to use a loop to loop through the variables and set them accordingly. The code below shows my settings menu and how it is built. I'm stuck with setting the variables based on a name that is stored as a string (See last code snippet below).
The section imedialty below are the menu classes. This bit works as expected
Public Class MenuItem
Public Name As String
Public Type As TypeEnum
Enum TypeEnum
CheckBox
ComboBox
TextBox
End Enum
Public Sub New()
End Sub
End Class
Public Class Menu
Public MenuItems() As MenuItem
Public Name As String
Public LinkedVariable as Object
Public Sub New()
End Sub
Public Sub AddMenuItem(ByVal ItemName As String, _
ByVal ItemType As MenuItem.TypeEnum, _
ByVal ItemLinkedVariable as Object)
If MenuItems Is Nothing Then
ReDim MenuItems(0)
Else
ReDim Preserve MenuItems(MenuItems.Length)
End If
MenuItems(MenuItems.Length - 1) = New MenuItem
MenuItems(MenuItems.Length - 1).Name = ItemName
MenuItems(MenuItems.Length - 1).Type = ItemType
MenuItems(MenuItems.Length - 1).LinkedVariable = ItemLinkedVariable
End Sub
End Class
Build the menus in the main form class. This bit works as expected
Public Class Form1
Public Settings As New SettingsForm
Public Sub CreateMenu()
Settings.AddMenu("Menu1")
Settings.Menus(0).AddMenuItem("CheckBoxA", MenuItem.TypeEnum.CheckBox, VariableA)
Settings.Menus(0).AddMenuItem("TextBoxB", MenuItem.TypeEnum.TextBox, VariableB)
Settings.Menus(0).AddMenuItem("TextBoxC", MenuItem.TypeEnum.TextBox, VariableC)
Settings.AddMenu("Menu2")
Settings.Menus(1).AddMenuItem("CheckBoxD", MenuItem.TypeEnum.CheckBox, VariableD)
Settings.Menus(1).AddMenuItem("TextBoxE", MenuItem.TypeEnum.TextBox, VariableE)
'etc......
Settings.Build()
Settings.Show()
End Sub
End Class
Public Class SettingsForm
Public Menus() As Menu
Public VariableA As Boolean
Public VariableB As String
Public VariableC As String
Public VariableD As Boolean
Public VariableE As String
Public Sub New()
InitializeComponent()
End Sub
Public Sub Build()
SettingsTabControl.TabPages.Clear()
If Menus IsNot Nothing Then
For i As Integer = 0 To Menus.Length - 1
SettingsTabControl.TabPages.Add(Menus(i).Name)
SettingsTabControl.TabPages(i).Name = Menus(i).Name & "TabPage"
SettingsTabControl.TabPages(i).Text = Menus(i).Name
AddSettingsItems(Menus(i), i)
Next
End If
End Sub
Public Sub AddSettingsItems(ByVal SelectedMenu As Menu, ByVal TabPageIndex As Integer)
Dim y As Integer = 50
Dim yinc As Integer = 25
If SelectedMenu IsNot Nothing Then
If SelectedMenu.MenuItems IsNot Nothing Then
For i As Integer = 0 To SelectedMenu.MenuItems.Length - 1
Dim formObj As Object
'Specific Settings
Select Case SelectedMenu.MenuItems(i).Type
Case MenuItem.TypeEnum.CheckBox
formObj = New CheckBox
Case MenuItem.TypeEnum.ComboBox
formObj = New ComboBox
Case MenuItem.TypeEnum.TextBox
formObj = New TextBox
formObj.TextAlign = HorizontalAlignment.Right
formObj.BorderStyle = BorderStyle.FixedSingle
End Select
formObj.Name = SelectedMenu.MenuItems(i).Name
formObj.Location = New Point(25, y)
SettingsTabControl.TabPages(TabPageIndex).Controls.Add(formObj)
y = y + yinc
Next
End If
End If
End Sub
End Class
This is the bit i am stuck on i want to be able to set the Variables A,B,C,D,E from the controls that were added to the SettingsTabControl. However i can't work out how to link the Variables to the LinkedVariable objects in each MenuItem. This is what i have but it doesn't work
Private Sub SettingsFromOkButton_Click(sender As Object, e As EventArgs) Handles OkButton.Click
For m As Integer = 0 To Menus.Length - 1
For i As Integer = 0 To Menus(m).MenuItems.Length
Dim currentcontrol As Object = SettingsTabControl.TabPages(m).Controls(Menus(m).MenuItems(i).Name)
Select Case Menus(m).MenuItems(i).Type
Case MenuItem.TypeEnum.CheckBox
If currentcontrol.CheckedState = True Then
Menus(m).MenuItems(i).LinkedVariable = True
Else
Menus(m).MenuItems(i).LinkedVariable = False
End If
Case MenuItem.TypeEnum.ComboBox
Case MenuItem.TypeEnum.TextBox
Menus(m).MenuItems(i).LinkedVariable = currentcontrol.Text
End Select
Next
Next
MsgBox(VariableA & vbCrLf _
VariableB & vbCrLf _
VariableC & vbCrLf _
VariableD & vbCrLf _
VariableE & vbCrLf)
End Sub
I used a reflection
Dim Flags As BindingFlags = BindingFlags.GetField Or BindingFlags.Instance Or BindingFlags.Public
Dim fVar As System.Reflection.FieldInfo = Me.GetType.GetField(ObjectName, Flags)
If TypeOf SettingsTabControl.TabPages(TabPageIndex).Controls(CtrlName) Is TextBox Then
ctrlValue = SettingsTabControl.TabPages(TabPageIndex).Controls(CtrlName).Text
ElseIf TypeOf SettingsTabControl.TabPages(TabPageIndex).Controls(CtrlName) Is CheckBox Then
ctrlValue = CType(SettingsTabControl.TabPages(TabPageIndex).Controls(CtrlName), CheckBox).Checked
ElseIf TypeOf SettingsTabControl.TabPages(TabPageIndex).Controls(CtrlName) Is RadioButton Then
ctrlValue = CType(SettingsTabControl.TabPages(TabPageIndex).Controls(CtrlName), RadioButton).Checked
End If
fVar.SetValue(Me, ctrlValue)

Variables and constants across multiple vba macros in same module & workbook

After a lot of small sub() writing in the same Excel workbook, I realised that I often used same part code, variables and constants. Thus I decided to write funcions() for the code, and declare variables & constant/static as Public outside functions and sub. I am very new to vba declarations and this is not so easy. Let me give you one summary of what i want to achieve. I have writen all funcions and sub in one module under the module directory of the workbook.
Option Explicit
Public ToDate As String ' variable I use in many sub and functions
Public MyPath As String ' variable I use in many sub and functions
Public NameOfWorker As Variant ' constant I use in many sub and functions
Public Salary As Double ' constant I use in many sub and functions
NameOfWorker = Cells(14, 19) ' !!! PB : 14 is highlighed with error : incorrect instruction outside a procedure
Salary = Cells(20, 7).Value '!!! same as above
How and where shall I declare such constants/statics ? Shall I write a "special" procedure to declare all these variables and constants ? I tried many way to declare them with no success.
Public Static NameOfWorker = Cells(14, 19) As String ' not working
''''''
Public Static nameOfWorker As String
NameOfWorker = Cells(14, 19) ' not working
''' etc etc
Thank you for help.
EDIT : after more reading, I found one solution this way:
Public Const MY_PATH = "Y:\path\to\directory\"
Public Const WORKERNAME = "14, 19"
Not so bad :-)
You could create a new module called something like DataHelper which looks like this:
Private NameOfWorker As String
Private AgeOfWorker As Long
Private SetupComplete As Boolean
Public Function GetNameOfWorker()
If NameOfWorker = "" Then
NameOfWorker = Sheets("SomeSheet").Cells(14, 19)
End If
GetNameOfWorker = NameOfWorker
End Function
Public Function GetAgeOfWorker()
...
End Function
Now in any other code you can retreive the value:
Sub SomeMethod()
Cells(1, 1).Value = DataHelper.GetNameOfWorker()
End Sub
...and you never have to worry if it's been set.
Good question!
I would Dim the globals above all the subs in the module, but initialize the globals at a convenient spot within some sub. For example:
Public NameOfWorker As String
Public AgeOfWorker As Long
Public SetupComplete As Boolean
Sub MAIN()
If SetupComplete Then
Else
NameOfWorker = Sheets("Sheet1").Range("B9")
AgeOfWorker = Sheets("Sheet1").Range("B10")
SetupComplete = True
MsgBox "Global variable set up complete!"
End If
End Sub

Resources