Find / Replace text using string found within Word document - vba

I've been trying to modify the brilliant example given here with little success. Within the MSWord document, I need to be able to find text like <<TEST>> and recover the string found between << and >> which would return TEST. Ultimately I intend to use this to look up a value against TEST and return a string to be replaced within the Word document. ie. <<TEST>> becomes FRED for example.
Sub Sample()
Dim c As Range
Dim StartWord As String, EndWord As String, TheWord As String
StartWord = "<<": EndWord = ">>"
Set c = ActiveDocument.Content
c.Find.ClearFormatting
c.Find.Replacement.ClearFormatting
With c.Find
.Text = "[\<]{2}*[\>]{2}"
'.Replacement.Text = TheWord
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = True
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
c.Find.Execute
While c.Find.Found
Debug.Print c.Text
TheWord = Replace(Replace(c.Text, StartWord, ""), EndWord, "")
Debug.Print TheWord
c.Find.Replacement.Text = TheWord
' Future something here to lookup value based on 'TheWord'
c.Find.Execute Replace:=wdReplaceOne
Wend
End Sub
At the moment, I'm just trying to replace those words like <<TEST>> that are found with the string found within. Although it will find and replace the first instance of the text matching the pattern, it doesn't find others like the example will.
Thanks.

Even if sometimes it is not recommended to use Selection within your code I prefer to use it when running find >> replace actions.
In the following code you will find two solutions- 1st is to replace text with one inside << >> brackets, 2nd is to replace with any text. Do not run both at once, comment one to run the other.
Sub Sample()
Dim c As Range
Dim StartWord As String, EndWord As String, TheWord As String
StartWord = "<<": EndWord = ">>"
ActiveDocument.Range(0, 0).Select
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = "[\<]{2}(*)[\>]{2}"
.Replacement.Text = "\1"
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = True
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
'DO NOT RUN BOTH OPTIONS TOGETHER, CHOOSE ONE
'OPTION 1. replace to inside text
'Selection.Find.Execute Replace:=wdReplaceAll
'OPTION 2. replace to any text, here- inside text found with replace function
Do While Selection.Find.Execute
Debug.Print Selection.Text
TheWord = Replace(Replace(Selection.Text, StartWord, ""), EndWord, "")
Debug.Print TheWord
Selection.Text = TheWord
Selection.Collapse WdCollapseDirection.wdCollapseEnd
Loop
End Sub

Related

Word Macro to select paragraph with specific words and copy to new document

I am trying to create a Word macro that will:
Search for a specific word (i.e. "see")
Select the entire paragraph where that word appears
Make the whole paragraph a different style (i.e. make it all red text)
Do the same thing with a second word (i.e. "blacklist")
Select that whole paragraph and apply a different style (i.e. again, make the paragraph red text)
Copy all paragraphs with the red text style and paste them in to a new word document
Unfortunately, I'm no VBA expert and I'm trying to cobble things together from what I can find online. I have found a great example that will select to the start of the paragraph, but I can't seem to figure out how to select the entire paragraph. Any help is appreciated!
** Sorry - here is the code I currently have. It will find all instances of the word "see" and selects to the start of the paragraph, then changes the color to red... but that's as far as I've gotten, as I am stuck on trying to figure out how to get it to select to the end of the paragraph.
Sub TestOne()
'
' TestOne Macro
'
'
If MsgBox(Prompt:="Would you like to update selected paragraph styles?", Buttons:=vbYesNo + vbQuestion, _
Title:="Format MD Report") = vbNo Then
Exit Sub
End If
Application.ScreenUpdating = False
Dim i As Long
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "see"
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchWildcards = False
End With
Do While .Find.Execute
i = i + 1
.Start = .Paragraphs.First.Range.Start
.Font.Color = wdColorRed
.Start = .Paragraphs.First.Range.End
Loop
End With
Application.ScreenUpdating = True
MsgBox i & " instances processed."
End Sub
For example, without needing to create a second document:
Sub Demo()
Application.ScreenUpdating = False
Dim i As Long, StrFnd As String
StrFnd = "see|blacklist"
With ActiveDocument.Range
.Font.Hidden = True
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Replacement.Text = "^&"
.Font.Hidden = True
.Replacement.Font.Hidden = False
.Format = True
.Forward = True
.MatchWildcards = True
.Wrap = wdFindContinue
For i = 0 To UBound(Split(StrFnd, "|"))
.Text = "[!^13]#" & Split(StrFnd, "|")(i) & "*^13"
.Execute Replace:=wdReplaceAll
Next
.Replacement.ClearFormatting
.Text = ""
.Replacement.Text = ""
.Execute Replace:=wdReplaceAll
End With
End With
Application.ScreenUpdating = True
End Sub
You could, of course, add a line of code before the final 'End With' to save the document with a new name.
To select the entire paragraph, following the line
.Start = .Paragraphs.First.Range.Start
add
.End = .Paragraphs.First.Range.End
... then to match only whole words, after
.MatchWildcards = False
add
.MatchWholeWord = True
And to run the code for multiple words you should add a parameter to your Sub eg
Sub TestOne(theWord As String)
then replace
.Text = "see"
with
.Text = theWord
And to run your code for each required word, add a Sub such as
Sub RunMe()
TestOne "see"
TestOne "blacklist"
End Sub
... optionally, move your MsgBoxes into RunMe()

VBA Word: Insert text before found text in word document

What I want to do is something simple (maybe). I have written a find method to loop around the document. I have find value - ']' and insert value - '[('. In between those two there can be any kind of number most likely from 1 - 100.
My current code is this:
Sub FindBracket()
Dim FindValue As String
Dim ReplaceValue As String
Dim oRange As Range
Set oRange = ActiveDocument.Range
FindValue = "]"
InsertValue = "(["
With oRange.Find
.Text = FindValue
.MatchWholeWord = False
Do While .Execute = True
If .Found Then
oRange.InsertBefore (InsertValue)
End If
oRange.Start = oRange.End
oRange.End = ActiveDocument.Range.End
Loop
End With
End Sub
The find method works good, but I need to modify .InsertBefore method.
Example
I would need to transform ' Dummy text 1] ' to this ' Dummy text [(1] ' but from the code I get ' Dummy text 1[(] ', I cannot seem to figure out how to do that, and I have only previous experience with Excel VBA only.
Would appreciate any help on this, than you.
Try this:
Sub FindBracket()
Dim FindValue As String
Dim ReplaceValue As String
Dim oRange As Range
Set oRange = ActiveDocument.Content
FindValue = "[0-9]#\]"
InsertValue = "[(^&" ' ^& - found number
With oRange.Find
.Text = FindValue
.Replacement.Text = InsertValue
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True ' enabled regular expressions
.Execute Replace:=wdReplaceAll
End With
End Sub
Before:
Dummy text 1234]
Dummy text 4321]
Dummy text 0]
Dummy text 1]
After:
Dummy text [(1234]
Dummy text [(4321]
Dummy text [(0]
Dummy text [(1]
All you need is:
Sub FindBracket()
Application.ScreenUpdating = False
With ActiveDocument.Range.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "[0-9]#\]"
.Replacement.Text = "[(^&"
.Forward = True
.Format = False
.Wrap = wdFindContinue
.MatchWildcards = True
.Execute Replace:=wdReplaceAll
End With
Application.ScreenUpdating = True
End Sub
Indeed, you don't even need a macro - it could all be done through the GUI using a wildcard Find/Replace with the same F/R expressions.

Word Macro - replace a fixed text with a variable that increase by a certain step

I have a word VBA that I want to make it a bit smarter. Right now, it serves me well but I still have to do a manual step, which I would like to eliminate. The macro replaces a string found in a selection. This string is "XXXX" which is found more than once. I prompt the user to enter a value for the variable that will replace the "XXXX". However, all the occurrences will be replaced by the same variable. I would like to be able to increase each instance by an increment of 2. So, if the user enters 402, I want the macro to find the first occurrence in the selection and replace it with 402, but the next occurrence should be replaced with 404, next 406, etc...
I tried to increment the "i" by two in the macro, but the macro goes ahead and replaces all the "XXXX" with the input variable. Any help or guidance would be very appreciated.
Here's my macro so far that needs to be enhanced.
Sub my_convert_to_PROCESS_steps_addBLOCKs()
'
' my_convert_to_PROCESS_steps Macro
'
'
Dim aRange As Range
Dim i As Integer
Dim intRowCount As Integer
Dim MyInput As Variant
intRowCount = 1
'Set aRange = ActiveDocument.Range
'Selection.WholeStory
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
With Selection.Find
Do
.Text = "XXXX " ' the word I am looking for
.Execute
If .Found Then
MyInput = InputBox(" ", "Process Block Sequence", "Enter Block Starting Number (e.g., 402)")
i = MyInput
.Replacement.Text = "At block " & i & ", the device may "
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = True
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
i = i + 2
End If
Selection.Find.Execute Replace:=wdReplaceAll
Loop While .Found
End With
End Sub
I was able to answer my own question. I had already worked on a similar one before. Here's the new code:
Sub my_convert_to_PROCESS_steps_addBLOCKs_new()
Application.ScreenUpdating = False
Dim i As Long
Dim MyInput As Variant
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "XXXX"
.Replacement.Text = ""
.Format = False
.Forward = True
.Wrap = wdFindStop
.MatchWildcards = True
.Execute
End With
MyInput = InputBox(" ", "Process Block Sequence", "Enter Block Starting Number (e.g., 402)")
i = MyInput
Do While .Find.Found
.Text = "At block " & i & ", the device may"
.Collapse wdCollapseEnd
.Find.Execute
i = i + 2
Loop
End With
Application.ScreenUpdating = True
End Sub

Find and Replace Single Digit numbers in MS Word

I am trying to locate single-digit numbers in MS Word (1-9) and replace it with word i.e. (1 = one, 2 = two). The current code replaces two-digit numbers and above. As of now, the only solution I can think of is to add spaces before and after the specific number but it is not that accurate.
Here is the code that I am using. TIA
Sub Single_Number()
Dim myDict: Set myDict = CreateObject("Scripting.Dictionary")
myDict("[1]{1}") = "one"
myDict("[2]{1}") = "two"
myDict("[3]{1}") = "three"
myDict("[4]{1}") = "four"
myDict("[5]{1}") = "five"
myDict("[6]{1}") = "six"
myDict("[7]{1}") = "seven"
myDict("[8]{1}") = "eight"
myDict("[9]{1}") = "nine"
Dim msword As Document, xWarp As Integer
For Each msword In Documents
msword.Activate
For myLoop = 0 To myDict.Count - 1
change_words myDict.Keys()(myLoop), myDict.Items()(myLoop)
Next
Next msword
End Sub
Function change_words(ByVal findWord, ByVal replaceWord)
If Selection.Type = wdSelectionIP Then
ActiveDocument.Range(0, 0).Select
xWarp = wdFindContinue
Else
xWarp = wdFindStop
End If
With Selection.Find
.ClearFormatting
.Text = findWord
.Replacement.Text = replaceWord
.Forward = True
.Forward = True
.Wrap = xWarp
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True
.Execute Replace:=wdReplaceAll
End With
End Function
Using the follow on string wasn't quite the best answer. The code below does the trick If and only if you only want to search in the main content of the document and your single digit numbers are preceded by a Space. If you are in the unfortunate position of having a single digit as the first character in a paragraph this code won't catch that issue. I'll leave it as an exercise to the reader as to how to modigy the () to include things such a paragraph markers.
The code below has been tested with
This 1 is 2 some 8 text 9. This is some7 more6 5 text
which is correctly converted as
This One is Two some Eight text Nine. This is some7 more6 Five text
This is the code
Sub ReplaceSingleNumbersWithText()
' Set up a search term for a single digit where the single digit is preceded
' by a space and followed by a character that is not a number or a letter
Const DIGIT_SEARCH As String = "( )([XXX]{1})([!0-9a-zA-Z])"
Dim myDigitAsWord As Variant
Dim mySearchDoc As Word.Document
Dim myIndex As Long
Dim myFindText As String
Dim myReplaceText As String
myDigitAsWord = Split("Zero,One,Two,Three,Four,Five,Six,Seven,Eight,Nine", ",")
For Each mySearchDoc In Word.Application.Documents
With mySearchDoc.StoryRanges(wdMainTextStory)
With .Find
.ClearFormatting
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True
End With
For myIndex = 0 To UBound(myDigitAsWord)
myFindText = Replace(DIGIT_SEARCH, "XXX", CStr(myIndex))
myReplaceText = "\1" & myDigitAsWord(myIndex) & "\3"
.Find.Execute FindText:=myFindText, replacewith:=myReplaceText, Replace:=wdReplaceAll
Next
End With
Next
End Sub

How to convert a letter to superscript in macro (Word)?

I want change a word to superscript in macro.
word 2016.
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = "7th of every month."
.Replacement.Text = "7^th of every month."
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchAllWordForms = False
.MatchWholeWord = True
.MatchWildcards = False
.MatchSoundsLike = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
End Sub
when i run the macro instead of making "th" as supercript it just create space between "7" and "h"
Result is like this "The meeting is on 7 h of every month."enter image description here
The following code searches for one or two digits, immediately followed by th and superscripts the th. This makes it more flexible than searching the specific string.
It works with a Range rather than a Selection object which will make it faster. The search type is a "wildcard" search.
Sub SuperScript_th_()
Dim rngFind As Word.Range
Dim searchText As String
Dim found As Boolean
Set rngFind = ActiveDocument.content
searchText = "[0-9]{1;2}th"
'searchText = "7th"
With rngFind.Find
.Text = searchText
.MatchWildcards = True
.wrap = wdFindStop
found = .Execute
Do While found
rngFind.Collapse wdCollapseEnd
rngFind.MoveStart wdCharacter, -2
rngFind.Font.Superscript = True
rngFind.End = ActiveDocument.content.End
found = .Execute
Loop
End With
End Sub
The ^t is the instruction in Word's Find to insert a TAB (like pressing the Tab-key on the keyboard). That's why the code in the quesiton is inserting space between the 7 the h in the Replacement.Text.
While Word's Find/Replace is able to format text as part of the Replacement, the difficulty here is that
Not all the text being found should be formatted
The entire text needs to be retained
It's not possible to tell Find/Replace to find text, then format only part of it. That's why the Find needs to be separate from the formatting action. If the entire found text needed to be formatted, then Find/Replace alone would work.
There are also no commands in Word's Find/Replace to apply formatting as a "code" in the Replacement.Text string.
Why don't simply try like this
With Selection.Find
.Text = "7th of every month."
'.Replacement.Text = "7^th of every month."
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchAllWordForms = False
.MatchWholeWord = True
.MatchWildcards = False
.MatchSoundsLike = False
Do While .Execute
ActiveDocument.Range(Selection.Range.Start + 1, Selection.Range.Start + 3).Font.Superscript = True
Loop
End With
Edit: With turning off some word options etc the 8 sec time to process 60 pages and 1240 replacement may be reduced to around 2 seconds. the test code
Sub test2()
Dim Rng As Range, tm As Double
tm = Timer
TurnOnOff False
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = "7th of every month."
X = 0
Do While .Execute
ActiveDocument.Range(Selection.Range.Start + 1, Selection.Range.Start + 3).Font.Superscript = True
X = X + 1
Loop
End With
Debug.Print X, Timer - tm
TurnOnOff True
End Sub
Sub TurnOnOff(OnOff As Boolean)
Application.ScreenUpdating = OnOff
With Options
.Pagination = OnOff
.CheckSpellingAsYouType = OnOff
.CheckGrammarAsYouType = OnOff
End With
End Sub