Object required error when clicking command button - excel

I'm receiving an "Object required" error when trying to access my user form. It highlights the following code:
Sub DataEntry()
ServiceUpgradesDatEntry.Show
End Sub
I've double checked that the name is correct. I'm still new to VBA so any help would be greatly appreciated!

Go to Tools - Options - General in the VBE and change Error Trapping to Break in Class Module. There is an error in the userform's Initialize event, but the VBE isn't set to break in the userform's class module so it breaks on the line that sent you into the class module (the .Show line).
Once you've set that, clicking Debug on the error will highlight the line that's actually producing the error.

Treat your userform like an object and declare and instantiate it accordingly.
Public Sub DataEntry()
Dim dataEntryForm As ServiceUpgradesDatEntry
' Create an instance of the form
Set dataEntryForm = New ServiceUpgradesDatEntry
' Show the form
dataEntryForm.Show
' If the form was opened as Modal, then the code here will only run
' once the form has been hidden/closed
' Now destroy the object
Set dataEntryForm = Nothing
End Sub

Related

Set CheckBox Control dim as a UserForm CheckBox

I am attempting to create a class module that builds on top of a checkbox control. Within the Class Module I want to point at the checkbox in the userform. Although, when I try to fill the CheckBox object with one of the checkboxes in the userform I get a type-mismatch since calling on the checkbox gives back it's state instead of the entire object. Is there a way to get the entire object?
I have tried
set myCheckBox = makeMyCheckBox(Me.CheckBox1)
and
set myCheckBox = makeMyCheckBox(Me.CheckBox1.Object)
where makeMyCheckBox is a function that takes in a CheckBox object and creates a new MyCheckBox object.
'Within my userform's code
Dim myCheckBoxes(1 to 2) As MyCheckBox 'MyCheckBox is my class module
Private Sub UserForm_Initialize()
set myCheckBoxes(1) = makeMyCheckBox(me.CheckBox1)'<--Error Type Mismatch
End Sub
Private Function makeMyCheckBox(c As CheckBox) As MyCheckBox
Dim myChck As MyCheckBox
Set myChck = New MyCheckBox
myChck.init c 'takes in a CheckBox and fills its internal CheckBox object
Set makeMyCheckBox= myChck
End Function
I expect Me.CheckBox1 to be a CheckBox object.
Me.CheckBox1 outputs the checkbox's state when I look in debug (true/false)
I get--
Run-time error '13':
Type Mismatch
I get a type-mismatch since calling on the checkbox gives back it's state instead of the entire object. Is there a way to get the entire object?
Wrong assumption, you're getting the "entire object", but the object you're getting isn't implementing the interface you're expecting, hence the type mismatch.
You need to qualify your MSForms types explicitly with the MSForms library, like this:
Private Function makeMyCheckBox(ByVal c As MSForms.CheckBox) As MyCheckBox
Otherwise the unqualified CheckBox identifier / type name is referring to Excel.CheckBox, because the host application's object model (the Excel library) always has a higher priority than the referenced MSForms library, in the project references dialog:
This is excruciatingly hard to discover in a vanilla VBE. With Rubberduck you just place the caret on CheckBox and it tells you where it's coming from:
Without any add-ins, you kind of have to guess what the actual type is, because Shift+F2 (which normally takes you to the definition in the Object Browser) is useless for this - all you get is a message saying "the identifier under the cursor is not recognized".
Disclaimer: I manage the Rubberduck open-source project.

Calling a VBA form from a button causes UserForm_Initialize to run twice, breaking my code?

Hello wonderful VBA community,
I'm still really new to vba and am trying to learn a lot. Thank you in advance for looking through my code and my description of the issue I'm facing.
I have a button on a page that calls a new Userform.
CODE SNIPPET 1:
Sub btnShowDetails_Click()
Call frmShowDeets.ShowDeets
End Sub
... which calls the next bit of code in the 'frmShowDeets' UserForm:
CODE SNIPPET 2:
Public Sub ShowDeets()
Dim frm As frmShowDeets
Set frm = New frmShowDeets 'this line triggers the Userform_Initialize() event below
frm.Show
End Sub
... triggering:
CODE SNIPPET 3:
Private Sub UserForm_Initialize()
Dim comboBoxItem As Range
For Each comboBoxItem In ContactList.Range("tblContactList[CompanyName]")
'^refers to unique values in a named range
With Me.boxCompanySelection
.AddItem comboBoxItem.Value
End With
Next comboBoxItem
End Sub
So at this point, the form I want to display has values loaded in its one combobox for user selection. The user selects a company and the Combobox_Change event triggers other routines that pull information for that company.
CODE SNIPPET 4:
Public Sub boxCompanySelection_Change()
Call frmShowDeets.PullData
End Sub
Sub PullData()
Dim numCompanies As Long
numCompanies = ContactList.Range("B6").Value 'this holds a count of the rows in the named range
Dim FoundCell As Range
Set FoundCell = ContactList.Range("tblContactList[Company Name]").Find(What:=boxCompanySelection.Text, LookIn:=xlValues, LookAt:=xlWhole)
Dim CompanyRow As Long
CompanyRow = FoundCell.Row
With ContactList
'pull a bunch of the company's details
End With
End Sub
Here is where it gets weird... Once the form is shown and the user selects one of the combo box items, triggering the Combobox_Change event the code breaks because the 'What:=boxCompanySelection.Text' part of the Range().Find method reads as "" empty (even though Code Snippet 3 is meant to load in company names and Code Snippet 4 is only triggered when the user selects one of those company names from the combobox) and I shouldn't need to build something to handle 'not found' exceptions since the only possible values should be the ones pulled in from my named range.
From stepping through the code, I have determined that for some reason, Code Snippets 2 and 3 run TWICE before Snippet 4 is run. Does anyone know what about my code is causing this to happen? I'm thinking there's a disconnect between the form that is shown and loaded with combobox values and whatever Code Snippet 4 is reading data from.
What is weirder is that if I run the code starting from Code Snippet 2 (ignoring the button call in Code Snippet 1), the form works as intended and from what I can tell 2 and 3 are only run once.
The problem is probably something simple I'm overlooking but I just cannot figure out what it is. Thanks again!
You have to understand that a form is an object - exactly as any other class module, except a form happens to have a designer and a base class, so UserForm1 inherits the members of the UserForm class.
A form also has a default instance, and a lot of tutorials just happily skip over that very important but rather technical bit, which takes us exactly here on Stack Overflow, with a bug involving global state accidentally stored on the default instance.
Call frmShowDeets.ShowDeets
Assuming frmShowDeets is the name of the form class, and assuming this is the first reference to that form that gets to run, then the UserForm_Initialize handler of the default instance runs when the . dot operator executes and dereferences the object. Then the ShowDeets method runs.
Public Sub ShowDeets()
Dim frm As frmShowDeets
Set frm = New frmShowDeets 'this line triggers the Userform_Initialize() event below
frm.Show
End Sub
That line triggers UserForm_Initialize on the local instance named frm - which is an entirely separate object, of the same class. The Initialize handler runs whenever an instance of a class is, well, initialized, i.e. created. The Terminate handler runs when that instance is destroyed.
So ShowDeets is acting as some kind of "factory method" that creates & shows a new instance of the frmShowDeets class/form - in other words whatever happened on the default instance is irrelevant beyond that point: the object you're working with exists in the ShowDeets scope, is named frm, and gets destroyed as soon as it goes out of scope.
Remove the ShowDeets method altogether. Replace this:
Call frmShowDeets.ShowDeets
With this:
With New frmShowDeets
.Show
End With
Now the Initialize handler no longer runs on the default instance.
What you want, is to avoid using the default instance at all. Replace all frmShowDeets in the form's code-behind, with Me (see Understanding 'Me' (no flowers, no bees)), so that no state ever accidentally gets stored in the default instance.
Call frmShowDeets.PullData
Becomes simply:
Call Me.PullData
Or even:
PullData
Since Call is never required anywhere, and the Me qualifier is always implicit when you make a member call in a class module's code.

VB6 Automation Error when calling Add on previously created MultiPage

I want to generate a bunch of MultiPages and create new Pages dynamically in my app, but i'm getting Run-time error '-2147417848 (80010108)': Automation error The object invoked has disconnected from its clients.
Steps to reproduce
In a Class Module named TestClass:
Public WithEvents TestMultiPage As MsForms.MultiPage
Sub createPage()
TestMultiPage.Add
End Sub
In a UserForm named TestForm:
Dim TestInstances as New Collection
Private Sub UserForm_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X as Single, ByVal Y as Single)
If Button = fmButtonRight Then
Dim TestInstance as New TestClass
Set TestInstance.TestMultiPage = Me.Controls.Add("Forms.MultiPage.1")
TestInstances.Add TestInstance
End If
End Sub
Private Sub UserForm_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Dim TestInstance As TestClass: Set TestInstance = TestInstances(1)
TestInstance.createPage
End Sub
When i right-click the UserForm twice, i get two MultiPages. Then i double-click the UserForm, expecting the first MultiPage to have a new Page. But i hit the automation error at TestInstance.createPage -> TestMultiPage.Add, even though all the variables seem present from the Locals window.
What am i missing?
Conclusion
Following #GSerg's answer, i suppose there's no way to do this with MultiPage.
Instead i have to use TabStrip instead and emulate the other behaviour of MultiPage.
Just to add some context, i was trying to create a browser-like UI with windows and tabs (a TabStrip at the bottom representing different windows, each window corresponding to a MultiPage with multiple tabs). I hit the obscure error when switching back to a previous MultiPage and creating a new tab.
There appears to be a problem in MSForms, where it cripples the existing MultiPage controls when a new one is added. To reproduce the problem, you don't need collections, arrays, classes, or even variables:
Sub Reproduce()
Me.Controls.Add "Forms.MultiPage.1", "TestInstance1"
Me.Controls("TestInstance1").Add ' That works
Me.Controls.Add "Forms.MultiPage.1", "TestInstance2"
Me.Controls("TestInstance1").Add ' Now it does not
Me.Controls("TestInstance2").Add ' But the new shiny one does
Me.Controls.Add "Forms.MultiPage.1", "TestInstance3"
Me.Controls("TestInstance2").Add ' Now the instance 2 is also defunct
Me.Controls("TestInstance3").Add ' Only the latest one works
End Sub
I do not know why that is so. It looks like a bug in MSForms.
The controls work fine otherwise, and their properties are accessible, you just can't call Add anymore.

VBA Form returns Compile error method or data member not found when label clearly exist

I'm trying to do it use a label to pop up, via a click, a user form, enter data and unload it into the label but VBA does not seem to recognize the label. I can make the form appear, but when I want to feed to data to the label the code crashed with the error message "Compile error method or data member not found"
Private Sub ok_Click()
Sheet1.faktnr = Me.faktnr
Unload Me
End Sub
That's all the code, the label and textbox is named faktnr. This is probably a silly question but I feel stupified by this.
Try this:
Private Sub ok_Click()
Sheet1.Range("faktnr") = Me.faktnr
Unload Me
End Sub

OLE Excel object manipulation causes run-time error '91'

I am maintaining an application that was written in Visual Basic 6.0 and makes use of the several OLE controls with Excel.Sheet.8 class objects. Several users are getting the following error when they reach a point in code that attempts to manipulate the excel objects.
Run-time error '91': Object variable or With block variable not set
Below are examples of the code that trigger this error. I believe that the issue happens at:
Set oExcel = oleXl.object
Here are the points in the code where it happens:
Private Sub Form_Load()
Dim i As Integer
Dim j As Integer
Dim sTempStringA As String
Dim sTempStringB As String
'Set up excel sheet
centerform Me
Set oOutGrid = oleXlOutput.object
...
Private Sub Form_Load()
centerform Me
Set oOtherFx = oleXlFx.object
...
Private Sub Form_Load()
Dim iRet As Integer
Dim i As Integer
On Error GoTo Err_Handler
centerform Me
Call InitArray
Me.Caption = "TJUJ | Version " & version & " | Enter Custom Fx"
Set oBook = oleExcel.object
...
Is there a specific situation or environment in which this error would be generated from this line of code OR a way that I can ensure the object will always be accessible at this point in the code?
The error only happens occasionally, and I can't reproduce it on my developer machine at all. I also do not have access to the machines that it is happening on, but it seems to be encountered when there is an instance of the EXCEL.EXE process running.
When you get runtime-error 91, you can bet there's an uninitialized object somewhere in the statement. In other words, you are trying to use the properties or methods of a variable/object with a value of Nothing.
In your examples, oleXl, oleXlFx, and oleExcel are probably Nothing. So when you refer to their .object property, you trigger the RTE.
Somewhere in your code these variables have to be initialized to something. Look for statements like Set oleXl = CreateObject("Excel.Application") or Set oleXl = New Excel.Application
One suggestion; when you find the statements that actually initialize those OLE objects, check to see how the error-handling is coded. If you see things like this:
On Error Resume Next
Set oleXl = CreateObject(...
add a test to make sure the object was instantiated
On Error Resume Next
Set oleXl = CreateObject(...
If oleXl Is Nothing Then
MsgBox "Hey, my object is Nothing!"
End If
Microsoft suggests that we can fix error 91 by creating a new registry key. To create a new key follow the steps below.
Click on the Windows Start menu
Type Regedit in the search box
Press Enter
Locate the following entry in the registry. HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Transaction Server
Now select the transaction server and right click on it
Select New and then choose Key
Name the key as Debug
Right click on the Debug key and choose New
Now select Key and name the key as RunWithoutContext
Ref: http://backspacetab.com/error-91/

Resources