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
Related
I'm learning about storing multiple values for a Key in VBA. My research has lead to me to utilize a custom Collection Class.
I got it to work in theory and then in practice I wanted to look up values based on the key but was only able to do it via "index number". I then generated a Property to return that index number, but that means if I have to loop through Keys each each will loop through the entire collection to find the index number before moving forward. This seems like too much computation and I'm wondering if there is a way to use a dicitonary key/value setup to store the Keys Index and have this all setup inside the Collection Class so I can directly call a keys value via it's index from the dictionary.
Here is my code so far:
Module:
'https://www.wiseowl.co.uk/blog/s239/collections.htm
Sub CreatePeople()
Dim p1 As New clsPersons, p2 As New clsPersons, p3 As New clsPersons
With p1
.FirstName = "Rita"
.LastName = "Smith"
End With
With p2
.FirstName = "Sue"
.LastName = "Jones"
End With
With p3
.FirstName = "Bob"
.LastName = "Brown"
End With
Debug.Print p1.FirstName, p1.LastName, p1.FullName
Debug.Print p1.FullName, p2.FullName, p3.FullName
End Sub
Sub CreatePersonsCollectionSafer()
Dim Persons As New clsPersons
Persons.Add "Rita", "Smith"
Persons.Add "Sue", "Jones"
Persons.Add "Bob", "Brown"
Dim Person As clsPersons
Dim PersonNumber As Integer
Debug.Print Persons.Count
For PersonNumber = 1 To Persons.Count
Debug.Print Persons.Item(PersonNumber).FullName
Next PersonNumber
Dim LastName As String
LastName = "Brown"
Debug.Print "Last Name = " & LastName & " & First Name = " & Persons.ItemByLastName(LastName).FirstName
End Sub
Class (clsPersons):
Option Explicit
Private Persons As New Collection
Private Person As clsPersons
Public FirstName As String
Public LastName As String
''Subs
Sub Add(FirstName As String, LastName As String)
Dim p As New clsPersons
p.FirstName = FirstName
p.LastName = LastName
Persons.Add p
End Sub
Sub Remove(NameOrNumber As Variant)
Persons.Remove NameOrNumber
End Sub
''EndSubs
''Properties
Property Get Count() As Long
Count = Persons.Count
End Property
Property Get Item(Index As Variant) As clsPersons
Set Item = Persons(Index)
End Property
Property Get FullName() As String
FullName = FirstName & " " & LastName
End Property
Property Get Items() As Collection
Set Items = Persons
End Property
Property Get ItemByLastName(LastName As String) As clsPersons
Dim PersonsIndex As Integer
For PersonsIndex = 1 To Persons.Count
Debug.Print Persons.Item(PersonsIndex).LastName
If Persons.Item(PersonsIndex).LastName = LastName Then
Set ItemByLastName = Persons(PersonsIndex)
Exit For
End If
Next PersonsIndex
End Property
''EndProperties
You should be using the keys provided by the collection. You don't need an extra collection/dictionary.
Sub Add(FirstName As String, LastName As String)
Dim p As New clsPersons
p.FirstName = FirstName
p.LastName = LastName
Persons.Add p, LastName
End Sub
Property Get ItemByLastName(LastName As String) As clsPersons
Set ItemByLastName = Persons(LastName)
End Property
However, you should not be working with a single class here. You are basically holding a new collection of persons inside each person. You should have a Person and a Persons class to make code easier to read and maintain.
You should also hide your members and expose getters to achieve encapsulation. In your code you can easily change the name of a person and thus the keys will be useless.
Here is a different approach:
Person class:
Option Explicit
Private m_firstName As String
Private m_lastName As String
Private m_initialized As Boolean
Public Function Init(ByVal firstName_ As String, ByVal lastName_ As String) As Boolean
If m_initialized Then
Err.Raise 5, TypeName(Me) & ".Init", "Already initialized"
End If
If firstName_ = vbNullString Or lastName_ = vbNullString Then Exit Function 'Returns False
m_firstName = firstName_
m_lastName = lastName_
m_initialized = True
Init = True
End Function
Property Get FirstName() As String
FirstName = m_firstName
End Property
Property Get LastName() As String
LastName = m_lastName
End Property
Property Get FullName() As String
FullName = m_firstName & " " & m_lastName
End Property
Public Function Self() As Person
Set Self = Me
End Function
Persons class:
Option Explicit
Private m_persons As New Collection
Public Function Add(ByVal p As Person) As Boolean
On Error Resume Next 'Name can already exist
m_persons.Add p, p.LastName 'Or maybe full name would be better as multiple persons can share the same last name
Add = Err.Number = 0
On Error GoTo 0
End Function
Public Function AddFromValues(ByVal firstName_ As String, ByVal lastName_ As String) As Boolean
With New Person
If Not .Init(firstName_, lastName_) Then Exit Function
AddFromValues = Me.Add(.Self)
End With
End Function
Public Sub Remove(ByVal indexOrLastName As Variant)
m_persons.Remove indexOrLastName
End Sub
Public Property Get Count() As Long
Count = m_persons.Count
End Property
Property Get Item(ByVal indexOrLastName As Variant) As Person
Set Item = m_persons(indexOrLastName)
End Property
Property Get Items() As Collection
Set Items = m_persons
End Property
Public Function Exists(ByVal lastName_ As String) As Boolean
On Error Resume Next
m_persons.Item lastName_
Exists = (Err.Number = 0)
On Error GoTo 0
End Function
and then the testing code in a standard .bas module:
Option Explicit
Public Sub CreatePeople()
Dim p1 As New Person
Dim p2 As New Person
Dim p3 As New Person
p1.Init "Rita", "Smith"
p2.Init "Sue", "Jones"
p3.Init "Bob", "Brown"
Debug.Print p1.FirstName, p1.LastName, p1.FullName
Debug.Print p1.FullName, p2.FullName, p3.FullName
End Sub
Public Sub CreatePersonsCollectionSafer()
Dim myPersons As New Persons
myPersons.AddFromValues "Rita", "Smith"
myPersons.AddFromValues "Sue", "Jones"
myPersons.AddFromValues "Bob", "Brown"
Dim tempPerson As Person
For Each tempPerson In myPersons.Items
Debug.Print tempPerson.FullName
Next tempPerson
Dim lastNameToSearch As String
lastNameToSearch = "Brown"
Debug.Print "Last Name = " & lastNameToSearch & " & First Name = " _
& myPersons.Item(lastNameToSearch).FirstName
End Sub
I've solved this issue via the following:
Private PersonsIndexDic As Object
Sub Add(FirstName As String, LastName As String)
Dim p As New clsPersons
p.FirstName = FirstName
p.LastName = LastName
Persons.Add p
PersonsIndexDic.Add Key:=LastName, Item:=PersonsIndexDic.Count + 1
End Sub
Property Get ItemByLastName(LastName As String) As clsPersons
Set ItemByLastName = Persons(PersonsIndexDic(LastName))
End Property
Test:
Dim LastName As String
LastName = "Brown"
Debug.Print "Last Name = " & LastName & " & First Name = " & Persons.ItemByLastName(LastName).FirstName
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.
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)
I currently have instances of classes stored using the data structure presented in the image below. Each -List item is a dictionary and each -Info item is an instance of a class.
I read elsewhere that if you Set an instance variable equal to another instance, it just references the original instance. Is this correct?
I have been able to create a reference for fileInfo(1) (in the image) using the following code.
Dim prflInfo As File_Info
Set prflInfo = New File_Info
Set prflInfo = fileList.Items(0)
I have attempted to reference the branchInfo instance using the following code, but I get a Run-time error 13: Type mismatch when I attempt to do so.
Dim prbrInfo As Branch_Info
With prflInfo
Set prbrInfo = New Branch_Info
brKey = .getbrKey(0)
Set prbrInfo = .getbrItem(brKey)
End With
Edit: Included below is the code for the File_Info class. All other classes follow this basic model.
'Class Module: File_Info
'Initialise class variables
Private pfileID As Integer
Private pfilePath As String
Private pfileName As String
Private pbranchList As Scripting.Dictionary
'Declare variantcopy subroutine
Private Declare Sub VariantCopy Lib "OleAut32" (pvarDest As Any, pvargSrc As Any)
Private Sub Class_Initialize()
Set pbranchList = New Scripting.Dictionary
End Sub
Public Property Let fileID(pfileIDi As Variant)
pfileID = pfileIDi
End Property
Public Property Get fileID() As Variant
fileID = pfileID
End Property
Public Property Let filePath(pfilePathi As Variant)
pfilePath = pfilePathi
End Property
Public Property Get filePath() As Variant
filePath = pfilePath
End Property
Public Property Let fileName(pfileNamei As Variant)
pfileName = pfileNamei
End Property
Public Property Get fileName() As Variant
fileName = pfileName
End Property
Public Sub addbrConn(branch As Branch_Info)
pbranchList.Add branch.branchID, branch.brConn
Debug.Print "addbrConn ID: " & branch.branchID
End Sub
Public Sub addBranch(branch As Branch_Info)
pbranchList.Add branch.branchID, branch
Debug.Print pbranchList.Count
End Sub
Public Function countbrList()
countbrList = pbranchList.Count
End Function
Public Function getbrKey(Key As Variant)
getbrKey = pbranchList.Keys(Key)
End Function
Public Function getbrItem(Key As Variant)
getbrItem = GetByRefVariant(pbranchList.Items(Key))
End Function
Public Sub dpbrList()
With pbranchList
Debug.Print pbranchList.Count
For k = 1 To pbranchList.Count
Debug.Print .Keys(k - 1), .Items(k - 1)
Next k
End With
End Sub
Public Sub updbrList(branch As Branch_Info)
Dim branchID As String
branchID = branch.branchID
If pbranchList.exists(branchID) Then
pbranchList.Remove (branchID)
pbranchList.Add branchID, branch
Debug.Print "Complete: " & branchID & " added."
Else
Debug.Print "Error: " & branchID & "does not exist."
End If
End Sub
Private Function GetByRefVariant(ByRef var As Variant) As Variant
VariantCopy GetByRefVariant, var
End Function
Is there a way to reference the branchInfo class, to make it easier to extract the data within it?
Thanks!
Eeshwar
I do things differently in that I iterate through the keys list using a For ... each loop rather than referring to an item number. Here is a snippet that works using two levels.
You can ignore the lines where the property values are written to an array, but they were part of the original code.
cf.Dependents is a dictionary of cDependents within the cFamily object
'Declarations in Main Module
Dim dF As Dictionary, cF As cFamily, cD As cDependents
Dim I As Long, J As Long
Dim V As Variant, W As Variant
...
For Each V In dF
I = I + 1
Set cF = dF(V)
With cF
vRes(I, 1) = .FirstName
vRes(I, 2) = .LastName
vRes(I, 3) = .Birthdate
J = 2
For Each W In .Dependents
J = J + 2
Set cD = .Dependents(W)
With cD
vRes(I, J) = .Relation
vRes(I, J + 1) = .DepName
End With
Next W
End With
Next V
Note that in the sequence, as you show in your question:
set Obj = new Obj
set Obj = myClass(0)
the first line is unnecessary.
IMO it is possible to use simple VBA.Collection, here example for the FileList and BranchList. In this example List classes have Items and Info classes have reference to List where List is wrapper for a VBA.Collection. HTH
For more reading have a look e.g. here.
FileList Class
Option Explicit
Private m_fileInfoCollection As FileInfoCollection
Private Sub Class_Initialize()
Set m_fileInfoCollection = New FileInfoCollection
End Sub
Public Property Get Items() As FileInfoCollection
Set Items = m_fileInfoCollection
End Property
FileInfo Class
Option Explicit
Private m_branchList As BranchList
Private m_fileID As Integer
Private Sub Class_Initialize()
Set m_branchList = New BranchList
End Sub
Public Property Get FileID() As Integer
FileID = m_fileID
End Property
Public Property Let FileID(ByVal vNewValue As Integer)
m_fileID = vNewValue
End Property
Public Property Get BranchList() As BranchList
Set BranchList = m_branchList
End Property
FileInfoCollection Class
Option Explicit
Private m_collection As VBA.Collection
Private Sub Class_Initialize()
Set m_collection = New VBA.Collection
End Sub
Public Sub Add(ByVal newItem As FileInfo)
m_collection.Add newItem, CStr(newItem.FileID)
End Sub
Public Function ItemByKey(ByVal key As String) As FileInfo
Set ItemByKey = m_collection(key)
End Function
Public Function ItemByIndex(ByVal index As Long) As FileInfo
Set ItemByIndex = m_collection(index)
End Function
Public Function Count() As Long
Count = m_collection.Count
End Function
BranchList Class
Option Explicit
Private m_branchInfoCollection As BranchInfoCollection
Private Sub Class_Initialize()
Set m_branchInfoCollection = New BranchInfoCollection
End Sub
Public Property Get Items() As BranchInfoCollection
Set Items = m_branchInfoCollection
End Property
BranchInfo Class
Option Explicit
Private m_branchID As Integer
Public Property Get branchID() As Integer
branchID = m_branchID
End Property
Public Property Let branchID(ByVal vNewValue As Integer)
m_branchID = vNewValue
End Property
BranchInfoCollection Class
Option Explicit
Private m_collection As VBA.Collection
Private Sub Class_Initialize()
Set m_collection = New VBA.Collection
End Sub
Public Sub Add(ByVal newItem As BranchInfo)
m_collection.Add newItem, CStr(newItem.branchID)
End Sub
Public Function ItemByKey(ByVal key As String) As BranchInfo
Set ItemByKey = m_collection(key)
End Function
Public Function ItemByIndex(ByVal index As Long) As BranchInfo
Set ItemByIndex = m_collection(index)
End Function
Public Function Count() As Long
Count = m_collection.Count
End Function
Standard Module
Option Explicit
Sub Demo()
' Fill
Dim bi As BranchInfo
Set bi = New BranchInfo
bi.branchID = 111
Dim fi As FileInfo
Set fi = New FileInfo
fi.FileID = 222
fi.BranchList.Items.Add bi
Dim fl As FileList
Set fl = New FileList
fl.Items.Add fi
' Get
Dim fi1 As FileInfo
Set fi1 = fl.Items.ItemByIndex(1)
Dim bi1 As BranchInfo
Set bi1 = fi1.BranchList.Items(1)
End Sub
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