I have two blocks of Word VBA code here that each work fine separately, but which I need to combine in order to obtain the desired result. One identifies a range of text (oRng), while the other runs a Selection.Find search to alter some text. I need to limit the Selection.Find search to the range defined by oRng.
Background: I have a variable list of news articles divided into sections under headers (single paragraph in Header1 style), which are also variable. I need to select the source line in the article (single paragraph in bold) and copy it to the end of the article header (single paragraph in Header2 style). However, certain sections need to be excluded from this operation, if the section header is a specific term.
Situation: I have working code to find the article source lines and copy them to the end of the article headers (looping through the whole document using Selection.Find). I also have working code to identify the sections of the text where the first set of code needs to be applied, by creating ranges (oRng) between applicable section headers, looping through the document section by section. What I need to do is run the first set of code (which is based around Selection.Find) within the ranges specified by the second set of code. My intention was to loop the code to identify the ranges and as it identifies each range, run the code to copy the source lines to the headers within that range, but I can't find a way to limit the Selection.Find search to a specific Range (oRng).
Can anyone help me out with this, please?
First block of code (Identify ranges between applicable section headers)
Sub SourceToArticleHeadersP2()
Dim oRng As Range
Dim oRngstart As Range
Dim oRngend As Range
Dim ArticleSource As Range
Dim ArticleHeader As Range
Dim excludedTerms(1 To 5) As String
excludedTerms(1) = "Term1"
excludedTerms(2) = "Term1"
excludedTerms(3) = "Term1"
excludedTerms(4) = "Term1"
excludedTerms(5) = "Term1"
Selection.HomeKey Unit:=wdStory
With Selection.Find
.Forward = True
.ClearFormatting
.Wrap = wdFindStop
.Style = ActiveDocument.Styles(wdStyleHeading1)
.Text = ""
.Execute
End With
Do While Selection.Find.Found
For i = 1 To 5
If InStr(1, Selection.Text, excludedTerms(i), vbTextCompare) Then
Selection.Collapse wdCollapseEnd
MsgBox excludedTerms(i) & " detected - skipping"
Selection.Find.Execute
End If
Next i
Set oRngstart = Selection.Range
MsgBox "Start = " & oRngstart
Selection.Collapse wdCollapseEnd
With Selection.Find
.Forward = True
.ClearFormatting
.Wrap = wdFindStop
.Style = ActiveDocument.Styles(wdStyleHeading1)
.Text = ""
.Execute
End With
If Selection.Find.Found Then
Set oRngend = Selection.Range
MsgBox "End = " & oRngend
Set oRng = ActiveDocument.Range(Start:=oRngstart.End, End:=oRngend.Start)
Selection.Collapse wdCollapseStart
Selection.Find.Execute
Else
MsgBox "End = End of Document"
Set oRng = ActiveDocument.Range(Start:=oRngstart.End, End:=ActiveDocument.Range.End)
End If
Loop
[SECOND BLOCK OF CODE GOES HERE]
End Sub
Second block of code (identify source lines and copy to article header lines, based on formatting). I need to modify this so that it works only on the range of text oRng.
With Selection.Find
.Forward = True
.ClearFormatting
.Wrap = wdFindStop
.Style = ActiveDocument.Styles(wdStyleHeading2)
.Text = ""
.Execute
End With
Do While Selection.Find.Found
Set ArticleHeader = ActiveDocument.Range(Selection.Range.Start, Selection.Range.End - 1)
With Selection.Find
.Forward = True
.ClearFormatting
.Wrap = wdFindStop
.Font.Bold = True
.Text = ""
.Execute
End With
Set ArticleSource = ActiveDocument.Range(Selection.Range.Start, Selection.Range.End - 1)
ArticleHeader.InsertAfter " (" & ArticleSource & ")"
Selection.Collapse wdCollapseEnd
With Selection.Find
.Forward = True
.ClearFormatting
.Wrap = wdFindStop
.Style = ActiveDocument.Styles(wdStyleHeading2)
.Text = ""
.Execute
End With
Loop
The target document has a similar layout to this (number of sections and articles is variable). Lines I'm searching for in the code above are in bold:
[2+ Pages of opening text and TOC]
Section header 1 (Style: Heading1)
Article 1 header (Style: Heading2)
Variable lines of header text
Article 1 source name (in bold)
More variable lines of header text
Article body text
Page break
Article 2 header (Style: Heading2)
Variable lines of header text
Article 2 source name (in bold)
More variable lines of header text
Article body text
Page break
Section header 2 (Style: Heading1)
Article 3 header (Style: Heading2)
Variable lines of header text
Article 3 source name (in bold)
More variable lines of header text
Article body text
Page break
[…]
Best Answer
I was able to resolve this in the end by counting the paragraphs in oRng which used the Header2 style, and looping the second search the appropriate number of times from the beginning of oRng (code below).
I'd still be very interested to know if there's another way to limit a loop with multiple searches so that it only operates within a specific range - the only idea I have would be to run the first search using oRng.Find, collapse to end, redefine oRng as (current position, oRngend) and cycle through that way, with the range becoming progressively smaller as the search moves forward until it reaches the point where there are no matches between the current position and oRngend.
Thanks a million to @Raystafarian for lots of helpful suggestions and a large dose of patience!