I am creating a tool in VBA to create labels with information about transactions.
I would like the user to use a form to give all the information and the labels will be automatically created.
To do so I have created a transaction class called clsTransaction.
Public PartNum As String
Private Sub Class_Initialize()
MsgBox "initialized!"
End Sub
At the initilalisation of the form a new object is created
Private Sub UserForm_Initialize()
(...)
Dim trans As New clsTransaction
End Sub
Then when a textbox is updated, I want to update the object property
Private Sub txtPartNum_AfterUpdate()
Dim strPartNum As String
strPartNum = txtPartNum.Value
MsgBox (strPartNum)
trans.PartNum = strPartNum
End Sub
I get the following error message
Run-time error '424':
Object required
My understanding is I need to declare the obect. I have tried to add:
dim trans as object
but I get an other error message:
Run time error '91':
object variable or With block variable not set
Could someone help me to update the object through the form?
The problem seems to be in the scope of your declaration. By doing this:
Private Sub UserForm_Initialize()
(...)
Dim trans As New clsTransaction '<-- declaration + assignment
End Sub
you are declaring trans in the scope of UserForm_Initialize(). Hence, when you then try to do something with it into another scope:
Private Sub txtPartNum_AfterUpdate()
(...)
trans.PartNum = strPartNum
End Sub
the object trans doesn't exist anymore because it's out of scope (so it has already been collected by the garbage collector) and you get an "object required error". You need to declare trans at global level, this is the idea:
Dim trans as yourClass '<-- global declaration: the object trans will keep on existing into all scopes
Private Sub UserForm_Initialize()
Set trans = New yourClass '<-- new instance of the object
End Sub
Private Sub txtPartNum_AfterUpdate()
'use the instance here
trans.PartNum = strPartNum
End Sub
Related
I'm trying to use the worksheet object as a property in a vba class module. Hers' what I have in a a class module called clsAgent:
Public Property Get AgentSheet() As Worksheet
Set AgentSheet = pAgentSheet
End Property
' error thrown on next two lines
Public Property Set AgentSheet(AgentSheet As Worksheet)
Set pAgentSheet = AgentSheet
End Property
When I use the the following code I get a `compile error: Variable not defined" thrown in the class module:
Sub test_agent_class()
Dim agent1 As clsAgent
Set agent1 = New clsAgent
agent1.AgentSheetName = "agentsFullOutput.csv"
Set agent1.AgentSheet = Worksheets(agent1.AgentSheetName)
Debug.Print agent1.AgentSheet.Name
End Sub
Please try to add in your clsAgent module file the following line:
Dim pAgentSheet As Worksheet
since the properties you have created ought to reference an existing pAgentSheet field of the clsAgent module.
Please try also the modified test file:
Sub test_agent_class()
Dim agent1 As clsAgent
Set agent1 = New clsAgent
Set agent1.AgentSheet = Worksheets("agentsFullOutput.csv")
Debug.Print agent1.AgentSheet.Name
End Sub
I'm not 100% sure but it looked like you were referencing a variable/propertyAgentSheetName which didn't exist in the clsAgent class module.
I hope it helps at least slightly.
I am new in VBA and classes.
I have this procedure in my class:
Public Sub InputData()
Dim blnLoaded As Boolean
Dim path As String
Dim file As String
path = MyForm.TextPath
file = MyForm.TextFile
If LoadData(path, file) = False Then
MsgBox FileErrorString
Else
blnLoaded = LoadData(path, file)
End If
End Sub
and I want to call it using 2 text boxes in my form:
Private Sub CmdLoad_Click()
Call clsData.InputData
End Sub
What I am doing wrong? Thank you in advance!
You need to create a new instance of your class first.
Something like this depending on your implementation of your class:
Private Sub CmdLoad_Click()
Dim myData as New clsData
Call myData.InputData()
End Sub
I am writing my first classes.
One is cCRElist which is essentially a collection of cCRE instances (some specialized events).
I want there to be a sub or function inside cCRElist that will load all the CRE's from the worksheet into one big collection I can work with. I created the function and it worked OK when I called it from a normal code module, but then I tried to move the code into the class. Now I am having trouble calling the function LoadFromWorksheet(myWS as Worksheet).
The error is "object does not support this property or method". I have tried making it a sub, a function, making it public, not public, I have tried turning into a Property Let instead of a sub. Obviously I have a flimsy grasp on what that does. I have tried
Call CREList.LoadFromWorksheet(myWS)
and
CREList.LoadfromWorksheet myWS
Same error every time.
Here is the test code that uses the class and calls the function:
Sub TestClassObj()
Dim CRElist As cCRElist
Set CRElist = New cCRElist
Dim myWS As Worksheet
Set myWS = ThisWorkbook.ActiveSheet
CRElist.LoadFromWorksheet (myWS)
End Sub
Here is a snippet of the class cCRElist:
' **** CLASS cCRElist
Option Explicit
' This is a collection of CRE objects
Private pCRElist As Collection
Private Sub Class_Initialize()
Set pCRElist = New Collection
End Sub
Public Property Get CREs() As Collection
Set CREs = pCRElist
End Property
Public Property Set Add_CRE(aCRE As cCRE)
pCRElist.Add aCRE
End Property
Function LoadFromWorksheet(myWS As Worksheet)
Dim CRE As cCRE
Dim iFirst As Long
Dim iLast As Long
Dim i As Long
Set CRE = New cCRE
iFirst = gHeader_Row + 1
iLast = FindNewRow(myWS) - 1
' update data in CRE then add
For i = iFirst To iLast
If myWS.Cells(i, gCRE_Col) <> "" Then ' This is a CRE row
Set CRE = New cCRE
With CRE
.CRE_ID = myWS.Cells(i, gCRE_Col)
If Not IsDate(myWS.Cells(i, gCRE_ETA_Col)) Then
.ETA = "1/1/1900"
Else
.ETA = Trim(myWS.Cells(i, gCRE_ETA_Col))
End If
<... snipped ...>
End With
pCRElist.Add_CRE CRE
End If
Next
End Sub
' **** END OF CLASS cCRElist
Thanks for your expertise.
Here is what worked based on help I got in the comments. First, I did the "break in class module". In the test code, I changed the function call from:
CRElist.LoadFromWorksheet(myWS)
to
CRElist.LoadFromWorksheet myWS
Inside the class, i had to change
Set pCRElist.Add_CRE CRE
to
pCRElist.Add CRE
Then I was able to get rid of extraneous CLASS functions Add_CRE and Count.
Thanks for everyone's input. I couldn't figure out how to mark comments as accepted answers so I did this. Let me know if I need to do something differently.
Now it works!
I'm trying to create a class that manages the events of a combo box in Access 2010. Here you have the code:
Class TestEvents
Public WithEvents cbMyCombo As Access.ComboBox
Public Property Get AssociatedCombo() As Access.ComboBox
Set AssociatedCombo = cbMyCombo
End Property
Public Sub cbMyCombo_Change()
MsgBox "Combo has changed!"
End Sub
Private Sub Class_Initialize()
Set cbMyCombo = Form_Form1.Combo1
End Sub
Form1 Code (Contains a combobox named Combo1)
Option Compare Database
Option Explicit
Private MyTestEvents As TestEvents
Private Sub Form_Load()
Set MyTestEvents = New TestEvents
MsgBox MyTestEvents.AssociatedCombo.Name
End Sub
When running the code, I get (as expected) a message with the combobox name (Combo1), so the TestEvents.AssociatedCombo property is pointing to the right object but nothing happens when I change the combo value. I would expect to get the message "Combo has changed".
Is there anything I'm doing wrong?
Thanks in advance for your help :)
By default events sunk for a form control are not raised in VBA at all; to enable them (and subsequently enable your WithEvents) you need to wire up each event you want to handle;
Set cbMyCombo = Form_Form1.Combo1 '//please put this in a property!
cbMyCombo.OnKeyDown = "[Event Procedure]"
cbMyCombo.OnBlaDeBla = "[Event Procedure]"
(Note that's the actual string value you need to set, not a placeholder/example)
You can also do this on the Events tab of the control properties.
Given that we have a script
Option Explicit
Class CClass
Private m_date
Private Sub Class_Initialize()
m_date = CDate("1970-01-01 00:00:00")
End Sub
Public Function Foo()
Dim d : d = Date()
WScript.Echo "d is " & FormatDateTime(d, vbGeneralDate)
End Function
Public Property Get Date()
Date = m_date
End Property
Public Property Let Date(p_date)
m_date = CDate(p_date)
End Property
End Class
Dim obj : Set obj = NEW CClass
Call obj.Foo()
How can class function CClass.Foo() call built-in VBScript function Date() without the property CClass.Date interfering?
My current solution is to introduce a dummy Date_() function which can be called instead. But that just seems wrong. I'm thinking there should be some way to specify that we want to call something outside the class scope.
I am almost positive that there is no way to do what you're asking in VBScript.
But even if you could figure out a way to do this, you really shouldn't. You need to choose names for your own functions that don't conflict with the names of built-in functions. Anything else is completely unmaintainable for a dynamic scripting language like VBScript.
Pick a different name for your Date property. Preferably something more descriptive: what kind of date does that property return? What does the date refer to? How is it likely to be used? Whatever you do, don't rename it to Date_—that's not any better.
You can call it from inside the class like:
Dim d : d = me.Date()
Me in VBScript is the same as you use This in Javascript for example
Too late to the party, but there is a solution using eval function.
see eval function docs for details
Class CClass
Private m_date
Private Sub Class_Initialize()
m_date = CDate("1970-01-01 00:00:00")
End Sub
Public Function Foo()
Dim d : d = eval("Date()")
WScript.Echo "d is " & FormatDateTime(d, vbGeneralDate)
End Function
Public Property Get Date()
Date = m_date
End Property
Public Property Let Date(p_date)
m_date = CDate(p_date)
End Property
End Class
Dim obj : Set obj = NEW CClass
Call obj.Foo()