lock a line for editing in a textbox in VBA - vba

I have a textbox on a userform. When the userform displays, the textbox opens with some
default value.
I want it to be such that the Line1 (or some words) of the default message is displayed in grey color and must be locked for editing. Is it possible?

Locking the TextBox for Editing?
Yes. it is possible.
Just set the .Locked Property to True
Locking/Coloring just the first line or part of a text in textBox?
No. It is not possible in VBA. For partial coloring, you may want to use RichTextBox in lieu of TextBox but then again you will not be able to partially lock the control.
Edit
Alternative: Since the first line of text contains text that shouldn't be edited then why not show that info in a ToolTip using the .ControlTipText property of the TextBox or say a Label which displays when you hover the mouse on top of the TextBox?
For example (Using the .ControlTipText property)
Option Explicit
'~~> This is what goes in the tooltip. Amend as applicable.
Const sMsg As String = "Hello World! This is an example of tooltip text"
Private Sub UserForm_Initialize()
Dim sSample As String
Dim i As Long
For i = 1 To 10
sSample = sSample & "Blah Blah" & i & vbNewLine
Next i
TextBox1.Text = sSample
'~~> Set to starting point
TextBox1.SelStart = 0
End Sub
Private Sub TextBox1_MouseMove(ByVal Button As Integer, _
ByVal Shift As Integer, _
ByVal X As Single, _
ByVal Y As Single)
TextBox1.ControlTipText = sMsg
End Sub
And now when you hover the text on top of the TextBox, you will be shown the ToolTip

This is more a workaround than a solution, but it works perfect (atleast on my computer).
Const defaultLine As String = "YourText" & vbcrlf
Private Sub TextBox1_Change()
Static oldValue As String
'set oldValue if empty
If oldValue = "" Then
oldValue = defaultLine
End If
'disable the change of the first line
If Left(TextBox1.Value, Len(defaultLine)) <> defaultLine Then
TextBox1.Value = oldValue
Else
oldValue = TextBox1.Value
End If
End Sub
Private Sub UserForm_Initialize()
TextBox1.Value = defaultLine
End Sub

Related

How can i pass a variable from userform1 textfield dblclk event to userform2 and then dynamically pass data back to userform1 through cmdbutton click

On userform1 I have a text field that when it is doubleclicked opens a "timebox" Userform 2. The user then can adjust the time and then either cancel or apply. Apply should fill in Userform1 Textbox with the selection from Userform2.
If it was once instance no problem but i'm trying to use the Userform 2 on 28 + fields and can't reference each one separately. I need to pass the textfield.name on Userform1 to give Userform2 the address in which to send the data. But its userform2 cmdbuttom - Apply.
I looked at ByVal and ByRef which seems to work when its a Sub but not when its a cmdbutton.
Userform1 > Field
Public Sub AgStart1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Dim fieldname As String
fieldname = UserForm1.AgStart1.Name
TimeForm1.Show
End Sub
UserForm2
Public Sub TimeApply1_Click()
Dim timeselect
timeselect = Me.txt_Hours.Value & ":" & Me.txt_Mins & " " & Me.txt_AmPm
'I need the value above to be sent back to the field that spawned the Userform2
TimeForm1.Hide
End Sub
OR a better way like activecell for user form fields
Userform1 text field
Useform2 spawned from dblclk
Something like this should work:
UserForm1
Public Sub AgStart1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
PopTime AgStart1
End Sub
Public Sub AgStart2_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
PopTime AgStart2
End Sub
'etc etc
Sub PopTime(ctrl As Object)
Dim frm As New TimeForm1
Set frm.TheControl = ctrl 'pass the control to the second form
frm.Show
End Sub
UserForm2
Public TheControl As Object
Public Sub TimeApply1_Click()
'set the value of the passed control
TheControl.Value = Me.txt_Hours.Value & ":" & Me.txt_Mins & " " & Me.txt_AmPm
Me.Hide
End Sub

Textbox on Access form passing previous value

I created a search form.
There is a text box for the search text. The user triggers the search event by either clicking on the search button or pressing the enter key.
The button click event is working.
On pressing of enter key for the first time the text box is passing the value which was entered in the text box from the previous event. If I press the enter key a second time the current value is passed.
For instance on the form load the text box is empty then I enter the search text as "Ali" and press enter key then the value "NULL" is passed and once again I press enter key then the value "Ali" is passed.
Option Compare Database
Option Explicit
Private Sub btnSearch_Click()
Dim SQL, strSearch As String
strSearch = Nz(Me.txtSearch.Value, "")
SQL = "SELECT tbl_mst_Employee_Details.emp_ID, " _
& "tbl_mst_Employee_Details.emp_Name " _
& "FROM tbl_mst_Employee_Details " _
& "where [emp_Name] like '*" & strSearch & "*' " _
& "ORDER BY tbl_mst_Employee_Details.emp_Name;"
Me.lstEmployee.RowSource = SQL
Me.lstEmployee.Requery
Me.txtEmpID.Value = ""
Me.txtEmpName.Value = ""
Me.Refresh
End Sub
Private Sub Form_Load()
Me.txtEmpID.Value = ""
Me.txtEmpName.Value = ""
Me.txtSearch.Value = ""
End Sub
Private Sub lstEmployee_Click()
With lstEmployee
Me.txtEmpID.Value = .Column(0)
Me.txtEmpName.Value = .Column(1)
End With
End Sub
Private Sub lstEmployee_DblClick(Cancel As Integer)
Forms!frmEmployeeShiftDetails.txtEmpID.Value = Me.txtEmpID
Forms!frmEmployeeShiftDetails.txtEmpName.Value = Me.txtEmpName
DoCmd.Close
Forms!frmEmployeeShiftDetails.txtEmpID.SetFocus
End Sub
Private Sub lstEmployee_KeyDown(KeyCode As Integer, Shift As Integer)
If KeyCode = 13 Then
lstEmployee_DblClick (0)
End If
End Sub
Private Sub txtSearch_KeyDown(KeyCode As Integer, Shift As Integer)
If KeyCode = 13 Then
btnSearch_Click
End If
End Sub
Simply set the focus to the search button first.
Additionally I would also check for pressing tab (and use constants for both, return and tab).
For having constant UI behaviour I would take care that the search button receives the focus when pressing tab in the search box, so set the correct tab order in the form.
Private Sub txtSearch_KeyDown(KeyCode As Integer, Shift As Integer)
If KeyCode = vbKeyReturn Or KeyCode = vbKeyTab Then
btnSearch.SetFocus
btnSearch_Click
End If
End Sub

Formatting Text Boxes in a Userform

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

Adding description into TextBoxes within an Excel VBA form that dissapears once user starts typing inside it

We have a userform with multiple textboxes and we would like to build something similar to the link image below, in terms of showing what the user should input in each text box:
http://d2o0t5hpnwv4c1.cloudfront.net/426_formsBestPractices/comments.png
The "default" text would disappear once the user starts typing (as opposed than once the user "lands" cursor within the textbox.
Also, if nothing gets entered within the textbox the default text would not be submitted and a blank would be used.
Can this be done?
Any suggestions will be greatly appreciated.
Can I ask why you want the default text to dissapear once a user changes the text and not once they enter the textbox?
This is not what most users will expect, I think it will be slightly confusing for some and wouldn't recommend it. The user will most likely try and delete the old text before typing their new text creating extra work.
I would use something like this:
Const sNameDefault As String = "Your Name Here"
Const sEmailDefault As String = "Your Email Here"
Private Sub UserForm_Initialize()
Me.TextBox1.Text = sNameDefault
Me.TextBox2.Text = sEmailDefault
CommandButton1.SetFocus
End Sub
'// TextBox1 - Name
Private Sub TextBox1_Enter()
With Me.TextBox1
If .Text = sNameDefault Then .Text = vbNullString
End With
End Sub
Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
With Me.TextBox1
If .Text = vbNullString Then .Text = sNameDefault
End With
End Sub
'// TextBox2 - Email
Private Sub TextBox2_Enter()
With Me.TextBox2
If .Text = sEmailDefault Then .Text = vbNullString
End With
End Sub
Private Sub TextBox2_Exit(ByVal Cancel As MSForms.ReturnBoolean)
With Me.TextBox2
If .Text = vbNullString Then .Text = sEmailDefault
End With
End Sub
Private Sub CommandButton1_Click()
Dim sName As String, sEmail As String
'// Get Name
If Me.TextBox1.Text = sNameDefault Then
sName = vbNullString
Else
sName = Me.TextBox1.Text
End If
'// Get Email
If Me.TextBox2.Text = sEmailDefault Then
sEmail = vbNullString
Else
sEmail = Me.TextBox2.Text
End If
MsgBox ("Your Name: " & sName & vbNewLine & " Your Email:" & sEmail)
Unload Me
End Sub
The above example is simply a userform with two textbox's and a commandbutton. Clicking inside the textbox will clear the default text. If the user enters nothing clicking another textbox or control will cause the default text to be added back. Once the command button is clicked the code will return blank if the default text remains.
Yes it is possible :)
I have created a sample for you. You can download it from here.
http://wikisend.com/download/143478/Sample.xlsm
The trick is to create 2 similar TextBoxes and hide the 'original' one behind the dummy TextBox ("Which has the default text")
When you start typing in the dummy, the text will actually be typed in the textbox which is hidden.
And when you are pulling values, simply pull the values from the 2nd text box so the default data is not considered :)
Hope this helps.
Code Used
Private Sub UserForm_Initialize()
TextBox1.SelStart = 0
TextBox1.SelLength = Len(TextBox1.Text)
End Sub
Private Sub CommandButton1_Click()
MsgBox TextBox2.Text
End Sub
Private Sub TextBox1_Change()
TextBox1.Visible = False
With TextBox2
.Text = Replace(TextBox1.Text, "Please enter your name", "")
.Visible = True
.SetFocus
.SelStart = Len(TextBox2.Text)
End With
End Sub

Determine which button was pressed?

I'm wondering if there's a simple way for a Word macro to determine which button was just pressed? I have a document template with several button which should all fire a macro.
The thing is, I want to create ONE macro which is called in each button. I don't want tons of macros for each button.
Now, this macro, when the button is pressed, it inserts a picture and the size of this picture is selected based on the buttons size. Meaning, this ends up as a picture placeholder. But, I want to write the macro dynamically so that the same code will work on each button without doing more than just calling the macro.
The complete macro is already done, I just need to know this one last thing, if anyone has any info on how to accomplish this? :) Thanx in advance!
UPDATE: This is the code at the moment
Private Sub ImageButton1_Click()
PicturePlaceholder ImageButton1
End Sub
Private Sub ImageButton2_Click()
PicturePlaceholder ImageButton2
End Sub
Public Sub PicturePlaceholder(ByVal oButton As CommandButton)
Dim oShape As Word.Shape
Dim Dlg As Office.FileDialog
Dim strFilePath As String
Dim oDoc As Document
Dim rgePlace As Range
Dim buttonHeight As String
Dim buttonWidth As String
Set Dlg = Application.FileDialog(msoFileDialogFilePicker)
Set oDoc = ActiveDocument
Set rgePlace = Selection.Range.Fields(1) _
.Result.Paragraphs(1).Range
Response = MsgBox("Do you want to delete the button/Picture?", vbYesNoCancel, "Do you want an image here?")
If Response = vbYes Then rgePlace.Fields(1).Delete
If Response = vbCancel Then Exit Sub
If Response = vbNo Then
With Dlg
.AllowMultiSelect = False
If .Show() <> 0 Then
strFilePath = .SelectedItems(1)
End If
End With
If strFilePath = "" Then Exit Sub
Set oShape = oDoc.Shapes.AddPicture(FileName:=strFilePath, _
LinkToFile:=False, SaveWithDocument:=True, _
Anchor:=rgePlace)
With oShape
.Height = oButton.Height
.Width = oButton.Width
End With
rgePlace.Fields(1).Delete
End If
End Sub
OK, so they're CommandButtons in the document.
In that case, there's nothing you can do - you need to have handlers called Button1_Click, Button2_Click, etc. (or whatever the button names are).
However, you can do something like this:
Private Sub Button1_Click(...)
DoStuff Button1
End Sub
Private Sub Button2_Click(...)
DoStuff Button2
End Sub
Private Sub DoStuff(ByVal oButton As CommandButton)
' All your shared code goes here
MsgBox oButton.Caption
End Sub
See also this tech note for how to create your buttons in code.
EDIT: updated to pass CommandButton reference so that the shared function can access the button properties.
EDIT 2: updated to show complete code using InlineShapes. Note that this no longer passes in the Button object, since the width/height of the button can be obtained directly from the field.
Private Sub CommandButton1_Click()
PicturePlaceholder
End Sub
Private Sub CommandButton2_Click()
PicturePlaceholder
End Sub
Public Sub PicturePlaceholder()
' Get the selected field, which must be a button field
Dim oField As Field
Set oField = Selection.Fields(1)
Debug.Assert oField.Type = wdFieldOCX
' Ask the user what he wants to do
Select Case MsgBox("Do you want to delete the button/Picture?", vbYesNoCancel, "Do you want an image here?")
Case vbCancel
Exit Sub
Case vbYes
oField.Delete
Exit Sub
End Select
' Get the filename of the picture to be inserted
Dim strFilePath As String
With Application.FileDialog(msoFileDialogFilePicker)
.AllowMultiSelect = False
If .Show() <> 0 Then
strFilePath = .SelectedItems(1)
End If
End With
If strFilePath = "" Then
Exit Sub
End If
' Figure out where to insert the picture, and what size to make it
Dim oRange As Range
Set oRange = oField.Result
Dim sglWidth As Single
sglWidth = oField.InlineShape.Width ' oButton.Width
Dim sglHeight As Single
sglHeight = oField.InlineShape.Height ' oButton.Height
' Delete the button field
oField.Delete
' Insert and resize the picture
Dim oInlineShape As Word.InlineShape
Set oInlineShape = oRange.InlineShapes.AddPicture(FileName:=strFilePath, LinkToFile:=False, SaveWithDocument:=True, Range:=oRange)
With oInlineShape
.Width = sglWidth
.Height = sglHeight
End With
End Sub
EDIT 3: Updated as requested to use Shapes rather than InlineShapes. (Both the CommandButton and the inserted Picture are now Shapes).
Private Sub CommandButton1_Click()
PicturePlaceholder
End Sub
Private Sub CommandButton2_Click()
PicturePlaceholder
End Sub
Public Sub PicturePlaceholder()
' Get the selected shape, which must be a button shape
Debug.Assert Selection.Type = wdSelectionShape
Dim oButtonShape As Shape
Set oButtonShape = Selection.ShapeRange(1)
' Ask the user what he wants to do
Select Case MsgBox("Do you want to delete the button/Picture?", vbYesNoCancel, "Do you want an image here?")
Case vbCancel
Exit Sub
Case vbYes
oButtonShape.Delete
Exit Sub
End Select
' Get the filename of the picture to be inserted
Dim strFilePath As String
With Application.FileDialog(msoFileDialogFilePicker)
.AllowMultiSelect = False
If .Show() <> 0 Then
strFilePath = .SelectedItems(1)
End If
End With
If strFilePath = "" Then
Exit Sub
End If
' Insert the picture at the same size/position
Dim oPictureShape As Shape
Set oPictureShape = ActiveDocument.Shapes.AddPicture _
( _
FileName:=strFilePath, _
LinkToFile:=False, _
SaveWithDocument:=True, _
Left:=oButtonShape.Left, _
Top:=oButtonShape.Top, _
Width:=oButtonShape.Width, _
Height:=oButtonShape.Height, _
Anchor:=oButtonShape.Anchor _
)
' Copy across the button shape formatting
oButtonShape.PickUp
oPictureShape.Apply
' Copy across other layout details
oPictureShape.LayoutInCell = oButtonShape.LayoutInCell
oPictureShape.LockAnchor = oButtonShape.LockAnchor
oPictureShape.RelativeHorizontalPosition = oButtonShape.RelativeHorizontalPosition
oPictureShape.RelativeVerticalPosition = oButtonShape.RelativeVerticalPosition
oPictureShape.WrapFormat.Type = oButtonShape.WrapFormat.Type
oPictureShape.WrapFormat.Side = oButtonShape.WrapFormat.Side
oPictureShape.WrapFormat.DistanceTop = oButtonShape.WrapFormat.DistanceTop
oPictureShape.WrapFormat.DistanceLeft = oButtonShape.WrapFormat.DistanceLeft
oPictureShape.WrapFormat.DistanceBottom = oButtonShape.WrapFormat.DistanceBottom
oPictureShape.WrapFormat.DistanceRight = oButtonShape.WrapFormat.DistanceRight
oPictureShape.WrapFormat.AllowOverlap = oButtonShape.WrapFormat.AllowOverlap
' Delete the button shape
oButtonShape.Delete
End Sub
I assume you mean that the button is a Command Bar button (aka toolbar button).
If so, you can use Application.CommandBars.ActionControl to get a reference to the button that was clicked. From there you can examine the caption, tag, or whatever.
You could put your base macro into a separate sub and then just call the macro from each button's click event, passing as a parameter the desired size. Then the only code you would have in the buttons is the call to the base sub.
You can have a button in Vba to pass arguments when it calls the macro which takes arguments.
For eg: if you have a function called as function test(x as string)
then the button which calls the macro will have a syntax as onclick("sheetx!test", "whatever"). So that way you can either have a generic macro to be called. Hope this helps you.
Placing the following in the various click/got_focus/change events of ActiveX buttons and textboxes works for me:
MsgBox ThisDocument.ActiveWindow.Selection.Fields.Item(1).OLEFormat.Object.Name