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
Related
I'm trying to do what, I think, ought to be the simplest of things, but I can't get it to work. i have an MS Word document with a number of legacy drop-down and text fields:
The first option in each drop-down is "Select ...", and if a user tabs out of one of the drop-downs without choosing something other than the first "Select ...", I want a msgbox to appear to tell them to make a selection, which works. What doesn't work, is that after the user dismisses the msgbox, I want the insertion point to return to the drop-down that they didn't select.
I understand that VBA has "timing issues", and from what I've read, one way to address these timing issues is to call the "return" macro from the validation macro. So I've written two macros:
Sub Validate()
' Dim strBookmark As String
' strBookmark = Selection.Bookmarks(1).Name
10: If (bool_debug) Then MsgBox ("NotSelected() - 10: strBookmark = " & strBookmark)
With ActiveDocument
If (strBookmark = "Locality") Then
Call Salary_Step
ElseIf (strBookmark = "Series") Then
20: If (bool_debug) Then MsgBox ("NotSelected() - 20: .FormFields(strBookmark).Name = " _
& .FormFields(strBookmark).Name)
If ((Len(.FormFields(strBookmark).Result) <> 4) Or (Not IsNumeric(.FormFields(strBookmark).Result))) Then _
MsgBox ("Please enter a 4 digit number.")
Call GoBackToPrevious(.FormFields(strBookmark).Name)
ElseIf (.FormFields(strBookmark).DropDown.Value = 1) Then
MsgBox ("Please select a " & Replace(Selection.FormFields(strBookmark).Name, "_", " ") & ".")
Call GoBackToPrevious(.FormFields(strBookmark).Name)
End If
End With
End Sub
and
Sub GoBackToPrevious(strPreviousField)
10: If (bool_debug) Then MsgBox ("GoBacktoPrevious - 10: strPreviousField = " & strPreviousField)
ActiveDocument.Bookmarks(strPreviousField).Range.Fields(1).Result.Select
End Sub
But when I tab out of any of the form fields, the insertion point jumps to the next form field and not back to the one that I just tabbed out of.
I know from the debug code that GoBackToPrevious is being passed the name of the current form field, but MS Word advances to the next field regardless.
I'd really appreciate it if someone can tell me how make MS Word return to and select the drop-down the user did not select appropriately instead of jumping to and selecting the next form field in the document.
Thank you.
P James Norris
EDIT:
Based on #TimothyRylatt comments, I have modified my macro and when they're called.
I have edited Validate as above (commenting out the Dim the strBookmark assignment, and I call it "on entry" to the next form field.
strBookmark is Dimed on the module's declaration section:
Option Explicit
Const bool_debug As Boolean = True
Const str_password As String = "###" ' I have a different password
Public strBookmark As String
and "on exit" from the "current" form field, I attempt to store the "current" bookmark name:
Sub StoreBookmark()
strBookmark = Selection.Bookmarks(1).Name
10: If (bool_debug) Then MsgBox ("StoreBookmark() - 10: strBookmark = " & strBookmark)
End Sub
which I call from the current form field "on exit".
But when I tab out of the current form field to the next form field, the insertion point doesn't go back to the "current" but instead stays in the next form field.
Anyone have any other suggestions/insights?
Thanks,
P James Norris
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 have a textbox on a userform. If the user fails to enter anything in this textbox, I need to trap that to force an entry. I can do this easily enough, but after notifying the user tht they need to make an entry, I want the focus to return to the textbox. Right now, it doesn't do that. Here is my code:
Private Sub txtAnswer_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Select Case KeyCode
Case 13:
If Me.txtAnswer.Value = "" Then
temp = MsgBox("You need to enter an answer!", vbCritical + vbOKOnly, "No Answer Found!")
Me.txtAnswer.SetFocus
Else
recordAnswer
End If
End Select
End Sub
This code works fine in that the message box pops up if the textbox is left blank. After clearing the message box, if I hit enter immediately again, the message box reappears, suggesting that the focus is on the textbox. However, if I try to enter a character (like the number '1' for example) nothing appears in the textbox.
Can anybody suggest how I can get the focus back on this textbox in a way that will allow the user to enter data? Thank you!
Why are you not using an 'ok' button to complete the action?
You should not bother users with messages while they are typing in a form. Do it at the end.
Private Sub OK_Click()
'// Validate form
If txtAnswer.Text = vbNullString Then
MsgBox "You need to enter an answer!", vbExclamation, "No Answer Found!"
txtAnswer.SetFocus
Exit Sub
End If
'// You have reached here so form is correct carry on
recordAnswer
End Sub
If you really want to use the behaviour you asked for then try this:
Private Sub txtAnswer_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
Select Case KeyCode
Case 13:
If Me.txtAnswer.Value = "" Then
temp = MsgBox("You need to enter an answer!", vbCritical + vbOKOnly, "No Answer Found!")
KeyCode = 0
Else
recordAnswer
End If
End Select
End Sub
The problem is that in your code you are setting focus but the enter key is firing afterwards. You don't need to set focus because the textbox already has the focus you just need to cancel the enter key.
The other answers seem really complicated. I had a similar problem and really wanted a text warning. It seemed easier for me to just make an invisible label on the form that would show up if the input was incorrect. I also made the background of the label red so that the user would notice something was wrong. Doing it this way kept the cursor visible and right where they left off.
Public Function amount(ByRef cont As MSForms.TextBox) As Integer
'makes sure that a number is used
'could change to account for decimals if necessary
Dim i As Long
On Error Resume Next
i = 0
If (cont.Value = "") Then Exit Function
Do While i < 1000000
If (cont.Value = i) Then
UserForm1.Label257.Visible = False
Exit Function
End If
i = i + 1
Loop
UserForm1.Label257.Visible = True
amount = 1
End Function
Public Sub qty_BeforeUpdate(ByVal Cancel As MSForms.ReturnBoolean)
If amount(UserForm1.qty) = 1 Then
Cancel = True
End If
End Sub
I hope this helps other who run into this problem later on.
Looking at the above code, I assume the i counter is to keep it going? Sorry a bit rusty, been a few years since I've done code.
At any rate, if thats the case you could always run it while i=0, do (or while true).
Sorry, first time posting here, hope that made sense.
I am fairly new to VBA, and have been searching the forum for one particular code.
I have a workbook with multiple different graphs. I also have a UserForm with a popbox box where the User can select the city and click enter. What I would like to do is Hide all the Worksheets with the graphs, and when the user selects one particular city, I would like Excel to show that particular Graph. For Example, The user Selects Vancouver, and Excel will show the worksheet Pertaining to Vancouver.
I would also Like to Have a done button, where if the user clicks that, it will go back to the sheet where the UserForm is.
Private Sub ENT_Click()
'Error if you do not select the City
If Me.City.Value = "" Then
MsgBox "Please Select a City", vbExclamation, "Select a City"
Me.City.SetFocus
Exit Sub
End If
If Me.City.Value = "Mississauga" Then
Sheets("Sheet4").Visible = True
Sheets("Sheet4").Activate
End If
End Sub
Every time I run the code, with the Worksheets hidden, Or UnHidden, I keep getting a Subscript out of Range error.
Thank you again for the help
It was an error with the way I was labeling my Worksheet. The Code should have actually been:
Private Sub ENT_Click()
'Error if you do not select the City
If Me.City.Value = "" Then
MsgBox "Please Select a City", vbExclamation, "Select a City"
Me.City.SetFocus
Exit Sub
End If
'Change "Mississauga" to the item in your ComboBox
If Me.City.Value = "Mississauga" Then
Worksheets(4).Visible = True
Worksheets(4).Activate
End If
End Sub
I want when you hit 'send' you are presented with a form. This I am developing in Outlook 2010.
Is there a way to populate a combo-box with a list of Macros?
Public Sub Confidential()
Application.ActiveInspector.CurrentItem.Sensitivity = olConfidential
Application.ActiveInspector.CurrentItem.Save
Set MsgSub = Outlook.Application.ActiveInspector.CurrentItem
Set objMail = Outlook.Application.ActiveInspector.CurrentItem
Subject = MsgSub.Subject
MsgSub.Subject = Subject + " - [CONFIDENTIAL]"
Email = objMail.HTMLBody
info = " <html> <body> <FONT color=#666666> <font-size: 11px> <p></p> AUTO TEXT: This message has been marked as 'CONFIDENTIAL' please treat it as such </body> </font> </html>"
objMail.HTMLBody = Email + info
End Sub
Private Sub Sens_DropButtonClick()
Sens.AddItem "Confidential()"
Sens.AddItem "Normal()"
End Sub
Public Sub Send_Click()
Set objMail = Outlook.Application.ActiveInspector.CurrentItem
objMail.Send
End Sub
Would I be right in thinking that this is a public sub?
My goal is when you hit the 'send' button a form will appear with a dropdown box, this has 4 options which are the sensitivity options you can use with the emails, except I have created them as macros and added code on them (to add to subject and footer of message) but I wont it so a user is forced to make a selection, hence why I am creating this form instead of having the 4 buttons.
My goal is when you hit the 'send' button a form will appear with a dropdown box, this has 4 options which are the sensitivity options you can use with the emails, except I have created them as macros and added code on them (to add to subject and footer of message) but I wont it so a user is forced to make a selection, hence why I am creating this form instead of having the 4 buttons. – Rsmithy 36 mins ago
If I understand you correctly, Yes it is possible to do what you want. See this Example
Let's say you have a userform with 4 options A,B,C and D and the userform code is
Private Sub UserForm_Initialize()
ComboBox1.AddItem "A"
ComboBox1.AddItem "B"
ComboBox1.AddItem "C"
ComboBox1.AddItem "D"
End Sub
Private Sub CommandButton1_Click()
lstNo = ComboBox1.ListIndex
Unload Me
End Sub
Next Paste this in a module
Public lstNo As Long
and this in the ThisOutlookSession
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
UserForm1.Show
MsgBox "user chose " & lstNo & "from combo"
Select Case lstNo
Case -1
'User didn't select anything in the combo
Case 0
'User selected option 1 in the combo
Case 1
'User selected option 2 in the combo
Case 2
'User selected option 3 in the combo
Case 3
'User selected option 4 in the combo
End Select
End Sub
Replace the above comments in the Select Statement` with the Macro Names that you want executed depending on the user choice.
SNAPSHOTS IN ACTION
And this is what you get when you select the Option D (ListIndex 3)
FOLLOWUP
Dim email As String, info As String
Private Sub Application_ItemSend(ByVal Item As Object, Cancel As Boolean)
UserForm1.Show
Select Case lstNo
Case -1
'User didn't select anything, default will be used
Case 0
With Item
.Sensitivity = olNormal
.Save
End With
Case 1
With Item
.Sensitivity = olPersonal
.Save
End With
Case 2
With Item
.Sensitivity = olPrivate
.Save
End With
Case 3
With Item
.Sensitivity = olConfidential
.Subject = .Subject & " - [CONFIDENTIAL]"
Email = .HTMLBody
info = " <html> <body> <FONT color=#666666> <font-size: 11px> <p></p> AUTO TEXT: " & _
"This message has been marked as 'CONFIDENTIAL' please treat it as such </body> </font> </html>"
.HTMLBody = Email & info
.Save
End With
End Select
End Sub
Is there a way to populate a combo-box with a list of Macros?
Not in Outlook, I'm afraid. Programmatic access to the VBA IDE isn't supported in Outlook due to the possibility of spreading viruses or conducting malicious activity via email.
See VBA Extensibility in Outlook for reference.
The closest you can come is by programmatically displaying the "Run Macro" dialog, like this:
ActiveExplorer.CommandBars.FindControl(,186).Execute
However I'm not sure if this is available in Outlook 2010.
But showing a dialog box can't possibly be your goal. Maybe if you explain what your goal is, someone can suggest a better way of reaching it that doesn't require populating a combo box with a list of macro names.