I'm trying to create some cue banners for my user form in Word. I got about half way through before I become stuck. I have it where the cue banner will disappear and clear the textbox once it has focus. If the user types their own text, that will be retained as well.
However, if the user doesn't type anything in the textbox once it has been cleared, I want to replace the cue banner along with its attributes (gray text and italicized). I can't seem to get it to work. Here's the code with everything related to this textbox below. The trouble is with the Leave event I think.
Private Sub UserForm_Initialize()
Me.txbShipToName1.Text = "name"
Me.txbShipToName1.Font.Italic = True
Me.txbShipToName1.ForeColor = &H80000006
End Sub
Private Sub txbShipToName1_Enter()
If Me.ActiveControl Is Me.txbShipToName1 And Me.txbShipToName1.Text = "name" Then
txbShipToName1.Font.Italic = False
txbShipToName1.ForeColor = &H80000008
txbShipToName1.Text = ""
End If
End Sub
Private Sub txbShipToName1_Leave()
If Me.ActiveControl Is Not txbShipToName1 And Me.txbShipToName1.Text = "" Then
txbShipToName1.Font.Italic = True
txbShipToName1.ForeColor = &H80000006
txbShipToName1.Text = LCase(txbShipToName1.Text)
txbShipToName1.Text = "name"
End If
End Sub
Private Sub txbShipToName1_Change()
If Me.ActiveControl Is Me.txbShipToName1 And Me.txbShipToName1 <> "name" Then
txbShipToName1.Text = UCase(txbShipToName1.Text)
End If
End Sub
I'm putting this here for anyone else who would like to know the solution. After a few days of messing with it, I finally realize I was over complicating things when I was messing with another piece of code. I eliminated the ActiveControl test because this is essentially already built into the Enter and Exit events. Here's the updated and working code.
Private Sub UserForm_Initialize()
'Populates cue banners
Me.txbShipToName1.Text = "Name"
Me.txbShipToName1.Font.Italic = True
Me.txbShipToName1.ForeColor = &H80000011
End Sub
Private Sub txbShipToName1_Enter()
'Removes cue banner upon entering textbox
If Me.txbShipToName1.Text = "Name" Then
txbShipToName1.Font.Italic = False
txbShipToName1.ForeColor = &H80000012
txbShipToName1.Text = ""
End If
End Sub 'txbShipToName1_Enter()
Private Sub txbShipToName1_Change()
'Converts textbox to uppercase
If Me.txbShipToName1.Text <> "Name" Then
txbShipToName1.Text = UCase(txbShipToName1.Text)
End If
End Sub 'txbShipToName1_Change()
Private Sub txbShipToName1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
'Replaces cue banner upon exiting textbox
If Me.txbShipToName1.Text = "" Then
txbShipToName1.Font.Italic = True
txbShipToName1.ForeColor = &H80000011
txbShipToName1.Text = "Name"
End If
End Sub 'txbShipToName1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Related
I am working with the Office365 version of Word. I have a VBA user form that I've created that contains text boxes with helper text as their intial value. I'm using code as below to clear out the values on user entry into the text field and repopulating the helper text if they leave the field empty:
Private Sub txtCount_Enter()
'When the user enters the field, the value is wiped out
With txtCount
If .Text = "Count No" Then
.ForeColor = &H80000008
.Text = ""
End If
End With
End Sub
Private Sub txtCount_AfterUpdate()
'If the user exits the field without entering a value, re-populate the default text
With txtCount
If .Text = "" Then
.ForeColor = &HC0C0C0
.Text = "Count No"
End If
End With
End Sub
My form has a dozen or so of these fields. I know I can somehow access a collection of Text Boxes in the form, but can I then call an action on them? Could someone provide me with an example if this is possible?
My other answer was focused on looping through all controls. To switch the default text, by textbox as they enter and exit the control (without a loop). I'd suggest a single function, based on the previous answer.
You will still need to populate the default text in both the .Tag & .Text properties
Private Sub ToggleControl(ByRef TB As Control, ByVal Hide As Boolean)
If Hide Then
If TB.Text = TB.Tag Then
TB.Text = ""
TB.ForeColor = &H80000008
End If
Else
If TB.Text = "" Then
TB.Text = TB.Tag
TB.ForeColor = &HC0C0C0
End If
End If
End Sub
Private Sub TextBox1_AfterUpdate()
Call ToggleControl(TextBox1, False)
End Sub
Private Sub TextBox1_Enter()
Call ToggleControl(TextBox1, True)
End Sub
Place the default value for each textbox in the .text property and the .tag property for this code to work.
When you call ControlToggle(Boolean) it will look through all the controls (but only target TextBoxes). If you passed True, it will hide the text in the control if the value of the textbox is the default value (located in the .tag property). If you pass False, it will find any blank fields and re-populate it with the default field.
Private Sub ControlToggle(ByVal Hide As Boolean)
Dim oControl As Control
For Each oControl In Me.Controls
If TypeName(oControl) = "TextBox" Then
If Hide Then
If oControl.Text = oControl.Tag Then
oControl.Text = ""
oControl.ForeColor = &H80000008
End If
Else
If oControl.Text = "" Then
oControl.Text = oControl.Tag
oControl.ForeColor = &HC0C0C0
End If
End If
End If
Next
End Sub
I have a Userform that includes Text Boxes with multiple formats. I have the Initialize as blank ("") and then format them using afterupdate(). This all works fine, my issues come from the possibility of the user miss keying the data the first go around or just clicking aimlessly on there screen. After you input a value it formats it correctly when you move from the text box. But if you reselect the text box then move away again, it clears the value. And if you do this with the text box that is formatted as a percent it actually bugs out with a mismatch error.
Here is a slice of my current code:
Private Sub UserForm_Initialize()
ValueAnalysisTextBox.Value = ""
CapRateTextBox.Value = ""
End Sub
Private Sub ValueAnalysisTextBox_AfterUpdate()
ValueAnalysisTextBox.Value = Format(Val(ValueAnalysisTextBox.Value), "$#,###")
End Sub
Private Sub CapRateTextBox_AfterUpdate()
CapRateTextBox.Value = Format(Val(CapRateTextBox.Value) / 100, "Percent")
End Sub
Any thoughts on how to clean this up would be great.
Is this what you are trying?
Private Sub ValueAnalysisTextBox_AfterUpdate()
Dim amt As Double
amt = Val(Replace(ValueAnalysisTextBox.Value, "$", ""))
ValueAnalysisTextBox.Value = Format(amt, "$#,###")
End Sub
Private Sub CapRateTextBox_AfterUpdate()
Dim Perct As Double
Perct = Val(Replace(CapRateTextBox.Value, "%", "")) / 100
CapRateTextBox.Value = Format(Perct, "Percent")
End Sub
Note: I am not doing any other error handling. For example, user typing "Blah Blah" or pasting something else in the textbox. I am sure you can handle that.
I'd store the underlying values in the .Tag property of the TextBox, then use it to change the formatting back and forth in the Enter and Exit events:
Private Sub UserForm_Initialize()
ValueAnalysisTextBox.Value = vbNullString
ValueAnalysisTextBox.Tag = vbNullString
End Sub
Private Sub ValueAnalysisTextBox_Enter()
ValueAnalysisTextBox.Value = ValueAnalysisTextBox.Tag
End Sub
Private Sub ValueAnalysisTextBox_Exit(ByVal Cancel As MSForms.ReturnBoolean)
If IsNumeric(ValueAnalysisTextBox.Value) Then
ValueAnalysisTextBox.Tag = Val(ValueAnalysisTextBox.Value)
ValueAnalysisTextBox.Value = Format$(ValueAnalysisTextBox.Tag, "$#,###")
Else
ValueAnalysisTextBox.Tag = vbNullString
End If
End Sub
Say you have aUserForm with TextBox1, TextBox3, TextBox3 and an OK Button.
To only allow the UserForm to close if all three TextBox have data I would use the following script assigned to the OK Button:
Private Sub CommandButton1_Click()
If Len(TextBox1.Value) >= 1 And _
Len(TextBox2.Value) >= 1 And _
Len(TextBox3.Value) >= 1 Then
Me.Hide
Else
MsgBox "Please Complete All Fields!"
End If
End Sub
Is there another way to do this besides an If statement?
Direct User Before Errors Are Made
Preferable to informing a user after an invalid action has been made is to prevent the user from performing that invalid action in the first place[1]. One way to do this is to use the Textbox_AfterUpdate event to call a shared validation routine that controls the Enabled property of your OK button, and also controls the display of a status label. The result is a more informative interface that only allows valid actions, thereby limiting the nuisance of msgbox popups. Here's some example code and screenshots.
Private Sub TextBox1_AfterUpdate()
RunValidation
End Sub
Private Sub TextBox2_AfterUpdate()
RunValidation
End Sub
Private Sub TextBox3_AfterUpdate()
RunValidation
End Sub
Private Sub RunValidation()
If Len(TextBox1.Value) = 0 Or Len(TextBox2.Value) = 0 Or Len(TextBox3.Value) = 0 Then
CommandButton1.Enabled = False
Label1.Visible = True
Else
CommandButton1.Enabled = True
Label1.Visible = False
End If
End Sub
Private Sub CommandButton1_Click()
Me.Hide
End Sub
The If Statement
As far as the If statement is concerned, there are a ton of ways that can be done, but I think anything other than directly evaluating TextBox.Value leads to unnecessary plumbing and code complexity, so I think it's hard to argue for anything other than the If statement in the OP. That being said, this particular If statement can be slightly condensed by capitalizing on its numeric nature, which allows for
Len(TextBox1.Value) = 0 Or Len(TextBox2.Value) = 0 Or Len(TextBox3.Value) = 0
to be replaced with
Len(TextBox1.Value) * Len(TextBox2.Value) * Len(TextBox3.Value) = 0
Although that doesn't gain you much and is arguably less readable code, it does allow for a condensed one liner, especially if the textboxes are renamed...
If Len(TB1.Value) * Len(TB2.Value) * Len(TB3.Value) = 0 Then
.Value vs .Text
Lastly, in this case, I think .Value should be used instead of .Text. .Text is more suited for validating a textbox entry while its being typed, but in this case, you're looking to validate a textbox's saved data, which is what you get from .Value.
More User feedback - Colorization
I almost forgot, I wanted to include this example of how to include even more user feedback. There is a balance between providing useful feedback and overwhelming with too much. This is especially true if the overall form is complicated, or if the intended user has preferences, but color indication for key fields is usually beneficial. A lot of applications may present the form without color at first and then colorize it if the user is having trouble.
Private InvalidColor
Private ValidColor
Private Sub UserForm_Initialize()
InvalidColor = RGB(255, 180, 180)
ValidColor = RGB(180, 255, 180)
TextBox1.BackColor = InvalidColor
TextBox2.BackColor = InvalidColor
TextBox3.BackColor = InvalidColor
End Sub
Private Sub TextBox1_AfterUpdate()
RunValidation Me.ActiveControl
End Sub
Private Sub TextBox2_AfterUpdate()
RunValidation Me.ActiveControl
End Sub
Private Sub TextBox3_AfterUpdate()
RunValidation Me.ActiveControl
End Sub
Private Sub RunValidation(ByRef tb As MSForms.TextBox)
If Len(tb.Value) > 0 Then
tb.BackColor = ValidColor
Else
tb.BackColor = InvalidColor
End If
If Len(TextBox1.Value) * Len(TextBox2.Value) * Len(TextBox3.Value) = 0 Then
CommandButton1.Enabled = False
Label1.Visible = True
Else
CommandButton1.Enabled = True
Label1.Visible = False
End If
End Sub
Private Sub CommandButton1_Click()
Me.Hide
End Sub
As I said in my comment, that is an ok way to do it. But i'll post this just so you have an example of another way. This would allow you to evaluate what is going into the text boxes as they are set.
Option Explicit
Dim bBox1Value As Boolean
Dim bBox2Value As Boolean
Dim bBox3Value As Boolean
Private Sub TextBox1_Change()
If Trim(TextBox1.Text) <> "" Then
bBox1Value = True
End If
End Sub
Private Sub TextBox2_Change()
If Trim(TextBox2.Text) <> "" Then
bBox2Value = True
End If
End Sub
Private Sub TextBox3_Change()
If Trim(TextBox3.Text) <> "" Then
bBox3Value = True
End If
End Sub
Private Sub CommandButton1_Click()
If bBox1Value = True And bBox2Value = True And bBox3Value = True Then
Me.Hide
Else
MsgBox "Please Complete All Fields!"
End If
End Sub
You can use a loop:
Private Sub CommandButton1_Click()
Dim n as long
For n = 1 to 3
If Len(Trim(Me.Controls("TextBox" & n).Value)) = 0 Then
MsgBox "Please Complete All Fields!"
Exit Sub
End If
Next n
Me.Hide
End Sub
You can use the below code
Private Sub CommandButton1_Click()
If Trim(TextBox1.Value & vbNullString) = vbNullString And _
Trim(TextBox2.Value & vbNullString) = vbNullString And _
Trim(TextBox3.Value & vbNullString) = vbNullString Then
Me.Hide
Else
MsgBox "Please Complete All Fields!"
End If
End Sub
I got the answer from this question
VBA to verify if text exists in a textbox, then check if date is in the correct format
I have created a TextBox1 within my UserForm.
I have create a Sub called
Sub TextBox1_Enter()
End Sub
where by clicking the textbox I want to open the DateTimePicker control to choose a date, and after the date is chosen the chosen date should be the TextBox1.Value
I have the DateTimePicker from mscomct2.ocx
I really don't figure out how to call the control; any tips with code and a good explanation anyone?
I'm not sure if this is exactly what you are looking for but you could take a look as this. It is very well explained.
My goal was to have an empty DatePicker at form startup, and was told to use a textbox to load the DTPicker upon clicking.
But I found this solution that keep the DTPicker Value empty as form startup
Private Sub DTPicker1_CloseUp()
FormatDTPicker
End Sub
Private Sub DTPicker1_Format(ByVal CallbackField As String, FormattedString As String)
If CallbackField = "X" Then FormattedString = ""
End Sub
Private Sub DTPicker1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal_
x As stdole.OLE_XPOS_PIXELS, ByValy As stdole.OLE_YPOS_PIXELS)
With DTPicker1
If .Value = vbNull Then
.Value = Now
End If
End With
End Sub
Private Sub UserForm_Initialize()
DTPicker1.Value = vbNull
FormatDTPicker
End Sub
Private Sub FormatDTPicker()
With DTPicker1
If .Value = vbNull Then
.Format = dtpCustom
.CustomFormat = "X"
Else
.Format = dtpShortDate
End If
End With
End Sub
http://www.mrexcel.com/forum/excel-questions/666685-dtpicker-value-null.html
I was trying to emphasis the option button from activeX control when it is selected by user. I decided to show the shadow when it is selected and then hide the shadow when user selects other option button. The first process is working whereas the shadow cannot be removed even though I select other button. My VBA code is shown below:
Private Sub OptionButton1_Click()
OptionButton1.Shadow = False
If OptionButton1.Value = True Then
OptionButton1.Shadow = True
Else
OptionButton1.Shadow = False
End If
End Sub
Can anyone please help me to solve this?
In case of FORMS buttons you can use
Sub RemoveFormsButtonShadows()
'A.Leine 21/10/2015
For Each Button In ActiveSheet.Shapes
Button.Select
Selection.ShapeRange.Shadow.Visible = False
Next Button
End Sub
For that you have to create one sub which needs to be called from all the option buttons that you have. This common sub will simply remove the shadow from all option buttons. Here I am taking the example of 3 option buttons.
Option Explicit
Private Sub OptionButton1_Click()
RemoveShadow
If OptionButton1.Value = True Then _
OptionButton1.Shadow = True
End Sub
Private Sub OptionButton2_Click()
RemoveShadow
If OptionButton2.Value = True Then _
OptionButton2.Shadow = True
End Sub
Private Sub OptionButton3_Click()
RemoveShadow
If OptionButton3.Value = True Then _
OptionButton3.Shadow = True
End Sub
Sub RemoveShadow()
Dim objOpt As OLEObject
With ActiveSheet
For Each objOpt In .OLEObjects
If TypeName(objOpt.Object) = "OptionButton" Then
objOpt.Shadow = False
End If
Next
End With
End Sub