I am calling a userform A from within another userform B. The problem arises when I try to close the userform B. I don't want to use Hide method, because there are some default values assigned to form properties in the form's Load method - and I would like these values to be reassigned every time the user closes up and opens the form during one session.
So it appears that I should use Unload Me, but the latter stops my entire application as if I used End command.
So the question is, why Unload Me shuts down the entire application, rather than a single form.
Edit: Using Unload showUserFormB instead of Unload Me does not help
Private Sub methodOfUserFormA()
Call FormB.showUserFormB(some_params)
Unload SqlUpload__handlePhantomRows
Msgbox "Why Unload method shuts down entire app?"
End Sub
Related
How do I keep the values that where inputted into the excel Userform from clearing itself out once I click on the finish button? So whenever I call upon the Userform through a Commandbutton the previously filled field information is left the way it is and not to be cleared basically.
This Userform consist of MultiPage which is designed to take in the inputs from the user and place them in excel cells once the user has hit the finish button. Within the Userform contains Commandbuttons which toggles an hide/unhide feature which will also have to be saved somewhere
The Finish page (where the user will close/exit the page) looks like this:
Code for the finish button so far:
I'm not sure why everyone is saying there is no way to do this - you should be able to use:
Private Sub BtnFinish_Click()
Me.Hide
End Sub
And all previous values will be kept. Someone correct me if I'm wrong :).
I should add that once the EXCEL.EXE is closed, the values are lost.
Background/issue: I created a userform so that when a value lower than $250 is entered in a specific cell, the userform prompts the user for a password. The password is then supplied by a supervisor to allow the value. The issue is that the value entered by the user will be a guess. These users mess with values until the value they enter gets them the number they're looking for (separate formula that's dependent upon the low $250 amount). So after the user attempts their first number, they're likely going to need to enter it up to 10ish times. Currently the userform would require the supervisor to enter the password each time the value is changed. I'm hoping to edit my code so that either A) the password can be "retained" if you will for a certain length of time or B) allow the opportunity to enter an amount lower than $250 a set amount of times without the userform launching each time. I tried the number attempt originally and was unsuccessful. Honestly a time option would be best so hopefully someone can help. I've tried multiple ways of waiting (application.wait), sleep using lib kernel32, and a few different do events. From what I've gathered, the do events might be my best option as what I need it to do is allow the user to change values and not have the PC prevent the user from working (change said value though I suppose the user could still perform other actions.)
I've tried putting different the different wait/sleep/loop subs in a standard module and call them but I've also tried putting them directly in the forms module but neither way works. If the sub is in a standard module, Excel doesn't let the user do anything (it acts as application.wait) but if I perform it in the form module, it allows the user to select cells but not edit them until the loop/userform sub is complete. No errors are given in any of this, it just doesn't let users make multiple attempts at the value under $250. One last tidbit...I can run the Wait sub on a standard module and work in the workbook while it continues firing; just can't get it to work with the userform.
Public Sub CommandButton1_Click()
Dim newTime As Date
If tbPassword.Value = "password" Then
me.hide 'Form would stay up so I thought hiding it would fix issue but didn't
call wait 'loop to allow an amount of time before PS has to be reentered
Else
MsgBox "Password is incorrect."
Sheets("Rate Calculator v8").Range("K19") = ""
Application.Goto Sheets("Rate Calculator v8").Range("K19")
End If
Unload me
End Sub
Sub Wait()
Start = Timer
Do While Timer < Start + 60
DoEvents
Loop
End Sub
I got a solution that works but not as you like it to work and I will tell you why it shouldn't work like you want it to work.
First the solution:
Put this code in "ThisWorkbook"-Module:
Option Explicit
Public Endt
Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
Call Modul1.TimeBeforeReentry
End Sub
Side note here: You may want to use another event then Workbook_SheetChange but it does the job for me here. The disadvantage is that it also triggers with everything else that changes the a sheet.
Then put this code in a module1:
Sub TimeBeforeReentry()
If ThisWorkbook.Endt > Timer Then
Else
UserForm1.Show
If UserForm1.Passwordfield.Value = "password" Then
UserForm1.Passwordfield.Value = ""
ThisWorkbook.Endt = Timer + 60
Else
MsgBox "Password is incorrect."
Worksheets(1).Range("K19") = ""
Application.Goto Worksheets(1).Range("K19")
End If
End If
End Sub
And finally in the userform:
Private Sub CommandButton1_Click()
Me.Hide
End Sub
And now the explanation and why you shouldn't put everything into the userform.
The public variable Endt is in thisworkbook and will be saved there (unless there is an error!). As soon as the event is triggered, in our case workbook_SheetChange, the module will be called. Here is the whole logic and this is good. Because you do not want to make "smartUI" the problem with logic in userforms is that it is nearly impossible to maintain and to adjust to changes. I learned this the hard way believe me.. I am not an expert on this topic but read these links
Smart UI
Model View Presenter as alternative to Smart UI
The Sub TimeBeforeReentry then checks the time and shows the userform accordingly. If the password is entered the Endt is set and if the next event is triggered within Endt then the password does not have to be reentered. Otherwise the password will be needed to reentered.
The userform is just a data interchange device it has nothing to do with logic it just holds data and delivers it. That's what UI is for!
I have a UserForm, A, with a command button that opens UserForm B using the below code:
Private Sub cmd_click()
Me.Hide
B.Show
End Sub
B, when closed via the X button, runs the following:
Private Sub UserForm_Terminate()
Unload Me
A.Show
End Sub
After:
opening B (from A)
closing B and returning to A
and then opening B again
The close button on B ceases to work.
UserForm A is a menu form that leads to several others, so navigating back and forth between the menus is a pretty basic requirement. This behaviour is reproducible for every form linked from A, as well as for tertiary forms that open from those.
Given my target demographic is of the older generation, I want my UserForms to be intuitive to use, which means preserving regular close button functionality.
Does anyone have any info on this? It may be that my google-fu is lacking, but I can't seem to find anyone who has had the same issue. Any input at this stage is greatly appreciated!
Use a variable to refer to the 2nd Userform in the first as this gives you greater control over the second forms status - you can unset the variable after you have closed the 2nd form and returned to the event handler that instantiated it in the first place. This guarantees that each time you click the button to launch UserForm2 that you are working with a 'fresh copy'.
Also you should use the QueryClose event - see MSDN. This event:
Occurs before a UserForm closes
You need to be able to be able to control the re-activation of UserForm1 before the form is disposed.
The Terminate event is slightly different:
Occurs when all references to an instance of an object are removed from memory by setting all variables that refer to the object to Nothing or when the last reference to the object goes out of scope.
In the sample code below I am getting the correct behaviour using a reference to UserForm2 and handling QueryClose.
In this sample code I am using UserForm1 and UserForm2 but you can substitue for A and B in your app:
Code in UserForm1:
Option Explicit
Private m_frm2 As UserForm2
Private Sub CommandButton1_Click()
Me.Hide
Set m_frm2 = New UserForm2
m_frm2.Show
Set m_frm2 = Nothing
End Sub
Code in UserForm2:
Option Explicit
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
UserForm1.Show
Unload Me
End Sub
I'm trying to make a standardized process for updating a particular worksheet. I want no user control except for the functions I give them. To do that I have locked sheets and then forms that load with certain macros. One form is designed to remove data from the sheet. It works fine as written and tested, but I've tried to update it so that if you open it without any relevant data to remove, it spits out a dialogue box and then uses Unload Me to close the form. This closes the form but then excel throws an error:
Run-time error '91': Object variable or With block variable not set
The form is loaded from a module that only has the one line:
MyForm.Show
This is where excel is throwing the error from. On initialization of the form, a combobox is filled with values based on the data in the sheet. If the combobox is empty after loading, the form is supposed to throw the dialogue box and then close.
If ComboBox.ListCount = 0 Then
MsgBox "No Data"
Unload Me
End If
How can I perform the check on load without having the error thrown from the Module?
This doesn't actually answer your question. But what I suggest is do the checking in your module code before you actually load the form. Something like:
Sub LoadForm()
If Sheets("Sheet1").Range("A1") = "" Then '<~~ your condition here
MsgBox "No Data"
Else
MyForm.Show
End If
End Sub
Another way would be to place the Unload Me in the Activate event:
Private Sub UserForm_Activate()
...
If ComboBox.ListCount = 0 Then
MsgBox "No Data"
Unload Me
End If
End Sub
The problem happens when you try and unload the userform from within it's initialize event. Because the object hasn't finished initialization yet, it cant be unloaded. The best ways to get around this are either to check conditions before you try to initialize the form, or put your checks and subsequent unload statements into the activate event of the userform. Activate is called whenever the form goes from being hidden to visible, which happens after the form has been completely initialized.
Sub RunForm()
On Error GoTo error
UserForm1.Show
error:
End Sub
I use the Unload.Me function to close a userform.
I have two userforms, when I close one, the second userform will close automatically as well.
I want try to keep the previous userform open.
A quick workaround, try to specify the exact form you are unloading.
i.e. use Unload UserForm2
If that doesn't help, check if the forms are modal forms. If not, set them to modal.
I tried adding a subsequent instruction in the same sub procedure that called/showed Userform2 (thinking that it might not close Userform1 until it finished the rest of the code after Userform2.show). Instructions like assigning a random value to a random variable did not work, but making a message box pop up did work. For example in the sub procedure calling userform2 you might try:
Userform2.show
Msgbox("Userform2 has already closed. Close this message box to see Userform1.")
This seems despotic to me too, but it worked.
This's caused by a code that executes when the form that you don't want to close becomes the active form.
It's 2022 now, but anyway, for those interested.
You do not need a messagebox, you can just set focus to an item in userform1.
That way you avoid having to click OK to close the messagebox