I have a series of ComboBoxes that are populated based on the previous ComboBox selection. So for example, ComboBox3 is populated based on the value selected in ComboBox2. The "trigger" for populating ComboBox3 is the DropButtonClick action. I have a message box pop up when there is no value in ComboBox2. This is working successfully - code below.
If Me.ComboBox2.ListIndex = -1 Then
MsgBox "Please select all preceding comboboxes"
ComboBox3.Value = ""
Exit Sub
Else
sh.Range("B2") = Me.ComboBox2.Value
End If
My issues is once the Message Box appears (as a result of there being no value in ComboBox2) ComboBox3 still displays drops down values. Is there a way to undo the ComboBox3 DropButtonClick Event when there is no value in ComboBox2, so that ComboBox3 never drops down?
You can immediately close the drop-down window of the combo-box by simulating the "ESC" key:
MsgBox "Please select all preceding comboboxes"
ComboBox3.Value = ""
' close immediately the combo's dropdown window
SendKeys "{ESC}{ESC}"
Is this something for you?
If Me.ComboBox2.Value = "" Then
ComboBox2.SetFocus
Else
sh.Range("B2") = Me.ComboBox2.Value
End If
When you want to click on the dropbutton of combobox3 it automaticly goes back to combobox2.
Related
I have the following two codes on a button: The (first code) aims to submit value of option button into worksheet cell:
For Each FormControl In Me.Controls
'Check only OptionButtons
If TypeName(FormControl) = "OptionButton" Then
'Check the status of the OptionButton
If FormControl.Value = True Then
'Set a variable equal to the Caption of the selected OptionButton
OptionButtonValue = FormControl.Caption
'We found the selected OptionButton so exit the loop.
Exit For
End If
End If
Next
'Store input in the worksheet
Sheets("Answer Sheet").Range("E80").Value = OptionButtonValue
To ensure an option button is selected before proceeding to next form, i have
the 'following code (second code):
Dim cnt As Integer
For Each ctl In Me.Controls
If TypeName(ctl) = "OptionButton" Then
If ctl.Value = True Then cnt = cnt + 1
End If
Next ctl
If cnt = 0 Then MsgBox "Hello " & CStr(ThisWorkbook.Sheets("AccessReg").Range("D630").Value) & ", you
have not selected an answer! Please select an answer to proceed to next question. Thank you.",
vbInformation, "Please select an answer!" Else ScoreBoards.Show
Unload Me
MY CHALLENGES
Both codes above exists in my forms i.e. questions 1, 2, 3,...respectively, but can't seem to get the second code (that, which ensures an option button is selected before next form can be opened) to work by adding 'unload me' to the end of it, yet i want the form closed before proceeding to next. Adding 'unload me', pop-up the msgbox (which tells me to select an answer) but when i clicked okay on the msgbox, it closes the form (Question1) instead of returning me to same form to ensure an answer is clicked, then proceed to next form (Question2). However, when i remove the 'unload me', things work fine i.e. the msgbox popup when selection not made, returns to same form when okay on msgbox is clicked, and opens next form when selection made.
What i really want is: i want the second code above (which ensures an option button is selected before next form can be opened) to work as programmed and each form closed before proceeding to the next form.
Thank you in advance
PS:
The concept summary is:
On a userform (Question1), select an option button and submit the value to worksheet
Ensure an option button is selected:
if selected and button clicked, the next form(being Question2) should open
if not selected and button clicked, the msgbox (which tells me to select an answer), should popup
clicking okay on the msgbox, should return me to same form (Question1) so that i can select an option and proceed.
Try adapting your second code in the next way, please:
If cnt = 0 Then MsgBox "Hello " & _
CStr(ThisWorkbook.Sheets("AccessReg").Range("D630").Value) & ", you have not selected an answer! Please select an answer to proceed to next question. Thank you.", vbInformation, "Please select an answer!"
Exit For
Else
ScoreBoards.Show
Unload Me
End if
I created an userform with 2 textboxes, 3 buttons and a listbox with two columns. If I click on an entry in the listbox, the list entry which is selected gets transfered to two different textboxes.
See the code below:
Private Sub NewSourceListBox_Click()
Dim i As Integer
'Show the selected data in the corresponding text boxes
For i = 0 To NewSourceListBox.ListCount - 1
If NewSourceListBox.Selected(i) Then
'Hide the add button and show the change button
NewSourceBtnChange.Top = 168
NewSourceBtnChange.Visible = True
NewSourceBtnAdd.Visible = False
NewSourcesIDTxtBox.Value = NewSourceListBox.List(i, 0)
NewSourcesSourceTxtBox.Value = NewSourceListBox.List(i, 1)
'Pass on the selected item row to another subroutine
selectedItem = i
Exit For
End If
Next i
End Sub
selectedItem is a global variable created in another module, which I need to use in another subroutine. If I change the entries in the text boxes in the userform and click the change button the following code gets executed.
This code:
Private Sub NewSourceBtnChange_Click()
Dim row As Integer
row = 6257 + selectedItem
'Change the selected data in the list box to the corresponding data in the text boxes
Sheets("Datensätze").Range("A" & row).Value = NewSourcesIDTxtBox.Value
Sheets("Datensätze").Range("B" & row).Value = NewSourcesSourceTxtBox.Value
'Another duplicate entry to make vLookup work
Sheets("Datensätze").Range("C" & row).Value = NewSourcesIDTxtBox.Value
Unload Me
'Unload the new entry user form to repopulate the comboboxes
Unload NewEntryUserForm
NewEntryUserForm.Show
End Sub
If I watch this step by step via F8 then the following happens: As soon as I click the "NewSourceBtnChange" button the corresponding subroutine NewSourceBtnChange_Click() starts. When I reach Sheets("Datensätze").Range("A" & row).Value = NewSourcesIDTxtBox.Value the program jumps to the NewSourcesListBox_Click() routine, executes it two times and jumps back to Sheets("Datensätze").Range("B" & row).Value = NewSourcesSourceTxtBox.Value, then executes the NewSourcesListBox_Click() routine for another two times and jumps back again to the last entry Sheets("Datensätze").Range("C" & row).Value = NewSourcesIDTxtBox.Value and executes the rest of the NewSourceBtnChange_Click() routine.
This makes it impossible to get the new data from the text boxes into their destined cells.
Edit:
Just to make it easier to reconstruct the described behavior, I exported the userform and its code and uploaded it.
Here is what your code is going through (just the important parts):
1) While initializing userform, it populates the listbox with:
.RowSource = "Datensätze!A6257:B" & 6257 + Sheets("Datensätze").Range("F2").Value - 1
2) When you click listbox item, you trigger NewSourceListBox_Click code, populate textboxes with selected items and set item index number to selectedItem variable. (which is handled wrong. You need to declare selectedItem as public variable.)
3) Then you click NewSourceBtnChange which triggers NewSourceBtnChange_Click. It sets row number of your selected item:
row = 6257 + selectedItem
Then you change this very cell using:
Sheets("Datensätze").Range("A" & row).Value = NewSourcesIDTxtBox.Value
which you have used to populate your listbox with:
.RowSource = "Datensätze!A6257:B" & 6257 + Sheets("Datensätze").Range("F2").Value - 1
At this moment, listbox is populated again, but this time it has been already selected so it triggers the NewSourceListBox_Click code.
Whenever you change the RowSource range, if the listbox is selected, it will behave like this. So you need to deselect the listbox item to workaround this.
TL;DR:
After:
row = 6257 + selectedItem
Insert:
NewSourceListBox.Selected(NewSourceListBox.ListIndex) = False
Also to be able to get selectedItem value in other subs, you need to declare it as public variable. Outside of subs, on the very top, insert:
Public selectedItem As Long
I have an MS-Word 2013 document with several (legacy) formfields; some text boxes, some comboboxes. The first list item on all of the comboboxes is "(select one)" to let the end user know they need to make a selection (I did not draft or design this document, I've just been asked to write the VBA code for it). So I coded each to give a simple VBA message box, ran on exit, if that first selection was not changed, for example:
Public factor1 As Integer
Sub MyFormFieldFactor1()
If ActiveDocument.FormFields("cbofactor1").Result = "(select one)" Then
MsgBox "You must select either Yes or No."
Exit Sub
End If
If ActiveDocument.FormFields("cbofactor1").Result = "Yes" Then
factor1 = 1
Else
factor1 = 0
End If
End Sub
The word document automatically goes to the next formfield when you click ok on the message box. Through VBA, I want it to stay on the current formfield when "(select one)" is chosen. Bonus points if it stays on the current field and pulls up the list selection automatically.
Will this work:
If ActiveDocument.FormFields("cbofactor1").Result = "(select one)" Then
MsgBox "You must select either Yes or No."
ActiveDocument.FormFields("cbofactor1").SetFocus()
Exit Sub
End If
You can auto drop the list with something like:
SendKeys "%{down}", True
DoEvents
Full code:
If ActiveDocument.FormFields("cbofactor1").Result = "(select one)" Then
MsgBox "You must select either Yes or No."
ActiveDocument.FormFields("cbofactor1").SetFocus()
SendKeys "%{down}", True
DoEvents
Exit Sub
End If
I need to show denominations based on selection in combo box in my access form.
The tricky thing here is that I need to show immediately after selecting in the combo box (without saving it). This one is working just after I save my selection.
If cmb_Main_Impact.Value = "Productivity" Then
Me.txt_Units = "minutes"
End If
If cmb_Main_Impact = "Quality" Then
Me.txt_Units = "number of errors"
End If
That code should work fine. You want to put it in the combobox on change event.
Also added an elseif so there isnt multiple if and end ifs. Put that code in in the userform that has the combo box.
So your code will look like.
Private Sub cmb_Main_Impact_Change()
If cmb_Main_Impact.Value = "Productivity" Then
Me.txt_Units = "minutes"
elseIf cmb_Main_Impact = "Quality" Then
Me.txt_Units = "number of errors"
End If
End Sub
I'm making an add records form for a spreadsheet of mine, and let's say that I want one of the controls to be a dropdown that is populated by unique entries under a certain column "type". However, I want to also make it such that the dropbox always has a initial option to "add new type" and upon such selection, it becomes a regular text box. How would I do this in VBA?
You cannot change a control type at run time. The easiest thing to do is create a combo box and a text box. Set the text box visibility to false. Then in the onchange event of the combo box your code will unhide the text box and hide the combo box. You will also need a save button so that when it is clicked it will add the option to the drop down, clear the text box, hide the text box, hide the button and unhide the drop down.
Okay, so here's my idea of how to tackle this.
Create 2 hidden elements (Visibility = False), one a TextBox and one a CommandButton.
Populate your ComboBox with the values from the sheet under column "type"
Add one more entry AddItem with wording such as "Add new item..."
When the user selects "Add new item...", change the Visibility of the TextBox & CommandButtons to True
When the user clicks the CommandButton, add the phrase to the column and add a new element to the ComboBox
I have created a mockup UserForm and code that does a little more than just this; it also styles the user entry to sentence case (consistency purposes) and checks to make sure the value isn't already in the column.
Excel Sheet with "type" column
UserForm with name labels
UserForm Code
Private Sub bAdd_Click()
Dim str As String
Dim rng As Range
Dim ro As Integer
'Makes sure there is an entry, adds it to the Sheet and then updates the dropdown
If Len(Me.tbNew) > 0 Then
'Converts user entry to "Sentance Case" for better readability
str = StrConv(Me.tbNew, vbProperCase)
'Finds out if the entry already exists
Set rng = Sheets(1).Range(Sheets(1).Cells(2, 1), Sheets(1).Cells(Sheets(1).Cells(Sheets(1).Rows.Count, 1).End(xlUp).Row, 1))
On Error Resume Next
Err.Number = 0
'Searches for duplicate; if found, then ListIndex of cbColor is modified without inserting new value (prevents duplicates)
ro = rng.Find(str, LookIn:=xlValues, LookAt:=xlWhole).Row
Debug.Print Err.Number
'Ensures a user doesn't add the same value twice
If Err.Number > 0 Then
Sheets(1).Cells(Sheets(1).Cells(Sheets(1).Rows.Count, 1).End(xlUp).Row + 1, 1) = str
Me.cbColor.AddItem StrConv(Me.tbNew, vbProperCase), Me.cbColor.ListCount - 1
Me.cbColor.ListIndex = Me.cbColor.ListCount - 2
Else
Me.cbColor.ListIndex = ro - 2
End If
'Resets and hides user form entries
Me.tbNew = vbNullString
Me.tbNew.Visible = False
Me.bAdd.Visible = False
End If
End Sub
Private Sub bClose_Click()
Unload Me
End Sub
Private Sub cbColor_Change()
'Visibility is toggled based on if the user selected the last element in the dropdown
Me.bAdd.Visible = Me.cbColor.ListIndex = Me.cbColor.ListCount - 1
Me.tbNew.Visible = Me.cbColor.ListIndex = Me.cbColor.ListCount - 1
End Sub
Private Sub UserForm_Initialize()
'Populate from the sheet
For a = 2 To Sheets(1).Cells(Cells(Sheets(1).Rows.Count, 1).End(xlUp).Row, 1).Row
Me.cbColor.AddItem Sheets(1).Cells(a, 1)
Next
'Add option for new type
Me.cbColor.AddItem "Add new type..."
End Sub