VBA: Stop Word from adding new line to selected text - vba

Whenever I select a section of text in MS Word using this code:
Dim aRange As Range
Set aRange = ActiveDocument.Range( _
Start:=ActiveDocument.Paragraphs(1).Range.Start, _
End:=ActiveDocument.Paragraphs(3).Range.End)
aRange.Select
everything is fine except that Word automatically alters the selection to add a new line character at the end of the selection. How to avoid it? Perhaps it is possible to change the selection so that it will not include a new line character.
My question is similar to another one already asked, but I would like it to do it using VBA.

When you work with selections on the keyboard you use Shift + Left/Right Arrow keys to change the extent of the selection. In the Word object model there's an equivalent you can use with the Range object; actually, there's a set of methods: MoveStart, MoveEnd, MoveWhile, MoveUntil
In this case, you need the MoveEnd method. You can move the end point by a specific set of units, such as characters, words, paragraphs - you want to move by one character, going "backwards", so:
aRange.MoveEnd wdCharacter, -1
aRange.Select

This should work:
doc.Paragraphs(1).Range.Select
Selection.MoveEnd wdCharacter, -1
Selection.Copy

Related

Batch add formatted autocorrects with VBA in Word

I use a long Excel spreadsheet containing incorrect and correct terms to check consistency between documents (e.g. anti-citrullinated is always hyphenated). I've added quite a few of these as autocorrect entries via the AutoCorrect Options feature in Word but it's time-consuming .
I came across the following code that will add long lists of autocorrects.
Sub BatchAddAutoCorrectEntries()
Dim objTable As Table
Dim objOriginalWord As Cell
Dim objOriginalWordRange As Range
Dim objReplaceWordRange As Range
Dim nRowNumber As Integer
Set objTable = ActiveDocument.Tables(1)
nRowNumber = 1
For Each objOriginalWord In objTable.Columns(1).Cells
Set objOriginalWordRange = objOriginalWord.Range
objOriginalWordRange.MoveEnd Unit:=wdCharacter, Count:=-1
Set objReplaceWordRange = objTable.Cell(nRowNumber, 2).Range
objReplaceWordRange.MoveEnd Unit:=wdCharacter, Count:=-1
AutoCorrect.Entries.Add Name:=objOriginalWordRange.Text, Value:=objReplaceWordRange.Text
nRowNumber = nRowNumber + 1
Next objOriginalWord
MsgBox ("All autocorrect items in the table1 are added.")
End Sub
It doesn't preserve any formatting: super- or subscripts, etc. Formatting autocorrect entries are stored in the Normal.dotm file and not in the regular .acl file so I haven't been able to figure out a way around this.
In a similar post, someone suggested a Find and Replace macro but Find and Replace doesn't allow me to replace with super- or subscripts.
There are two methods of adding Auto Correct Entries, Add and AddRichText. It is this second one that you use for formatted entries.
When faced with an issue like this my first resort is to check the Object Brower in the VBA editor (press F2 to display) to see what methods and properties may be available. My next step is to look them up in the VBA technical reference, aka Help, to check the usage.
If the problem is just sub/superscribt, then you could use uni-codes. Those are also available in autocorrect. Fx writing the unicodes ₁₂₃₄₅₆₇₈₉ instead of using formating on a normal 2. Most (but not all) characters exist in super and sub unicode.
The program is not working. It is giving an error message
Compile Error Expected Function or Variable
It is showing the following line as error
Autocorrect.Entries.Add Name:=objOriginalWordRange.Text, Value:=objReplaceWordRange.Text

Insert Building Blocks using Word VBA

I'm trying to insert a formatted table that I have saved in word named "DV Table" as part of the building blocks using VBA. I need this table to be inserted at the 13th paragraph of the word document.
Here's my code below. The first 3 lines just sets the selection to be at the 12th paragraph and create a new paragraph (13) after that. The last line of code is to insert the table. But when I run this, it gives the error.
Compile Error: Sub or Function not defined
I guess that this is not the proper way of defining the location. Would like some help on this. Thanks.
ActiveDocument.Paragraphs(12).Range.Select
Selection.EndKey Unit:=wdLine
Selection.Paragraphs.Add
ActiveDocument.AttachedTemplate.BuildingBlockEntries("DV Table" _
).Insert Where:=Paragraphs(13).Range.Select, RichText:=True
The Where parameter requires a Range object. There are two problems with Paragraphs(13).Range.Select
it's a method - it's an action, selecting something, not returning an object
Paragraphs(13) isn't "fully qualified" - VBA doesn't know what it is/what is meant.
One possibility would be
ActiveDocument.Paragraphs(13).Range
Notice ActiveDocument. preceding Paragraphs: this "fully qualifies" Paragraphs(13) - it tells VBA to what that belongs. And, since Where requires a Range object, Paragraphs(13).Range should be a correct "target" (I have not tested your code).
Generally, it's preferable not to work with Selection, just with Range objects. There's usually no need to actually select something using VBA. An alternative to the code snippet in the question could be
Dim rng As Word.Range
Set rng = ActiveDocument.Paragraphs(13).Range
rng.Collapse wdCollapseEnd 'like pressing right-arrow for a selection
rng.InsertParagraphAfter
rng.Collapse wdCollapseStart ' like pressing left-arrow for a selection
'rng.Select ' for testing / demo purposes
ActiveDocument.AttachedTemplate.BuildingBlockEntries("DV Table" _
).Insert Where:=rng, RichText:=True
In this case, the selection in the document does not change. There's no screen flicker; and code executes more quickly. This way of working takes getting used to, but once one is familiar with it, it's much easier to recognize what the code should be doing... Selection is rather vague as to what is being manipulated, especially if there's a lot of code using it.

Add characters before and after selection using VBA

I tried to write a macro to would add a certain character before a selected text in Word. This works fine. I'd like to add one more feature. When no selection is made the macro should select a word where the cursor is and then add a certain character.
I have the following code:
Sub AddChar()
If Len(Trim(selection.Text)) >= 1 Then
Trim (selection.Text)
selection.InsertBefore Chr(187)
selection.InsertAfter Chr(171)
Else
selection.Words(1).Select
selection.InsertBefore Chr(187)
selection.InsertAfter Chr(171)
End If
End Sub
I am assuming that your question is about the case where you have a "point" selection.
When you have a "point" selection, although it looks as if nothing is selected, the Selection object actually contains the character after the insertion point (you can check by typing
?Selection
in the Visual Basic Editor's Immediate window)
So the problem is that the selection will still have a length of 1, so your initial test
If Len(Trim(selection.Text)) >= 1 Then
will not work.
What you need to do is check the Selection.Type. You will find that the Object Browser lists several types, but for example the following code will solve the immediate problem:
If Selection.Type = wdSelectionType.wdSelectionIP Then
' code for a "point" selection
Else
' code for the case where something is already selected
End If

Modifying a table cell's .Range.Text removes any attached comments

I've written a small VBA program to remove trailing whitespace from MS Word table cells. It iterates through all the cells of each table and modifies their .Range.Text object using the command
C.Range.Text = myRE.Replace(C.Range.Text, "")
where myRE is a VBScript RegExp 5.5 object and myRE.Pattern = "\s+(?!.*\w)". The entire program can be found here.
The program works fine except for one problem. It removes all the comments from the cells as well. Before:
After (the extra space is gone, but so is the comment):
Looking at the local object tree, I can see that changing C.Range.Text also changes C.Range.Comments - but why?
What can I do to prevent this?
When you work with Range.Text, as is the case whenever RegEx or, indeed, any function that manipulates strings is used, all formatting and other non-text characters are lost when a pure string is written back to the cell.
For example, if a single character in your cell text were formatted as Bold, the bold formatting would be lost. Or if change tracking were in the cell - it would be lost. Any Footnote or Endnote would be lost. Comments fall into this same category.
You need a different approach, one that respects how Word stores non-text information in a document. Here's a suggestion that loops the cells in a table, picks up the Range at the end of the cell, then moves the starting point of the Range back as long as a pre-defined Whitespace character is found. When this criterium is no longer met, the Range is deleted. (Note I don't know why I needed to use Range.Delete twice - the first time had no effect.)
You need to work out what for you is "whitespace". I used a space, a carriage return and a tab character. You can certainly add others to the sWhitespace string.
Sub RemoveWhiteSpaceEndOfCell()
Dim cel As word.Cell
Dim sWhitespace As String
Dim rng As word.Range
Dim lWhiteSpaceChars As Long
'define what constitutes Whitespace.
'Here: a space, a carriage return and a tab
sWhitespace = Chr(32) & Chr(13) & Chr(9)
For Each cel In ActiveDocument.Tables(1).Range.Cells
Set rng = cel.Range
'set the Range to the end of the cell
rng.Collapse wdCollapseEnd
rng.MoveEnd wdCharacter, -1
'move the starting point back as long as whitespace is found
lWhiteSpaceChars = rng.MoveStartWhile(sWhitespace, wdBackward)
'Only if whitespace was found, delete the range
If lWhiteSpaceChars <> 0 Then
'rng.Select 'For debugging purposes
rng.Delete
rng.Delete
End If
Next
End Sub

Getting the previous Word in VBA using selection.previous wdword, 1 bug

I'm trying to write a macro to type the previous word at the cursor.
the problem is when i'm using "selection.previous wdword, 1" to get the previous character, it sometimes get the 2 previous characters and it seems like a bug. when i press "delete" button it works and it is very strange to me.
I'd glad if you help.
my ultimate goal is to create a calendar converter inside word using this code.
here is how i test it:
MsgBox Selection.previous(unit:=wdWord, Count:=1)
it is the same using next :
MsgBox Selection.Next(unit:=wdWord, Count:=1)
instead of next word, sometimes it returns the word after!
For example this is the text: during the flight on 21/3/1389
If the cursor is right after the 1389, msgbox selection.previous(1,1) would show "/"; if the cursor is after a space after 1389 it shows "1389". The problem is, I think, the space. My question is if there is any alternative to read the previous word instead of this command (Selection.previous(unit:=wdWord, Count:=1))
Word is not buggy - it's behaving as designed. Something has to tell Word where words start and end. When the cursor stands to the right of a space it's (quite logically) at the beginning of the next word. So going one word back is going to pick up 1389 instead of /.
You can work around this in your code. I'm sure there's more than one way to do it, but the following works for me in a quick test:
Sub GetPrevWord()
Dim rngSel As word.Range, rngPrev As word.Range
Set rngSel = Selection.Range
Set rngPrev = rngSel.Duplicate
rngPrev.MoveStart wdCharacter, -1
If Left(rngPrev.Text, 1) = " " Then
rngPrev.Collapse wdCollapseStart
End If
rngPrev.Select
MsgBox Selection.Previous(unit:=wdWord, Count:=1)
rngSel.Select
End Sub
What it's doing is using two Ranges: one to hold the original selection, the other to work with (rngPrev). rngPrev is extended backwards by one character and this character is evaluated. If it's a space then rngPrev is collapsed to its starting point. (Think of it like pressing the left arrow key of a selection.) In any case, rngPrev is selected and your MsgBox code is run. Finally, the original range is selected again.