Multipage error: The object invoked has disconnected from its clients - vba

So I've probably spent the last week researching/trying to fix this annoying error but to no avail. Here's what I'm trying to do and the error I'm getting:
I have a userform that contains 12 multipage pages and to access each one I have coded previous/next buttons. Now, One of these pages is disabled through properties to hide from the user, that is until a specific checkbox is clicked. When it's clicked, the page is enabled, and the user is now able to view this page as well as all the others. when the checkbox is clicked again (making it false and no longer true), the page hides from the user's sight. This is basically what I'm trying to accomplish. The pages are like so:
page1, page2, page3, page4, "page5", page6, etc.
As you can see, page5 is what is being disabled/enabled. Now also, something important to note, I've made the userform to appear before the workbook is actually visible using this:
Private Sub Workbook_Open()
Application.ScreenUpdating = False
ThisWorkbook.Application.Visible = False
OpeningWindow.Show
Windows(ThisWorkbook.Name).Visible = True
Application.Visible = True
Application.ScreenUpdating = True
End Sub
This I would like to avoid changing because it's vital that the userform appear first before the workbook because the workbook is acting as the storage/database for everything that is being typed in the userform using this multipage system. Now when I run the userform through VBA and test out this function "checkbox_click Enables/Disables multipage page", it works no problem. When I attempt to open it (as if you were starting up excel without anything opened) everything works fine, until I click the checkbox in question to enable the multipage to make it visible. This is where I'm getting the error "The object invoked has disconnected from it's clients". Now I've tried some other things out to see if I could get the same result:
Made the multipage page visible = False instead of Enabled = false.
Result: This somewhat works, however when attempting to click the previous button to go back a page (Page6 to Page5) when Page5 is visible = False, The previous button doesn't respond, as if it knows that Page5 is there even though it's invisible.
Anyway, to wrap things up, I would like to ask the community here if anyone knows exactly why, from the code I've provided below that is responsible for this "page enable/disable feature", I'm getting this object invoked has disconnected error and if there's a way to fix it.
Private Sub CheckBox119_Click()
If CheckBox119.Value = True Then
Me.MultiPage1.Pages(5).Enabled = True
CheckBox138.Value = True
Label309.Visible = True
Else
Me.MultiPage1.Pages(5).Enabled = False
CheckBox138.Value = False
Label309.Visible = False
End If
End Sub
CheckBox138 btw is located on Page5 and is there if the user wishes to click it to disable page5 and Jump to Page4, which is this code:
Private Sub CheckBox138_Click()
If CheckBox138.Value = False Then
MultiPage1.Value = 4
CheckBox119.Value = False
Label309.Visible = False
End If
End Sub
Also, I'm relatively new to coding in VBA, but I'm always ready to learn.

After some playing around, I believe I figured out what the problem was. The checkbox138 in the disabled page was the culprit. By deleting the code Private sub checkbox138_click(), it works now. I'm not entirely sure why this is the case (so someone with more knowledge may be able to explain) But When checkbox119 is clicked, checkbox138 is suppose to turn true being that's what the initial code expressed. However, even though making checkbox119 true is suppose to enable the disabled page followed by making checkbox138 true, there seems to be a hiccup. It seems checkbox138 is thinking the disabled page is still disabled (even though checkbox119 is suppose to enable it) therefore making the checkbox138 hidden.

Related

How to hide a Visible Object in MS Access?

I have a button named btnSave that by default is not visible and when I clicked the button btnAdd, this is the time that btnSave showed. My aim is to make this button invisible again when I clicked it but I am getting this error:
Run-time error '2165':
You can't hide a control that has the focus.
This is how my code looks like:
Private Sub btnSave_Click()
....
Me.Refresh
Me.Repaint
Me.btnSave.Visible = False
Me.btnCancelSave.Visible = False
End Sub
Any help is much appreciated.
The error message is clear - object cannot be set invisible while it has focus. Move focus elsewhere.
Me.someothercontrol.SetFocus
Me.btnSave.Visible = False
Me.btnSaveCancel.Visible = False
After several googling this is what I found and thanks to the Author (Mike Wolfe). Here is the link: Fix for the error: "You can't hide a control that has the focus" in Microsoft Access

Word VBA - easily remove form frame?

I'm trying to create a user entry form which both captures the users input and displays a status update message. The slickest way I think of doing it is to have my modal form for the user entry display over a modeless form. After the user enters their info and clicks OK, the info from the modal form is copied to the modeless form, the modal form is closed and status updates get pushed to the modless form as things change during processing:
Hopefully, with a lot of messing about with positions, it will look relatively seamless. My challenge is getting rid of the frame on my modal form. I've done a lot of searching and it seems to involve completely redrawing the form from base libraries - is there seriously no easier way to do it?
I would not use a 2nd form but just place a simple Frame on top of your form. When you want to show the "modal form", just set the visibility of the frame to True, and when you want to hide it, set it to False - all controls (in your case, the input field and the OK and Cancel button) that are placed on the frame are automatically shown or hidden.
If you have controls outside the "modal form" frame that you don't want to be active at that time, set them to enabled = False. You could handle this with a simple routine within your form.
In this example I have a frame FrameModal painted on top of the form. Note that this frame could be places over other controls.
Option Explicit
Private Sub UserForm_Activate()
showHideModalFrame False
End Sub
Private Sub buttonShowModal_Click()
' Show the "modal" dialog
showHideModalFrame True
End Sub
Private Sub buttonOK_Click()
' Do your stuff here...
Me.tbUpdates = Me.tbUpdates & vbCrLf & Me.tbInput
' Hide the "modal" dialog"
showHideModalFrame False
End Sub
Private Sub showHideModalFrame(show As Boolean)
Me.FrameModal.Visible = show
Me.buttonShowModal.Enabled = Not show
End Sub
Start the form
Click the show button:

How to check for when a checkbox is checked in a Userform?

I have a Userform that has a Checkbox. I am able to check the value of it, but it is always False whether it is checked or not.
Update
This is how the UserForm is being called (This is in another UserForm ):
Private Sub AddOutgoingbtn_Click()
With New AddIncomingForm
.TopBottom.Value = False
.Show
.Repaint
End With
End Sub
End Update
I created a sub to look for a change in the value like:
Sub TopBottom2_Change()
With AddOutgoingForm
If .TopBottom2.Value = True Then TopBottom = True
If .TopBottom2.Value = False Then TopBottom = False
End With
End Sub
But no matter what I do the .TopBottom2.Value is always False.
I've put a breakpoint on the With line so that I know it is hitting this Sub, then I step through it each time. I open the UserForm and check the box, step through and the value is False, then I uncheck the box and step through. The value is still False.
I am not setting the value in any other way with VBA. I am checking the value in the UserForms code, not in any other place.
I have an If in a Calculation Module that is looking at this value for when it is true or falses, but it is always false.
Here are all the Properties of the Checkbox:
With AddOutgoingForm
That's referring to the form's default instance, which may or may not be the instance that's currently being displayed.
You have two options:
At the call site, instead of doing this (or something similar):
With New AddOutgoingForm
.Show
'...
End With
Do this:
AddOutgoingForm.Show
'...
That way you'll be working with the default instance and the checkbox value-check should work.
...but IMO that's a very very bad idea, because then your form contains code that will only ever work when you're showing the default instance.
Leave the call site alone, and NEVER refer to the default instance of a UserForm inside that form's code-behind. In other words change With AddOutgoingForm for With Me.
The Me keyword refers to the current instance - and that is what you want. Doing this will make the form work regardless of what the call site does.
Alternatively, just drop the With block altogether: With Me wouldn't be doing anything useful here.
I will assume the checkbox is indeed on your user form so just use me or you could use
AddOutgoingForm.TopBottom2.Value
But let me ask you, where is TopBottom and what is it a Boolean variable or another Checkbox? Also on the same form? The Subs are also all in the form? You have to be calling the form from somewhere so be careful between the worksheet, workbook, module variables. Is TopBottom a Global variable to the whole project (in a module called Global_Variables with Public in front of it perhaps?) You may not have access to TopBottom from inside of your form if you are not passing anything in or out.
Private Sub TopBottom2_Change()
If (Me.TopBottom2.Value) = True Then
Me.TopBottom.Value = True
Else
Me.TopBottom.Value = False
End If
End Sub
Cheers,
-WWC

VBA-Excel: Filling forms in an IE Window

I'm hoping someone can help. I'm trying to speed up the process of filling a webform that must be completed dozens or hundreds of times with information stored in excel.
To do this, I need one button to open an IE window and navigate to a certain website's login page (I've figured this bit out). The user can then log in and navigate to the form that needs to be filled. Then, I'd like the user to be able to return to the excel page, click another button, which will automatically fill several drop downs and text boxes.
Within Excel, I already have some code to allow the user to search for the particular set of information that needs to go to the form, so all they should have to do is click the button to transfer it over. The first bit of the code is just this:
Public IE As Object
Public Sub OpenIE()
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
IE.Navigate "loginpage url"
End Sub
Where I'm having trouble, however, is having a different function access the same IE window once the user has logged in and navigated to the form. Right now I've got this:
Sub FillMacro()
Dim sh As Object, oWin As Object
Set sh = CreateObject("Shell.Application")
For Each oWin In sh.Windows
If TypeName(oWin.document) = "HTMLDocument" Then
Set IE = oWin
Exit For
End If
Next
IE.Visible = True
Application.Wait (Now + TimeValue("00:00:01"))
IE.document.getElementById("idec").Value = "John"
Application.Wait (Now + TimeValue("00:00:01"))
IE.document.getElementById("idee").Value = "Smith"
End Sub
Most of that I've gotten from other posts on this forum, and while I'm a bit of a novice at this, the problem seems to be that for some reason VBA can't find the text boxes with the id of LastName or FirstName. What's more, the IE.Visible = True doesn't bring the IE window back to the foreground, so I'm trying to find the proper line to do that. When I try to run the code, I get an "Object Required" error at:
IE.document.getElementById("idec").Value = "John"
I've tried searching this site and will continue to look, but any help in the meantime would be greatly appreciated!
On the Internet Explorer page, here is the line for the first text box I'm trying to fill:
<input name="componentListPanel:componentListView:1:component:patientLastNameContainer:patientLastName" class="input300" id="idec" type="text" maxlength="60" value="">
Why not automate logging process as well? Login could be stored in Excel and its value read by macro from cell.
As Tim Williams suggests, if there is Iframe on website, use (for me it works only with contentwindow included):
IE.document.getElementById("iFrameIdHere").contentwindow.document.getEleme‌ntById("idec").Value = "John"
Instead of Application.Wait use:
Do Until IE.ReadyState = 4 And IE.Busy = False
DoEvents
Loop
It will save you a lot of time when page loads fast and prevent errors when loading exceeds wait time. Use it ONLY after page reloads (meaning after navigating or anything what causes page reloads, especially .click on HTML elements.
Use early binding, it's a bit faster than creating objects. It can increase performance by a few percent based on page loading speed, the faster pages load, the bigger increase.
Set IE = New InternetExplorer
Finally, you can toggle loading pictures, depending on whether you need to download images from website.
Public Sub ShowPictures(ByVal EnabledStatus As Boolean)
Public ScrapingCancelled as Boolean
Dim obj_Shell
Dim v_Result As Variant
Set obj_Shell = CreateObject("WScript.Shell")
'Reads the registry key that determines whether 'Show pictures' Internet Explorer advanced setting is enabled
v_Result = obj_Shell.RegRead("HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\Display Inline Images")
Select Case v_Result
Case "yes" 'Pictures are displayed
If EnabledStatus = False Then _
obj_Shell.RegWrite "HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\Display Inline Images", "no", "REG_SZ"
Case "no" 'Pictures are not displayed
If EnabledStatus = True Then _
obj_Shell.RegWrite "HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\Display Inline Images", "yes", "REG_SZ"
Case Else
ScrapingCancelled = True
End Select
End Sub
No images loaded:
ShowPictures (0)
Images loaded:
ShowPictures (1)
A good practice is to set value to 1 in the end of macro.

SetFocus inside a GotFocus procedure initiated by another SetFocus

Objective: Redirect focus from one command button to another using the first's GotFocus procedure.
Context: I have a form-independent procedure in a generic module that, on most forms, sets focus to the NewRecord button after saving the previous record. But on one form, I would like to redirect (based on certain conditions) focus back to the SignRecord button so the user can "sign" a second part of the same record (I may need this for other uses in the future). The target control is enabled and visible and can otherwise be focused and the original control can be focused when the redirect doesn't occur. Reference [2] below implies that this should be possible, though I'm not changing visibility of my controls.
Issue: When the conditions are met to redirect focus in the GotFocus procedure, it redirects as desired but the original (test) SetFocus call throws a "Run-time error '2110', Can't move focus to the control CommandNew".
What I've tried:
Exit Sub after my downstream SetFocus calls.
Call CommandSign.SetFocus in the hopes that it would make it happen outside the previous SetFocus process.
In a module,
Public Sub test()
Forms("TargetForm").CommandNew.SetFocus 'This gets the error '2110'
End Sub
In the 'TargetForm',
Private Sub CommandNew_GotFocus()
If IsNull(textDateTime) Then Exit Sub 'Works as expected
'I can see these two parts work. The framSign value changes
'and CommandSign gets focus
If checPPC And IsNull(textSigID_PPC) And framSign = 2 Then
framSign = 1
CommandSign.SetFocus
ElseIf checDAS And IsNull(textSigID_DAS) And framSign = 1 Then
framSign = 2
CommandSign.SetFocus
End If
End Sub
References:
[1]: SelectNextControl() a bad idea in a GotFocus event?
[2]: http://www.access-programmers.co.uk/forums/showthread.php?t=100071
I think your problem is that the call to Forms("TargetForm").CommandNew.SetFocus doesn't quite seem to, in fact, finish setting the focus to CommandNew until after Private Sub CommandNew_GotFocus() has finished executing. Because you've called another SetFocus before the first SetFocus could finish, there is a conflict that Access seems to be unable to cope with.
Whether or not that is the case, one thing is clear: the way you have your execution plan set up right now is unfortunately not going to work. You might try adding either a global variable or a public variable to each form that determines whether or not you should set your focus to CommandSign after you set the focus to CommandNew.
Ex. TargetForm:
Public boolSetCommandSignFocusInstead As Boolean
Private Sub CommandNew_GotFocus()
If IsNull(textDateTime) Then Exit Sub 'Works as expected
'I can see these two parts work. The framSign value changes
'and CommandSign gets focus
If checPPC And IsNull(textSigID_PPC) And framSign = 2 Then
framSign = 1
boolSetCommandSignFocusInstead = True
ElseIf checDAS And IsNull(textSigID_DAS) And framSign = 1 Then
framSign = 2
boolSetCommandSignFocusInstead = True
Else
boolSetCommandSignFocusInstead = False
End If
End Sub
Module:
Public Sub test()
Forms("TargetForm").CommandNew.SetFocus
If Forms("TargetForm").boolSetCommandSignFocusInstead Then
Forms("TargetForm").CommandSign.SetFocus
End If
End Sub