I have created a userform that has two buttons on it. One is called CmdCon6 and the other is called CmdLbs6. When clicked, they are suppose to close the current userform, pull up another userform, and pull values from the 4th column in sheet18 and add them to a combobox named x48 (both of the new userforms have a combobox named x48)in the new userform. The range of cell values to be added to the combobox x48 will flucuate, but never exceed 20 (hence why I added a loop). Everything works great and does what it is suppose to do when I click the CmdCon6 button, but when I click the CmdLbs button, it gives me a run-time error '70' Permission denied and highlights the 20th line of code (line between the If and end if in the Sub CmdLbs_Click()).
I have tried to change the name of the combobox x48 in the frmInputLbs6 userform and keep it as x48 for the frmInputCon6 userform, but I still received the same error.
Any suggestions to fix this issue? I'm stumped, and can't think of a way around it. Thanks in advance!
Private Sub CmdCon6_Click()
Unload Me
For x = 1 To 20
If Sheet18.Cells(x, 4).Value <> "" Then
frmInputCon6.x48.AddItem Sheet18.Cells(x, 4)
End If
Next x
frmInputCon6.Show
End Sub
Private Sub CmdLbs6_Click()
Unload Me
For x = 1 To 20
If Sheet18.Cells(x, 4).Value <> "" Then
frmInputLbs6.x48.AddItem Sheet18.Cells(x, 4)
End If
Next x
frmInputLbs6.Show
End Sub
Controls on UserForms are private by default. You need to access them through the Controls collection:
Private Sub CmdLbs6_Click()
Unload Me
For x = 1 To 20
If Sheet18.Cells(x, 4).Value <> "" Then
frmInputLbs6.Controls("x48").AddItem Sheet18.Cells(x, 4)
End If
Next x
frmInputLbs6.Show
End Sub
I'd also note that although you mention that "they are suppose to close the current userform", this isn't what happens. Your forms also aren't actually being fully unloaded until the other form is closed. The .Show method defaults to modal so in the code above frmInputCon6 doesn't fully unload until after frmInputLbs6 is closed.
Just something to keep in mind, because it really messes up your event stack. You can see the results by with this simple test code. Add UserForm1 and UserForm2, and put a button on each of them and the following code:
UserForm1:
Private Sub CommandButton1_Click()
Unload Me
UserForm2.Show
End Sub '<--Put a breakpoint here.
Private Sub UserForm_Terminate()
Debug.Print "UserForm1 closed"
End Sub
UserForm2:
Private Sub CommandButton1_Click()
Unload Me
UserForm1.Show
End Sub '<--Put a breakpoint here.
Private Sub UserForm_Terminate()
Debug.Print "UserForm2 closed"
End Sub
Put a breakpoint on the End Subs of each Click() event, fire up one of the forms and hit the buttons to hop back and forth a few times. Then close one of the forms and count how many times you hit the breakpoints before you actually exit.
Related
I'm using Office Professional Plus 2019. I have a ListBox that sometimes freezes the macro. The UserForm (AffDateSelector) has a ListBox (DateSelectionList) and a Button (Continue). The UserForm is called from the driving Sub with AffDateSelector.show. The code for the form is below:
Option Explicit
Private Sub Continue_Click()
Dim lngCurrItem As Long
'Assign the selected value to the public variable strClassDate.
For lngCurrItem = 0 To DateSelectionList.ListCount - 1
If DateSelectionList.Selected(lngCurrItem) = True Then
strClassDate = DateSelectionList.List(lngCurrItem)
End If
Next lngCurrItem
'Unload the form and return to the calling Sub.
Unload Me
End Sub
Private Sub DateSelectionList_Click()
End Sub
Private Sub UserForm_Click()
End Sub
Private Sub UserForm_initialize()
'Load ListBoxAccounts with the public variable strDateArray
With DateSelectionList
.List = strDateArray
End With
'Default the first row in DateSelectionList to be selected.
DateSelectionList.Selected(0) = True
End Sub
I've been using F8 to step through the code. When the form is shown, the UserForm_initialize() sub is executed and the data display properly. If the user does nothing else except click the Continue button, the Continue_Click() sub gets executed, the variable strClassDate is populated, control is returned to the calling sub and all is well.
The problem comes when the user selects an item other than the one defaulted in the list. Once the user clicks on the ListForm, the sub DateSelectionList_Click() is executed, but there's nothing in that sub, so the macro freezes. If I put in "dummy code" into DateSelectionlist_Click() (e.g. strClassDate = strClassDate) that line is executed and then the macro freezes when the End Sub statement is executed.
How can I allow the user to click on a non-defaulted item in the list, keep the form displayed, and wait for the Continue button to be pressed?
The code was fine. I had a lot of windows open and the pop-up didn't appear I was running the code from the VB editor but the pop-up never appeared. When I pressed Alt + Tab it didn't appear in that list either.
I have 2 userforms, Userform_1 contains many TextBoxes (TextBox1, TextBox2, TextBox3, .....) & in Userform_2 I have 1 TextBox where user can enter value. Now I need to pass the User entered value in Userform_2 to be shown/stored in its respective triggering TextBox event in Userform_1. So when User want to pass in TextBox3 (Userform_1) then he/she will just use double_click trigger (activate Userform_2) & pass value which should be stored in TextBox3 only.
I tried this:
In Userform_1
Private Sub TextBox3_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
On Error Resume Next
UserForm2.Show
End Sub
In Userform_2
Private Sub CommandButton1_Click()
On Error Resume Next
If UserForm1.TextBox1.Value = "" Then UserForm1.TextBox1.Value = ComboBox1.Value
If UserForm1.TextBox2.Value = "" Then UserForm1.TextBox2.Value = ComboBox1.Value
If UserForm1.TextBox3.Value = "" Then UserForm1.TextBox3.Value = ComboBox1.Value
Unload Me
End Sub
Problem is that it will display entered value in any TextBox which is empty & not specifically in TextBox3. Any insight would be helpful.
Your code is doing exactly what you have asked it to do (not what you want it to do). Based on your description above, I offer the following (not tested).
In Userform_1
Private Sub TextBox3_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
UserForm2.Show
TextBox3.Value = UserForm2.ComboBox1.Value
End Sub
In Userform_2
Private Sub CommandButton1_Click()
Me.Hide
'Note not unloading, this means that the userform is still in memory and you can access the values after it is hidden.
' Also, hiding the form will return control back to the UserForm1 for further processing.
End Sub
And avoid using On Error, especially On Error Resume Next, all you are doing is hiding the bugs, not dealing with them. If you can anticipate that your code is going to cause an error, deal with it before that piece of code.
Thanks ADJ...
Your concept is good but it doesn't quite fulfill the requirement, just hiding the Userform doesn't remove/clear the entered value for next entry & reopening it again shows last entered value. I can write a code to blank it but then I have too many textboxes.
I used your concept of only calling required Userform from a specific TextBox...
Wrote below code, fits my requirement:
UserForm_1:
created hidden TextBox1 in UserForm_2 for identifier
UserForm2.TextBox1.Value = "<random identifier value>"
UserForm_2:
If TextBox1.Value = "<random identifier value>" Then
UserForm1.TextBox3.Value = "<User Input>"
End If
So this way I get to assign & call only identified TextBoxes.
I have a sub called as sub1() which activates the userform1 through the command userform1.show()
This userform1 has a button called as continue. On clicking that button continue - A Macro called as Private Sub continuebutton() gets activated.
I want to program in such a way that it redirects to the line after userform1.show() in sub1().
Is it something that can be done?
Theoretically, what you want is possible, if you do it like this:
In the UserForm:
Private Sub btnContinue_Click()
flag = True
Debug.Print "I continue ..."
sub1
End Sub
In a module:
Public flag As Boolean
Public Sub sub1()
If flag Then
Debug.Print "sub 1 continues here..."
Else
flag = False
UserForm1.Show
Exit Sub
End If
End Sub
It will work exactly as intended, BUT it is not a good practice to work this way. (Some people may throw stones at you for using public variables at all in VBA.) Here are two articles, that give better ideas:
https://rubberduckvba.wordpress.com/2017/10/25/userform1-show/
Disclaimer - this one is mine:
http://www.vitoshacademy.com/vba-the-perfect-userform-in-vba/
On the form properties for userform1, set its "Modal" property to true.
When the form opens, it will have exclusive focus, and the code in sub1 will not continue running until after it closes. This may be the solution you need.
In the code below, the msgbox will only appear once userform1 closes:
sub sub1()
userform1.show()
msgbox "Now continuing with sub1"
end sub
No way as long as you show the form.
If you show the form modal, the calling routine continues if (and only if) the form is closed.
If you show the form non-modal, the code continues to run directly after the show - so it's already done.
So either you have to close the form when the user clicks the "continue..." button to let the calling macro continue or you have to split your code into two routines and call the second on button-click.
You can change your Sub1 as follows:
Sub sub1(Optional Continue As Boolean)
If Continue = True Then
DoSomeStuff
Exit Sub
End If
userform1.show
End sub
And then, you can call your sub1 using:
Private Sub continuebutton()
Call sub1(True)
End Sub
Hope it helps
If you don't want to go with the 'Modal Form' solution, you could add a subroutine to your main module, and call it when required. So, in userform1, you have:
sub sub1()
userform1.show()
end sub
public sub sub2()
msgbox "Now continuing..."
end sub
And then in userform1, set some code on its onClose event:
Private Sub continuebutton()
Call sub2()
end sub
In VBA for excel, I have a userform then I want this to show only for 1 instance. Even if the user re-open it, it won't open again. Is there any code for it? well, I'm also using this code for my login:
Private Sub UserForm_Initialize()
User.Caption = Environ("Username")
End Sub
I'm thinking if i can use this code in my problem. Hoping for a quick response. thanks guys, you're awesome!
Yes, it's possible.
You have to add new sheet. In a cell A1 type 0 (zero), then hide it. In a code which calls UserForm, use this:
Sub ShowMyForm()
If ThisWorkbook.Worksheets("HiddenSheet").Range("A1")=0 then MyUserForm.Show
End Sub
In a form:
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
ThisWorkbook.Worksheets("HiddenSheet").Range("A1")=1
ThisWorkbook.Save()
DoEvents
End Sub
If you don't want to add an extra sheet just to store one bool, you can set a custom document property like this:
Private Sub Workbook_Open()
On Error Resume Next
Dim test As Boolean
test = Me.CustomDocumentProperties("UserFormShown").Value
If Err.Number = 0 Then Exit Sub
UserForm1.Show
Me.CustomDocumentProperties.Add "UserFormShown", False, msoPropertyTypeBoolean, True
End Sub
If the property hasn't been set yet it will throw an error, so trapping an error lets you know if you've set the property (and shown the form).
I have a sub that is activated from a button on a userform. The basic procedure from the click is
1) Run my sub based off of user inputs
2) Select results sheet
3) Display my results
4) Unload my userform
I've run into a problem because I want to try and put bounds on an user input value and if the user inputs something out of the range a message box will pop up notifying them of the range. I've been able to accomplish this simple task through the use of an if/then loop. After the user exits out of the message box I want to keep the userform displayed along with the original user inputs and allow the user to change their input. But currently after the user clicks 'ok' on the message box, my click sub continues its procedure and unloads my userform and selects my results worksheets. Is there a simple one line code that I can put after my msgbox state to preserve the userform instead of making the user re-enter their values?
EDIT - The general gist of my code is as follows:
Private Sub CommandButton1_Click()
PropertySearch.Search
ActiveSheet.Name = "SearchResult"
Cells(1, 1).Select
Unload ILsearch
End Sub
Sub Search()
If (TextBox1 And TextBox2 <= 8) And (TextBox1 And TextBox2 > 0) Then
'
'Performs my desired function
'
Else: MsgBox ("Database only includes ionic liquids with a maximum of 8 carbons in cation")
End If
I would turn Search into a function which returns true or false if the input is within bounds or not:
Function Search() AS Boolean
If (TextBox1 And TextBox2 <= 8) And (TextBox1 And TextBox2 > 0) Then
Search = True
Else
Search = False
EndIf
End Function
then you just exit the sub if input does not meet your bounds:
Private Sub CommandButton1_Click()
If(Not PropertySearch.Search) Then
MsgBox("your error message here")
Exit Sub
EndIf
' rest of the routine
End Sub
There are about a thousand and one ways around this - the question is what behavior do you want the form to have?
Do you want it to self close after a certain amount of time?
Check out this example of timer 1
Or look into Application.Ontime
Application.OnTime Now + TimeValue("00:00:10"), "unloadForm"
Where "unloadForm" is a sub in a normal module
Sub unloadForm()
Unload ILsearch
End Sub
Do you want to add a close form button?
Private Sub CommandButton1_Click ()
Unload Me
End Sub
Do you want the user to close the form manually with the red X in the top corner? Simply delete the line with Unload
Do you want to display a modal popup window that freezes Excel until closed and then your form unloads? Try addging MsgBox "Hello" before you unload the form.
And many many many more!
For example, I have several forms that use keyboard events. Escape can clear all fields and hide/unload the form while Enter does the same thing but also write the values to a table, Delete only clears the active control and doesn't hide the form, up and down arrows cycle through forms hiding the current and showing the previous/next while left and right function like tab/shift + tab.