Microsoft Word 2013 Macro - Adding Content Controls to Multiple Items - vba

What I need to do is add a Rich Text Content Control to all "xx"'s in a large word document.
I saw a similar thread on highlighting multiple instances. I based the solution that I've tried so far on this:
Options.DefaultHighlightColorIndex = wdYellow
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
Selection.Find.Replacement.Highlight = True
With Selection.Find
.Text = "target1"
.Replacement.Text = "target1"
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
Now just testing in word to see what command it uses to add the content controls individually I found this command:
Selection.Range.ContentControls.Add (wdContentControlRichText)
What I came up with was:
Sub StandardLanguageVariableSearch()
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
Selection.Range.ContentControls.Add (wdContentControlRichText)
With Selection.Find
.Text = "xx"
.Replacement.Text = "xx"
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
End Sub
Swapping out Selection.Range with Selection.Find simply resulted in a "method or data field not found" or something like that. I think Range refers to the currently highlighted range of characters, whereas find refers to whatever the with block... well, finds.
Whatever find is doesn't appear to have the ability to throw some content controls onto it.

You were quite close:
Sub StandardLanguageVariableSearch()
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = "xx"
'.Replacement.Text = "xx"
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Do While Selection.Find.Execute
'Selection.Text = "" 'uncomment if you want to remove xx
Selection.Range.ContentControls.Add (wdContentControlRichText)
Loop
End Sub

Related

How to search for and highlight an array of "ChrW(n)" Asian font characters using VBA rather than listing them out

I use a colleague-made macro which scans a document and highlights specified Asian font characters (such as a full stop [ChrW(65294)], an apostrophe [ChrW(65287)]). It works fine, and does exactly what I need it to (highlight Asian font characters) but because it was cobbled together and added to over time, it's incredibly long and not very elegant.
I sometimes need to share it with other colleagues and it's cumbersome having to use such a long macro.
Here's a sample of the code (the actual one is hundreds of lines long):
Sub HighlightAsianCharacters
Selection.Find.ClearFormatting
With Selection.Find
'full stop
.Text = ChrW(65294)
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchByte = True
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = False
.MatchFuzzy = False
End With
Selection.Find.Execute
While Selection.Find.Found
Options.DefaultHighlightColorIndex = wdTurquoise
Selection.range.HighlightColorIndex = wdTurquoise
Selection.Find.Execute
Wend
Selection.Find.ClearFormatting
With Selection.Find
'apostrophe
.Text = ChrW(65287)
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchByte = True
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = False
.MatchFuzzy = False
End With
Selection.Find.Execute
While Selection.Find.Found
Options.DefaultHighlightColorIndex = wdTurquoise
Selection.range.HighlightColorIndex = wdTurquoise
Selection.Find.Execute
Wend
End Sub
Does anyone know how to put the character codes into an array (for example) so the macro doesn't have to be pages and pages in length?
Many thanks in advance for any help!
Why not simply create a subroutine that replaces one of these characters and pass the character as parameter. Then call the routine for each character you want to handle.
Sub HighlightAllAsianCharacters
HighlightAsianCharacter ChrW(65294)
HighlightAsianCharacter ChrW(65287)
(...)
End Sub
Sub HighlightAsianCharacter(asianChr as string)
Selection.Find.ClearFormatting
With Selection.Find
.Text = asianChr
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchByte = True
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = False
.MatchFuzzy = False
End With
Selection.Find.Execute
While Selection.Find.Found
Options.DefaultHighlightColorIndex = wdTurquoise
Selection.range.HighlightColorIndex = wdTurquoise
Selection.Find.Execute
Wend
End Sub
Of course you could collect all characters in an array or collection first and then loop over it, but I don't really see a point in doing so.

Select the result of replacement - Word Macro

I want to get and select the result of a find and replacement macro and do some operations on it.
Say, this is the text: ‎\[abc\]‎, I want to convert it to abc and then select abc.
Here is the code:
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = "(\\\[)(*)(\\\])"
.Replacement.Text = "\2"
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchKashida = False
.MatchDiacritics = False
.MatchAlefHamza = False
.MatchControl = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True
End With
Selection.Find.Execute Replace:=wdReplaceAll
Selection.Cut
Here in the last line, Selection.Cut gives an error that the Selection is empty.
I want to select the output of the replacement and Cut it.
From my repository Amin MSWord VBA macros
wdReplaceAll as the Replacement "target" doesn't jump to individual "hits", which is why the Selection is not picking up anything.
Use wdReplaceOne, instead, and the Selection (or Range object, if that is used) will move to the found content.
You might want to test whether something was actually found before issuing the .Cut command as that could have unexpected consequences if nothing is found (delete content at the point where the macro was initiated). For example:
Sub FindReplaceAndCut()
Dim found As Boolean
With Selection.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "(\\\[)(*)(\\\])"
.Replacement.Text = "\2"
.Forward = True
.wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchKashida = False
.MatchDiacritics = False
.MatchAlefHamza = False
.MatchControl = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True
End With
found = Selection.Find.Execute(Replace:=wdReplaceOne)
If found Then
Selection.Cut
End If
End Sub

To find and replace a text in the whole document in MS Word 2010 (including tables)

I have an MS Word document including a table. I am trying to find and replace text via VBA using the following code:
If TextBox1.Text <> "" Then
Options.DefaultHighlightColorIndex = wdNoHighlight
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
Selection.Find.Replacement.Highlight = True
With Selection.Find
.Text = "<Customer_Name>"
.Replacement.Text = TextBox1.Text
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.ClearFormatting
With Selection.Find.Font
.Italic = True
End With
Selection.Find.Replacement.ClearFormatting
With Selection.Find.Replacement.Font
.Italic = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
End If
This works fine for replacing all my content which is outside of the table. But it will not replace any of the content within the table.
If your goal is to perform replacements in the whole documents (it looks so from the code, but it is not explicit), I would suggest you use Document.Range instead of the Selection object. Using Document.Range will make sure everything is replaced, even inside tables.
Also, it is more transparent to the user, as the cursor (or selection) is not moved by the macro.
Sub Test()
If TextBox1.Text <> "" Then
Options.DefaultHighlightColorIndex = wdNoHighlight
With ActiveDocument.Range.Find
.Text = "<Customer_Name>"
.Replacement.Text = TextBox1.Text
.Replacement.ClearFormatting
.Replacement.Font.Italic = False
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Execute Replace:=wdReplaceAll
End With
End If
End Sub
I have used the following code and it works like charm..... for all the occurances that are found in the document.
stringReplaced = stringReplaced + "string to be searched"
For Each myStoryRange In ActiveDocument.StoryRanges
With myStoryRange.Find
.Text = "string to be searched"
.Replacement.Text = "string to be replaced"
.Wrap = wdFindContinue
.ClearFormatting
.Replacement.ClearFormatting
.Replacement.Highlight = False
.Execute Replace:=wdReplaceAll
End With
Next myStoryRange

Cleaning up messy paragraph breaks in a dictionary in MS Word

I have a dictionary in MS Word format which I'd like to have cleaned from any paragraph breaks within dictionary entries, and keep only paragraph breaks that separate any two dictionary entries. This is how the layout of the dictionary looks now:
First picture http://img43.imageshack.us/img43/6476/snapshotpr.jpg
I'd need a macro or a regular expression that would first remove all the paragraph breaks, from the document, which would produce this layout:
Second picture http://img824.imageshack.us/img824/5219/snapshot1i.jpg
and then in the next step would add paragraph breaks only before the dictionary entries, which means only before bold phrases followed by the phonetic transcription in square brackets, to get this layout:
Third picture http://img849.imageshack.us/img849/2003/snapshot2qf.jpg
I used this site to help me with the paragraph markers.
Again, I recorded a macro with something did manually with 4 find/replace (two steps were used to make sure that a word followed by a square bracket was matched). Here's the macro:
Sub Separator()
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = "^13"
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchByte = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True
.MatchFuzzy = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
Selection.Find.Replacement.Font.Bold = True
With Selection.Find
.Text = "\["
.Replacement.Text = "^&"
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchByte = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchFuzzy = False
.MatchWildcards = True
End With
Selection.Find.Execute Replace:=wdReplaceAll
Selection.Find.ClearFormatting
Selection.Find.Font.Bold = True
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = "[a-z\-]# \["
.Replacement.Text = "^p^&"
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchByte = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchFuzzy = False
.MatchWildcards = True
End With
Selection.Find.Execute Replace:=wdReplaceAll
Selection.Find.ClearFormatting
Selection.Find.Font.Bold = True
Selection.Find.Replacement.ClearFormatting
With Selection.Find.Replacement.Font
.Bold = False
.Italic = False
End With
With Selection.Find
.Text = "\["
.Replacement.Text = "["
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchByte = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchFuzzy = False
.MatchWildcards = True
End With
Selection.Find.Execute Replace:=wdReplaceAll
End Sub
Let me know if there's anything to tweak and I'll try to change it :)
EDIT: Part added for hyphens.

Word 2010 VBA Replace within a highlighted range

The following code works, but it performs everything on the entire document. I'd like to highlight a block of text, then when I run the macro only have it work on the highlighted text. How do I do that? Thanks...
Sub DoCodeNumberStyle(numchars As String)
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = "(^13)([0-9]{" + numchars + "}) "
.Replacement.Text = "\1###\2$$$ "
.Forward = True
.Wrap = wdFindAsk
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True
End With
Selection.Find.Execute Replace:=wdReplaceAll
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
Selection.Find.Replacement.Style = ActiveDocument.Styles("CodeNumber")
With Selection.Find
.Text = "###([0-9]{" + numchars + "})$$$"
.Replacement.Text = "\1"
.Forward = True
.Wrap = wdFindAsk
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True
End With
Selection.Find.Execute Replace:=wdReplaceAll
End Sub
Sub CodeNumberStyle()
DoCodeNumberStyle ("1")
DoCodeNumberStyle ("2")
End Sub
PostScript:
One additional thing I've discovered: if you do more than one find on a Selection, the first find loses/changes the Selection, so the others are no longer bounded by the original Selection (and a wdReplaceAll will continue to the end of the document). To fix this, capture the Selection into a Range. Here's the final version of my method, which now does everything I need, is restricted to the original highlighted selection (even with 3 find-and-replacements), and has also been minimized, code-wise:
Sub AAACodeNumberStyleHighlightedSelection()
With Selection.Range.Find
.ClearFormatting
.Style = ActiveDocument.Styles("Code")
.Replacement.ClearFormatting
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
' First line:
.Text = "1 //"
.Replacement.Text = "###1$$$ //"
.MatchWildcards = False
.Execute Replace:=wdReplaceAll
' Rest of lines:
.Text = "(^13)([0-9]{1,2}) "
.Replacement.Text = "\1###\2$$$ "
.MatchWildcards = True
.Execute Replace:=wdReplaceAll
' Now style the line numbers:
.Text = "###([0-9]{1,2})$$$"
.Replacement.Text = "\1"
.Replacement.Style = ActiveDocument.Styles("CodeNumber")
.MatchWildcards = True
.Execute Replace:=wdReplaceAll
End With
End Sub
Change .Wrap to wdFindStop and this should work for you. I think this might be a minor Word bug; the documentation says that the Wrap value
sets what happens if the search begins at a point other than the beginning of the document and the end of the document is reached (or vice versa if Forward is set to False) or if the search text isn't found in the specified selection or range.
But it seems like it forces the Find to go to the end of the document rather than taking the selection into account. Anyway, there's no need for wdFindAsk if you only plan to run this on selections.
I, too, found that even when beginning a FIND loop on a range, the range is redefined by FIND, and so continuous loop on .execute goes beyond the original range to the end of the document. wdFindStop stops only at the end of the document, not at the end of the original range.
So, I inserted an IF statement:
do while .find.found
...
If .find.parent.InRange(doc.Bookmarks("BODY").Range) = False Then Exit Do
...
.execute
loop
Set myRange = Selection.Range
myRange.Select
With Selection.Find
.Text = "Apple"
.Replacement.Text = "Banana"
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
'.MatchWildcards = True
End With
Selection.Find.Execute Replace:=wdReplaceAll
myRange.Select
With Selection.Find
.Text = "red"
.Replacement.Text = "yellow"
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
'.MatchWildcards = True
End With
Selection.Find.Execute Replace:=wdReplaceAll