Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Word - macro for find/replace to include header/footers? 2

Status
Not open for further replies.

smooveb

IS-IT--Management
Jul 20, 2001
161
US
Hi everyone,

running a quick experiment, I found that find/replace doesn't automatically run through headers and footers. I'll of course clumsily record a macro to find out some code to help me, but is there an elegant solution to including these areas of a word doc in my find/replace?

Thanks!
Barrett
 
From my help file, how to Find/Replace in all areas (ie StoryRanges) of a word document:
For Each myStoryRange In ActiveDocument.StoryRanges
myStoryRange.Find.Execute _
FindText:="Microsoft Word", Forward:=True
While myStoryRange.Find.Found
myStoryRange.Italic = True
myStoryRange.Find.Execute _
FindText:="Microsoft Word", Forward:=True
Wend
While Not (myStoryRange.NextStoryRange Is Nothing)
Set myStoryRange = myStoryRange.NextStoryRange
myStoryRange.Find.Execute _
FindText:="Microsoft Word", Forward:=True
While myStoryRange.Find.Found
myStoryRange.Italic = True
myStoryRange.Find.Execute _
FindText:="Microsoft Word", Forward:=True
Wend
Wend
Next myStoryRange

Hope This Help, PH.
Want to get great answers to your Tek-Tips questions? Have a look at FAQ219-2884
 
Hi Barrett,

I'm not sure elegant is the expression that comes to mind, and I'm afraid the macro recorder won't help much in this case.

Find and Replace (and, indeed, most things in Word VBA) operate on a single Story at a time. Headers and Footers are in a different Stories from the main body of the Document. They aren't the easiest things to work with, but take a look at help; meanwhile, to get you started ..

[blue][tt]ActiveDocument.StoryRanges(wdPrimaryHeaderStory).Select[/tt][/blue]

.. or ..

[blue][tt]Selection.Sections(1).Headers(1).Range.Select[/tt][/blue]

.. will select you the first header.

Enjoy,
Tony

--------------------------------------------------------------------------------------------
We want to help you; help us to do it by reading this: Before you ask a question.
 
Thanks guys, both valuable posts.

In attempt to go with the first snippet of code, I'm running into an infinite loop problem in first While.Storyrange loop. It hits the first Wend and keeps going back to the first While. Here's my modified code, is there a slight mod that might make it work?

Thanks!
Barrett

For Each myStoryRange In ActiveDocument.StoryRanges
myStoryRange.Find.Execute _
FindText:="<Project Name>", Forward:=True
While myStoryRange.Find.Found
myStoryRange.Italic = True
myStoryRange.Select
With Selection.Find
.Text = "<Project Name>"
.Replacement.Text = TextBox1.Value
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With

Wend
While Not (myStoryRange.NextStoryRange Is Nothing)
Set myStoryRange = myStoryRange.NextStoryRange
myStoryRange.Find.Execute _
FindText:="<Project Name>", Forward:=True
While myStoryRange.Find.Found
myStoryRange.Italic = True
myStoryRange.Select
With Selection.Find
.Text = "<Project Name>"
.Replacement.Text = TextBox1.Value
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Wend
Wend
Next myStoryRange
 
Hi Barrett,

Your while loop will never end because you never do anything to change the loop control value; you must Execute the Find in order to set the Found property.

Also, instead of ..

[purple]
Code:
    myStoryRange.Select
      With Selection.Find
[/purple]
.. I would use ..

[blue]
Code:
    With myStoryRange.Find
[/blue]

Enjoy,
Tony

--------------------------------------------------------------------------------------------
We want to help you; help us to do it by reading this: Before you ask a question.
 
Alright, gonna post what I have. Tony, that's great to know that the with storyrange.find will work! however, I don't think I even necessarily need a with clause, if I can figure out another good way to get a Replace action to work. I've tried the following code, but it's not doing the trick - notice how I tried to get the replacement method into the execute statement somehow...

Any thoughts?
Barrett



For Each myStoryRange In ActiveDocument.StoryRanges
myStoryRange.Find.Execute _
findText:="<Project Name>", replacementtext:=TextBox1.Value, Forward:=True
While myStoryRange.Find.Found
myStoryRange.Italic = True

Wend
While Not (myStoryRange.NextStoryRange Is Nothing)
Set myStoryRange = myStoryRange.NextStoryRange
myStoryRange.Find.Execute _
findText:="<Project Name>", Forward:=True
While myStoryRange.Find.Found
myStoryRange.Italic = True

Wend
Wend
Next myStoryRange
 
The following worked, after I played around a bit. Taking the advice of both of you, in a way. Thanks so much! Takes a while to grasp the syntax, but learning a little everyday :)


For Each mystoryrange In ActiveDocument.StoryRanges
mystoryrange.Find.Execute _
findtext:="<Project Name>", Forward:=True

With mystoryrange.Find
mystoryrange.Text = TextBox1.Value
End With

Next mystoryrange
 
Hi Barrett,

I have found working with headers and footers to be problematic; what ought to happen doesn't always work, so if you have something which works I should stick with it. Just for reference, a couple of quick points:

1. You should have some code 'up front' setting up the Find object properties.

2. With mystoryrange.Find ... End With serves no purpose because you have only fully qualified references inside the block.

3. If you have headers and footers which are different first page or different odd and even your code won't catch all of them (see the inner loop using NextStoryRange in PHV's code)

Lastly, thanks for the star :)

Enjoy,
Tony

--------------------------------------------------------------------------------------------
We want to help you; help us to do it by reading this: Before you ask a question.
 
Thanks Tony!

I'll admit, something is working funky and I could use some help figuring it out. For example, the first time I run it, the replace will be done on the correct body text, but the header will be replaced as well (which does not include the Find text). Even worse, if it is run again, the Replace text replaces everything!

I'm still using:

For Each mystoryrange In ActiveDocument.StoryRanges
mystoryrange.Find.Execute _
findtext:="<Insert Project Name>", Forward:=True

With mystoryrange.Find
mystoryrange.Text = tbProjectName.Value
End With

Regarding your points:
1. should i set find properties up front somehow as well as replacement text properties?

2. about only fully qualified references being inside the block - I'm not sure about that. The way I've coded it, it seems my Find qualification is not working properly.

3. I'll try to incorporate the inner loop. good idea :)

I'm going to work on this and keep you guys posted. Thanks!
Barrett
 
Ok, this expanded version is working much better :p

For Each mystoryrange In ActiveDocument.StoryRanges
mystoryrange.Find.Execute _
findtext:="<Insert Project Name>", Forward:=True

While mystoryrange.Find.Found
mystoryrange.Find.Execute _
findtext:="<Insert Project Name>", Forward:=True
mystoryrange.Text = tbProjectName.Value
Wend

While Not (mystoryrange.NextStoryRange Is Nothing)
Set mystoryrange = mystoryrange.NextStoryRange
mystoryrange.Find.Execute _
findtext:="<Insert Project Name>", Forward:=True
While mystoryrange.Find.Found
mystoryrange.Find.Execute _
findtext:="<Insert Project Name>", Forward:=True
mystoryrange.Text = tbProjectName.Value
Wend
Wend

Next mystoryrange

Now I'm going to put this all within a loop, which will choose different find/replace text each loop through, based on which document it's opening. Should be fun! Thanks everyone.

Barrett
 
Hi Barrett,

Your problem is because you do this ..

Code:
[blue]mystoryrange.Text = tbProjectName.Value[/blue]
.. unconditionally.

If your Find is successful, then [purple]mystoryrange.Text[/purple] replaces the selected range (the found text), but ..

.. if your Find is UNsuccessful, then [purple]mystoryrange.Text[/purple] also replaces the selected range which is the WHOLE story because it has not been changed because nothing has been found.

You need to make it conditional upon the Find having been successful ..

Code:
[blue]If mystoryrange.Find.Found Then
    mystoryrange.Text = tbProjectName.Value
End If[/blue]

Enjoy,
Tony

--------------------------------------------------------------------------------------------
We want to help you; help us to do it by reading this: Before you ask a question.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top