Delete Selected Text in a Text Box - vba

Hey fellow Stackoverflow users,
i'm trying to create a text editor with HTML tag functions (for export) and can't get a solution working. Therefor i created a textbox where the user should be able to insert the text. For this insert function i need the in the title described function to delete the selected text (only the selected text, the text around it stays) inside the textbox. Even SendKeys won't function right.
Please let me know if anyone got an idea, thanks upfront!
EDIT: Here's the corrected code for the bold button with maintextbox as textbox for the user's text:
Private Sub BoldButton_Click()
If maintextbox.SelLength = 0 Then
MsgBox ("Please highlight the text you want to edit!")
Else
SelectionText = maintextbox.SelText MsgBox ("SelText: " & SelectionText)
maintextbox.SelText = "<b>" & _
SelectionText & _
"</b>"
End If
End Sub

Simply:
TextBox.SelText = ""
The .Sel* methods all relate to the text currently selected within the control. SelText = "" replaces the current selection with nothing, thereby deleting it whilst preserving the surrounding unselected text.

Related

VBA - Enter array into multiline textbox on userform

I want to enter each element of an array onto a new line in multiline textbox on a userform. I have the Multiline and EnterKeyBehaviour of the textbox set to True.
The code below will enter the array elements but after entered they are then overwritten by the next element.
For i = LBound(clipArray) To UBound(clipArray)
frmMyForm.txtBox.Text = clipArray(i)
Next
I have tried variations like below (with vbCr, vbCrLf etc) but still does not work.
frmMyForm.txtBox.Text = clipArray(i, vbNewLine)
How can I fix?
Please, use:
frmMyForm.txtBox.Text = Join(clipArray, vbLf)

Select name from one list box to another using add item error

Got an issue where I want to select a text from one list box and add the text into another list box. the error only seems to happen if text has a "'" within the text and VBA seems to split the text and add the remaining text to the next column. Also, I'm working with column in my listbox and my code should add each text from left to right. This is fine but I need the whole text (including the ".") instead of the text being split up.
Private Sub btnAddUser_Click()
Dim SelectUser, ItemString1, ItemString2 As String, ItemString3 As String
For Each SelectUser In lstusers.ItemsSelected
Debug.Print lstusers.Column(0, SelectUser)
Debug.Print lstusers.Column(1, SelectUser)
Debug.Print lstusers.Column(2, SelectUser)
ItemString1 = lstusers.Column(0, SelectUser)
ItemString2 = lstusers.Column(1, SelectUser)
ItemString3 = lstusers.Column(2, SelectUser)
Form_frmAS.lstAddedUsers.AddItem ItemString1, 0
Form_frmAS.lstAddedUsers.AddItem ItemString2, 1
Form_frmAS.lstAddedUsers.AddItem ItemString3, 2
Form_frmAS.lstAddedUsers.Requery
Next SelectUser
End Sub
Is there a way to make it work or do I need to find a workaround?
Many Thanks
in the ListBox.AddItem method, the second parameter is the position in the list, i.e. the row number and not the column number. You cannot add the columns one by one.
To make it work, set the Row Source Type of the second ListBox to Value List and change the code to
For Each SelectUser In lstusers.ItemsSelected
lstAddedUsers.AddItem lstusers.Column(0, SelectUser) & ";" _
& lstusers.Column(1, SelectUser) & ";" _
& lstusers.Column(2, SelectUser)
Next
If you don't specify the second parameter in AddItem, the new item will automatically be appended at the end of the list.

Multiple text boxes to call the same VBA procedure

I am developing an Access Database and have several forms; all of which have the same text box on them.
The text box for each form is from the same record source, same name, same properties, etc. After the textbox is updated I have VBA running an Instr procedure which captures key phrases commonly used in these text boxes and replaces them with a common phrase.
How can I get each text box from each form to call the same procedure, that way if I have to improve the code over time I am only doing so in one place versus going to each form to update the code.
Example code.
textbox1_AfterUpdate()
Dim A as TextBox
Set A= Me.Textbox1
If InStr(A," Attachment Number ") Then
Me.FunctionalArea.SetFocus
A=Replace(A,"Attachment Number","<<Att."&" "& Left(Me.FunctionalArea).text,1)&""&"XXX>>")
A=SetFocus
End If
If InStr(A, " Program Name ") Then
A = Replace(A, " Program Name ", " <<ProgramNameXX>> ")
End If
If InStr(A, " Office Address ") Then
A = Replace(A, " Office Address ", " <<OfficeAddressXX>> ")
End If
You just call the code with a parameter of the textbox.
Something along the lines of
Public Sub textbox1_AfterUpdate()
DoTextBoxActions Me.Textbox1
End Sub
Public Sub DoTextBoxActions(ByRef ipTextBox As TextBox)
If InStr(ipTextBox.Text, " Attachment Number ") Then
ipTextBox.FunctionalArea.SetFocus
ipTextbox=Replace(ipTextbox.Text,"Attachment Number","<<Att."&" "& Left(ipTextbox.FunctionalArea).text,1)&""&"XXX>>")
ipTextBox.Parent.SetFocus = SetFocus
End If
If InStr(ipTextBox.Text, " Program Name ") Then
ipTextBox = Replace(ipTextBox.Text, " Program Name ", " <<ProgramNameXX>> ")
End If
If InStr(ipTextBox.Text, " Office Address ") Then
ipTextBox = Replace(ipTextBox, " Office Address ", " <<OfficeAddressXX>> ")
End If
End Sub
You can do this.
When you place that text box on each form, in place of building a "event" code stub, you can enter this:
=MyFunctionName()
Or, thus in your case, you would place this code in a standard code module (NOT the forms code module).
Public Function MyGlobalAfterUpdate
' pick up the form and the control
' do this first, do this fast, do this right away
' since a timer event, mouse click, focus change etc. can
' case the screen.ActiveForm, and screen.ActiveControl to change
' once we grab these values, then you ok
Debug.Print "global after"
Dim MyControl As TextBox
Dim MyForm As Form
Set MyForm = Screen.ActiveForm
Set MyControl = Screen.ActiveControl
Debug.Print "Control name = " & MyControl.Name
Debug.Print "Text of control = " & MyControl.Value
Dim strText As String
strText = MyControl.Value
Debug.Print strText
' note that we have FULL use of the form values
' in place of me!Some value, or control?
' you can go
MyForm.Refresh
MyForm!LastUpdate = now()
' save the data in the form
' If MyForm.Dirty = true then MyForm.Dirty = False
End sub
So you are free to do whatever you want in this code. And you simple replace "me" the forms reference with MyForm, but once you grabbed the active form, then anything you would or could do with "Me", you can do the SAME with MyForm. As noted, you could in theory using Screen.ActiveForm, but you are MUCH better to pick up a reference as fast as possible and as soon as possible, since those values and focus could change, and often it will - so get/grab/take a reference to the controls as fast and as soon as possible. Once you grabbed the reference from screen, then minor changes in focus etc. don't matter - since you picked up the form and control right away.
The key concept, the key takeaway? you can grab both the current form with screen.ActiveForm, and you can get/grab the current control that fired the after update event with Screen.ActiveControl.
So, in summary:
Don't create a code stub in the form. In the controls after update event, place the name of the PUBLIC function in a STANDARD code module.
eg like this:
=MyGlobalAfterUpdate()

Check for an empty Text Box

I have a text box in a Word 2016 document. This is not a TextBox form object but a normal Text Box that you insert from the Insert tab here:
I am trying to check if it is empty when the document is opened. For the life of me I cannot figure out how to do this. I have tried all of the following:
If (Len(ActiveDocument.Sections(1).Headers(wdHeaderFooterPrimary).Shapes("Text Box 2").TextFrame.TextRange.Text & vbNullString) = 0) Then
If (IsNull(ActiveDocument.Sections(1).Headers(wdHeaderFooterPrimary).Shapes("Text Box 2").TextFrame.TextRange.Text)) Then
If (LTrim(RTrim(ActiveDocument.Sections(1).Headers(wdHeaderFooterPrimary).Shapes("Text Box 2").TextFrame.TextRange.Text)) = "") Then
If (ActiveDocument.Sections(1).Headers(wdHeaderFooterPrimary).Shapes("Text Box 2").TextFrame.TextRange.Text = "") Then
None of these return true when the text box is empty? This is the text box:
It seems that the text box always contains a paragraph marker (which I can't delete). This is what the VBA watch shows:
Watch : : ActiveDocument.Sections(1).Headers(wdHeaderFooterPrimary).Shapes("Text Box 2").TextFrame.TextRange.Text : "
" : String : ThisDocument.Document_Open
Note that the watch is two separate lines which makes me think that there's CRLF or something in there?
There is always a paragraph break in an otherwise empty textbox. Accordingly, you could use something along the lines of:
Private Sub Document_Open()
With ActiveDocument.Sections(1).Headers(wdHeaderFooterPrimary).Shapes("Text Box 2")
If Not .TextFrame Is Nothing Then
If Trim(.TextFrame.TextRange.Text) = vbCr Then
MsgBox "Empty Text Range"
End If
Else
MsgBox "No Text Range"
End If
End With
End Sub

How can I set focus through Word vba range.find

I am writing a macro in Word, for replacing some text with a mapped definition.
I want to give the user the option to give confirmation for each replace, just like the default Find & Replace.
How can I set focus on the text that is found?
How can the particular section be scrolled into view?
I need to use custom VBA code(rather than default Find & Replace) as I have to process the document after reading in the mappings.
I am already able to replace the text, and also show the alerts to the user.
However, I want to put the focus on the text while showing the alert.
Current code:
Do While myRange.Find.Execute( _
FindText:=dict.Items()(i) & " (" & Word & ")", _
MatchCase:=False, _
MatchWholeWord:=True _
)
myRange.Select
If MsgBox("Replace '" & myRange.Find.Text & "' with '" & Word & "'?", vbYesNo) = vbYes Then
myRange.Text = Word
End If
myRange.Start = myRange.Start + Len(myRange.Find.Text)
myRange.End = cached
Loop
p.s. I have a custom form/dialog open, from which the macro is being run;
so the text is behind the dialog.
EDIT: Based on Jay's response, I again checked the behavior of the Find & Replace dialog. The dialog gets moved based on the location of the text. Can I achieve the same when I have a form and a confirmation dialog over the text?
The statement myRange.Select that's already in your code puts the Selection on the found text, and scrolls it into view if it's offscreen. That won't help, though, if the Selection is hidden behind a custom form (userform?) or the message box. You may be able to move the form out of the way, if you can figure out where the Selection is with respect to the screen coordinates.