Loop through find and replace for line breaks - vba

I'm trying to create a macro which finds a string and makes sure that there are always 3 line breaks after the string.
If Chapter One is found, there should always be 3 line breaks after it.
I need to loop through this until this is the case (so if there's 7 line breaks after "Chapter One" it needs to loop through until there are 3.
Unfortunately i'm having difficulty inserting the loop to remove more than 3 consecutive line breaks
Sub ChapterLineBreaks()
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
Selection.Find.Replacement.Style = ActiveDocument.Styles( _
"Heading 1,Chapter Heading")
With Selection.Find
.Text = "Chapter One^p^p^p^p"
.Replacement.Text = "Chapter One^p^p^p"
.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
Expected:
Chapter One
Text should then start here

You may need to use wildcards like this:
Sub ChapterLineBreaks()
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
Selection.Find.Replacement.Style = ActiveDocument.Styles( _
"Heading 1,Chapter Heading")
With Selection.Find
.text = "(Chapter One)([^13]#)([!^13])"
.Replacement.text = "\1^p^p^p\3"
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True
End With
Selection.Find.Execute Replace:=wdReplaceAll
End Sub
You will find good info here, here, and here. What I did was use the wildcards to define a regular expression: "Chapter One{1 or more line breaks}Other text". I then replaced the line breaks with exactly 3 line breaks.

Related

Microsoft Word 2013 Macro - Adding Content Controls to Multiple Items

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

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

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

Cannot get word to find "If..."

I cannot execute a find in VBA for word to find "If..." Word doesn't seem to like finding the "If." part. Any ideas?
Sub Macro2()
Selection.Find.ClearFormatting
Selection.Find.Highlight = False
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = "If..."
.Replacement.Text = "If..."
.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
Chances are Word replaced the three periods with the single character ellipsis.
As a bonus, the ellipsis should have a space before and after it, it can be a half or thin space, but certainly a non breaking space so it won't be forced onto a new line.

Eliminate space in word file

in my word file there are hundrens of paragraph which like the format below. There is a single letter Y here. It can be other letter except "A","T","C","G". I want to remove the white space in it then create a new line.
AAATGGGCCC CACAGAAGTG AGAATGGGTG AAGTCAGAAT TCCTGGTAAT GAAGTGCTTG
AACTTGGATT CCTCCCGACA TGTGCAGTAC AATGAGATGA TTTTCTCCTT AATGAGATTA
GGAAATTCTA TTAGCGCTCC CAGCTGCTGA CCCGATTCCA TGAGGCTGAG GCTCCAGGGC
TGAACCTGCC TGGTT
Y
AGTGTTCCTG GAAACTAGAC ACCCCACCCT TCAGATGGGC CAGGGCCTCC CCAGCTCTAC
CTAAAGCTGT GGTCTGCCCC CAGGGGTGCC CAGTTTCCTC CCTTCACCCT GTGCTCCAGA
GGAGTGTGGG GCCCTGGGCA TTCTGCAGTG TACCCCAGGA TCCTCACTCC TTCCTGCTTA
The new line's format is
AAATGGGCCCCACAGAAGTGAGAATGGGTGAAGTCAGAATTCCTGGTAATGAAGTGCTTGAACTTGGATTCCTCCCGACATGTGCAGTACAATGAGATGATTTTCTCCTTAATGAGATTAGGAAATTCTATTAGCGCTCCCAGCTGCTGACCCGATTCCATGAGGCTGAGGCTCCAGGGCTGAACCTGCCTGGTT[Y]AGTGTTCCTGGAAACTAGACACCCCACCCTTCAGATGGGCCAGGGCCTCCCCAGCTCTACCTAAAGCTGTGGTCTGCCCCCAGGGGTGCCCAGTTTCCTCCCTTCACCCTGTGCTCCAGAGGAGTGTGGGGCCCTGGGCATTCTGCAGTGTACCCCAGGATCCTCACTCCTTCCTGCTTA
Notice Y becomes [Y].
The final result will be saved as a text file. Thanks for help.
You don't need to write a program. The “Replace” tool is sufficient for this:
Replace Y with [Y] (EDIT: see the comments below, because it's a little more complex than that indeed)
Replace ^w with nothing (^w means whitespace)
Replace ^p with nothing (^p means paragraph markers)
EDIT: if you need a macro, just do the above once while recording a macro.
EDIT: by applying the method discussed in the comments, I get the following VBA macro:
Sub ProcessATCG()
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = "([!ACGT^13^32])"
.Replacement.Text = "[\1]"
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True
End With
Selection.Find.Execute Replace:=wdReplaceAll
With Selection.Find
.Text = "[^13^32]"
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True
End With
Selection.Find.Execute Replace:=wdReplaceAll
End Sub