Word-Scripting: replace nonbreaking spaces with thin spaces? - vba

I use word to open (special) html documents for printing and want to write a script to fix a small issue:
In the html file I have numbers like '15 cm' written as '15 cm', so there will be no line break between the number '15' and the unit 'cm'.
My problem is: The spacing is too wide, especially when word expands the spaces to fit a sentence to the margins.
So I'd like to replace these with some kind of thin spaces using a word VBA script. I guess I need to enumerate the paragraphs, but I'm not sure how to replace text in there. This is what I came up with so far, but I don't know how to write the html nbsp in word and what to use for thin spaces, maybe someone can help me here?
Sub MakeThinSpaces()
Dim para As Paragraph
For Each para In ActiveDocument.Paragraphs
replace the with some   here?
Next
End Sub

Thin space is Unicode 8201. (A narrow no-break space would be 8239).
It should work with this code using the selection object.
^s is the wildcard for a protected space, you could also use Chr(160)
Selection.WholeStory
With Selection.Find
.Text = "^s"
.Replacement.Text = ChrW(8201)
.MatchWildcards = True
End With
Selection.Find.Execute Replace:=wdReplaceAll

Regarding replacement in the entire text, there is an alternative solution to selecting the whole story.
E.g. following code would replace all non-breaking spaces in the document with normal spaces:
With ActiveDocument.Content.Find
.Execute "^s", replacewith:=" ", Replace:=wdReplaceAll
End With
The wildcard-match parameter, should it really be required, could be packet into the .Execute statement in the same way.

Related

Word VBA: Replace the space at the end of a line if the preceding character is a digit

I've found this similar issue here, but I don't know how to make it work for what I need.
I need to replace the space (" ") at the end of a line if it's preceded by a digit ("[0-9]"). Replacement text will be a non-breaking space ("^s"). So for example, throughout my document I might have dates written in this format "24 September 2019", phone numbers, phrases like "in 8 days" etc. I need to ensure the line doesn't break between the digit and the following word, hence replacing the space with a non-breaking space.
My code is on a different PC so it's not easy for me to include it, and all I've done so far is copy the one linked above but it doesn't work because I'm not sure which parts I need to amend. So please see the link above for what I've got so far, alternatively any new code that might be more effective is of course welcome.
Thank you in advance :)
This should resolve your issue:
Sub testNBS()
Dim myRange As Range
Set myRange = ActiveDocument.Range(ActiveDocument.Range.Start, ActiveDocument.Range.Start)
myRange.Select
Selection.Expand wdLine
While Selection.End < ActiveDocument.Range.End
If Right(Selection.Text, 1) = " " And IsNumeric(Left(Selection.Words.Last, 1)) = True Then
Selection.Characters.Last = Chr(160)
End If
Selection.MoveDown wdLine, 1
Selection.Expand wdLine
Wend
End Sub
I changed Left to Right, added the check for a numeric string, and added in the addition of a non-breaking space (NBS) in place of the last character in the line, which should be a space. I added the And clause just to double-check/verify.

Word VBA - Ignore punctuation while counting/selecting X number of "Words" or "Sentences"

Does anyone know if there is a VBA statement to recognize successive adjacent characters as "words" rather than counting each and every non-alpha character (as a word) along the way?
My research indicates that most people who want to ignore punctuation and/or non-alpha characters are focused on trimming or deselecting the characters. I want to retain these characters, but I also want the non-alpha character ignored while the macro is determining how many "words" to select.
Consider the following examples of "visual" words versus "Word words":
Ms. Smith-Harris (visually 2; Word 5)
9:00 a.m. (visually 2; Word 7)
and/or (visually 1, Word 3)
I have hundreds of macros that I access easily (with mnemonic shortcuts) via a text expander, among them dozens of macros that will select and perform an action (e.g., highlight, bold, uppercase, italicize, delete, etc.) on varying amounts of text to my left or right - something I do quite often in my transcription and editing work.
So, for example, my cursor might be to the right of Ms. Smith-Harris, and perhaps I want to highlight it or make it uppercase or delete it. It's much easier and faster for my eyes to quickly assess that string of characters as 2 "words" (of adjacent text) rather than stop and perform the tedious task of counting all the disruptive non-alpha characters that Word counts as "words" when selecting text, to figure out that it's 5 "words" by Word standards.
Although the text expander itself is capable of performing all the functions I might want to do to the text directly from within the program, it's much faster and more efficient to have it instead invoke a Word macro to perform the function, especially since the macro can intelligently trim unwanted spaces from the selection
But alas, if I run, for example, the Highlight2PreviousWords macro (shown below) while my cursor is to the right of Ms. Smith-Harris, it would only highlight "-Harris."
Here are two examples of my "select X number of words" macros:
Sub h1lw_HighlightPrevious1Word()
Selection.MoveLeft Unit:=wdWord, Count:=1, Extend:=wdExtend
Dim oRng As Word.Range
Set oRng = Selection.Words(1)
Do While oRng.Characters.Last = " "
oRng.MoveEnd wdCharacter, -1
Loop
oRng.Select
Selection.Range.HighlightColorIndex = wdYellow
Selection.Collapse Direction:=wdCollapseEnd
End Sub
Sub h2lw_HighlightPrevious2Words()
'
Selection.MoveLeft Unit:=wdWord, Count:=2, Extend:=wdExtend
Dim oRng As Range
Set oRng = Selection.Range
Do While oRng.Characters.Last = " "
oRng.MoveEnd wdCharacter, -1
Loop
oRng.Select
Selection.Range.HighlightColorIndex = wdYellow
Selection.Collapse Direction:=wdCollapseEnd
End Sub
All of my "select some words and then do something" macros look the same, except for the "do something" part, of course. So all of the "select 1 word to the left and do something" macros look like the first one, and all of the "select 2+ words to the left and do something" look like the second one. I usually don't go beyond 5 words because in the time it takes to visually count beyond that, I could just manually select the text.
So the macros work great for straight-text words, but not so great when other characters are in the mix. I'd love to be able to ignore the non-alpha characters and define all strings of adjacent text as "words."
Does anyone know of a way to accomplish this?
Two tips first:
To get real information about number of words you could use something like Range.ComputeStatistics() method
To select required part of your document you can trace starting and ending characters which defines range in this way ActiveDocument.Range(startingPosition, EndingPosition)
Here is your first subroutine improved. It could be not 100% of what you need but I believe it is a good starting point (tested with Ms. Smith-Harris :) ).
Sub h1lw_HighlightPrevious1Word()
Dim curSection As Range
Dim curEnd As Long
curEnd = Selection.End
Dim newStart As Long
Do
newStart = Selection.Start
Selection.MoveLeft Unit:=WdUnits.wdWord, _
Count:=1
Set curSection = ActiveDocument.Range(Selection.Start, curEnd)
Debug.Print curSection.Text 'test
Loop While curSection.ComputeStatistics(wdStatisticWords) < 2
Set curSection = ActiveDocument.Range(newStart, curEnd)
Debug.Print curSection.Text 'test
'removing ending spaces
Do While curSection.Characters.Last = " "
Set curSection = ActiveDocument.Range(curSection.Start, curSection.End - 1)
Loop
With curSection
.HighlightColorIndex = wdYellow
ActiveDocument.Range(.End, .End).Select
End With
End Sub
Ps. I believe there is a shorter solution but I could not figure it out. I think one could use RegEx here as an alternative.

Find multiple words with MatchWholeWord

I am writing a script that finds a term from a list and inserts a link to its definition using the Range.Find object. As I don't want to e.g. insert a link to 'cat' in 'catalogue', I use the MatchWholeWord property.
Now, this works well if the term is only a single word. However, if the term contains spaces or phrases, MatchWholeWord is simply ignored.
How can I make e.g. 'e-mail' not match 'free-mail'?
In case it matters, I use MS Word 2010.
Try using FindText:="<(e-mail)>" with MatchWildcards:=True.
With ActiveDocument.Content.Find
.Execute FindText:="<(e-mail)>", MatchWildcards:=True, MatchCase:=False, _
ReplaceWith:="blah", Replace:=wdReplaceAll
End With
Greetings
Axel

How do i get Word to check Integrity of my text?

i want to automatically check my document for certain properties:
a space before a parenthesis
look for weasel words, that is specified in a list
Unprintable characters (I set a lot of equations and then changed the type - not good)
Ideally I would like word to marker all these with a comment, so i can fix them later.
Is this testing of text possible/feasible/already existing in word?
Unfortunately, you can't run it at once as it's not possible to highlight hidden document marks if you need some. Try this two subs for different goals (read some comments inside subs, too)
Sub Searching_For_Text()
'will highlight all options added with .HitHighlight method
With ActiveDocument.Content.Find
.ClearHitHighlight
'words
.HitHighlight "Variant" 'any word this way
'any text
.HitHighlight " (" 'this for spaces before parenthesis
'partially specified text
.HitHighlight "doc" 'simply this for words like: _
document, documents
'option 2- this can't be highlighted but no error returned
.HitHighlight "^p" 'paragraph mark
.HitHighlight "^l" 'soft line mark
End With
End Sub
And for special document marks:
Sub Searching_Special_marks()
'for paragraph marks you need to search each separately
'each time you call it you will find next one, next to current selection point
With Selection.Find
'some cleaning
.ClearFormatting
'searching each separately
.Text = "^p" '^l for soft lines, _
^t for tabs, etc.
.Forward = True
.Execute
End With
End Sub
I think you need to make some experiments with these possible solutions.

Select Text Between Two Words and Delete Empty Lines

I am trying to delete empty lines occurring in a word document between two placeholders.
I am not sure how to find the position of the placeholders within the entire document.
I am not sure how to search between the placeholders and replace multiple carriage returns with a single carriage return.
I tried to convert the code here but couldn't get it working.
If your placeholders are always the same, you can accomplish the whole thing from Word's Find and Replace dialog. No code necessary.
For example, to replace multiple carriage returns:
Ctrl+H
turn "Use Wildcards" on
Find: (Placeholder1)^13{2,}(Placeholder2) \include the parentheses
Replace: \1 ^13 \2
If you're trying to incorporate this into a bigger block of code:
With Selection.Find
.Text = "(Placeholder1)^13{2,}(Placeholder2)"
.Replacement.Text="\1" & " ^13 " & "\2"
.Forward = True
.Wrap = wdFindContinue
.MatchWildcards = True
.Execute
End With
Let me know if that works for you.