Hi Bear
Good questions! And the answers, in the end are "because someone at
Microsoft just did it that way".
QUESTION 1
There are lots of different ways of laying out code, especially code to find
text in a Word document. So I've re-arranged this a bit to make it easier to
see what's going on. And I've added voluminous comments. Sadly, Microsoft's
example code never explicitly establishes its variables. It's worth knowing
that the myStoryRange in the following is a Range object. One really should
create the variable explicitly, as I've done here.
Sub FindStuff
'Declare our variable
Dim myStoryRange As Range
'Before the next bit of code would work, we have to set the myStoryRange to
something
'(In the original, it cycles through all the StoryRanges)
Set myStoryRange = ActiveDocument.StoryRanges.Item(wdMainTextStory)
'Use myStoryRange (which is the main text story) and do stuff with Finding
With myStoryRange.Find
'Identify what to find
.Text = "Microsoft Word"
'Identify whether to search top-to-bottom or bottom-to-top
.Forward = True
'Tell Word what to do when it's finished searching. Specifically:
'(from the help file) 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.
'
'The wdFindContinue setting is the default. So in Microsoft's code
'example they could omit it. That's fine for computers, but we
'humans might like to know what's going on.
'
'The .Wrap property works like the prompt you get in the UI if
'you select a range and do a search-and-replace within the range.
'Word asks if you want to continue searching in the rest of the
document.
'
'For what it's worth, if you want to restrict your search to a specific
'range, choose .Wrap = wdFindStop.
'
'So, we tell Word to keep searching after this Find.
'
.Wrap = wdFindContinue
'Go see if you can find anything
.Execute
'If Word found the text, then the myStoryRange object (which is
'just a Range object) is now re-assigned to the range where
'Word found the text it was looking for.
'
'However, if Word did not find the text, then myStoryRange
'is the same as it ever was.
'
'That's just how it works. The VBA help file explains much of this.
'We haven't yet looked to see if Word found the text.
'We can detect that using myStoryRange.Find.Found.
'If that is true, then Word found our text.
'If Word reported that it found something, then do this stuff.
While .Found
'If we found our text, then myStoryRange has been re-assigned
'to the text we found. Make it Italic.
myStoryRange.Italic = True
'Quick reminder:
'The .Forward setting is still True.
'The .Wrap setting is still wdFindContinue
'So, if we haven't hit the end of the document, Word will
'keep looking in the document.
'Go see if you can find another instance of our text
.Execute
'And if Word finds another instance of our text, then
'.Found will be true
'and myStoryRange will have been re-assigned to the
'newly-found text.
'So, if .Found is true, we'll loop here.
'If .Found is false, Word will kick us out of the loop
'and we can go home.
Wend
End With
EndSub
QUESTION 2
Here's an illustrated version of code to cycle through StoryRanges. I've
used a separate variable here for the 'inner' story ranges, where Microsoft
only uses one. And I've tried to make some things more explicit - it's not
necessarily good programming practice, it's just designed for illustration.
And I will count myself as having succeeded if, after working through this,
you no longer think that "While Not (myStoryRange.NextStoryRange Is
Nothing)" is Odd<g>.
Sub CycleThroughStoryRanges()
Dim myStoryRange As Range
Dim mySubRange As Range
'Go through every StoryRange (there are exactly 17 of them
'in Word 2003)
For Each myStoryRange In ActiveDocument.StoryRanges
'Do some stuff to this myStoryRange object
If myStoryRange.Paragraphs.Count > 0 Then
MsgBox myStoryRange.Paragraphs(1).Range.Text
End If
'But some stories have 'followers'. Eg if the document has more than
'one section, there may be many even page headers in the document.
'And we want to cycle through them all.
'Trap an error if the .NextStoryRange doesn't exist.
'For example, if myStoryRange is the even headers story, then there
might
'not be a Next even header. And the VBA Help for NextStoryRange explains
'that when myStoryRange is (eg) the footnotes story, then
..NextStoryRagne
'will always return Nothing.
On Error Resume Next
Set mySubRange = myStoryRange.NextStoryRange
On Error GoTo 0
If mySubRange Is Nothing Then
'There is no 'next' story - so if myStoryRange were, say,
'an even pages header, then there is no next even pages
'header. Or maybe, eg, myStoryRange is the footnotes, and
'it has no .NextStoryRange. So we can give up and go on.
Else
'We're here because mySubRange is *not* a Nothing
'While we continue to have more than Nothing, do this stuff
While Not (mySubRange Is Nothing)
'Do some stuff to this 'follower' range
If myStoryRange.Paragraphs.Count > 0 Then
MsgBox mySubRange.Paragraphs(1).Range.Text
End If
'See if we can find yet another 'follower' range
'(eg the next even header)
On Error Resume Next
Set mySubRange = mySubRange.NextStoryRange
On Error GoTo 0
'If we've found another 'follower' range (eg another
'even pages header), then we'll loop here.
'Otherwise, Word will kick us out of this inner loop
'and we'll go on to the next (top-level) myStoryRange.
Wend
End If
Next myStoryRange
End Sub