Loop Through Document

D

DJ

Hello Group!

I'm trying to write a subroutine that will examine the first several
characters of each line in a Word document and take some action based on the
value. I'm having difficulty with coding a loop that will cycle through each
line until it reaches the end of the document.

I'm fairly new to vba and was wondering if someone could explain why the
following code doesn't reach the end sub when the cursor is at the end of
the document:

Sub AutoExport()

Selection.HomeKey Unit:=wdStory
Selection.HomeKey Unit:=wdLine

Do Until ActiveDocument.Bookmarks("\Sel") = _
ActiveDocument.Bookmarks("\EndOfDoc")
Selection.MoveDown
Loop

End Sub

Many thanks!

~ Dave
 
G

Greg Maxey

DJ,

I am fairly new to this VBA business myself. Your code continues to run
because your condition:

ActiveDocument.Bookmarks("\Sel") = ActiveDocument.Bookmarks("\EndOfDoc")

is never met.

While your IP is moved down the page end line, it is never moved to the end
of the document. I don't know why an error isn't generated when selection
can not move further down. Perhaps one of the heavy hitters will be along
to enlighten us.

I don't know what you are trying to do exactly, but here is a example of
code that will move down the document line by line until the last line is
met then exit:

Sub AutoExport()
Dim numLines As Long
Dim oBM As Bookmark
Dim i As Long

Set oBM = ActiveDocument.Bookmarks("\EndOfDoc")
numLines = oBM.Range.Information(wdFirstCharacterLineNumber)
i = 1
Selection.HomeKey Unit:=wdStory
Do While i < numLines
Selection.MoveDown Unit:=wdLine
i = i + 1
Loop
End Sub
 
D

DJ

Jezebel,

Thanks for the speedy reply. I'll post a follow-up if I have problems.

Getting back to the example I posted, my last line was, indeed, not blank.
However, even when I added a blank line I couldn't get it to exit the loop.
It still doesn't exit the loop if I add a selection.endkey unit:wdline
within the loop, nor even a selection.endkey unit:wdstory.

I ran across this method of looping through documents many times after
googling for solutions, and I'd like to understand why it isn't working. The
original example was:

Loop: Do Until End of Document
Do Until ActiveDocument.Bookmarks("\Sel") = _
ActiveDocument.Bookmarks("\EndOfDoc")
'(Do something)
Loop

I thought I could simply add code to move down a line each time through the
loop and look at the start of each line of text, and exit the loop when I
got to the last line. Obviously I'm missing something or don't understand
the real purpose of the example.

Thanks,

~ Dave
 
G

Greg Maxey

DJ,

Here are a few examples for you to look at. Type a word or two in a
document and then run these test. Use F8 in your VBA editor to step through
the tests.

Sub Test1()

Dim i As Long

Selection.HomeKey Unit:=wdStory
i = 0

Do Until ActiveDocument.Bookmarks("\Sel") = _
ActiveDocument.Bookmarks("\EndOfDoc") Or i = 1000
i = i + 1 'Do something
Loop
MsgBox """i"" = " & i & " . This test shows that \Sel isn't" _
& " going to be equal to \EndOfDoc anytime soon! In" _
& "fact it never will. You are spinning your wheels."

End Sub
Sub Test2()

Dim i As Long

Selection.HomeKey Unit:=wdStory
i = 0

Do Until ActiveDocument.Bookmarks("\Sel") = _
ActiveDocument.Bookmarks("\EndOfDoc") Or i = 1000
i = i + 1 'Do something
Selection.Move Unit:=wdCharacter, Count:=1 'Do something else
Loop
MsgBox """i"" = " & i & " . This test shows that while you can move" _
& " the selection towards \EndOfDoc, you can't get there."

End Sub
Sub Test3()

Dim i As Long

Selection.HomeKey Unit:=wdStory
i = 0

Do Until ActiveDocument.Bookmarks("\Sel") = _
ActiveDocument.Bookmarks("\EndOfDoc") Or i = 1000
i = i + 1 'Do something
Selection.GoTo What:=wdGoToBookmark, Name:="\EndOfDoc"
Loop
MsgBox """i"" = " & i & " . This test shows that while you can go" _
& " directly to the \EndOfDoc bookmark, the \Sel bookmark" _
& " and \EndOfDoc bookmarks are still not equal."

End Sub
Sub Test4()

Dim i As Long

Selection.HomeKey Unit:=wdStory
i = 0

Do Until i = ActiveDocument.Characters.Count Or i = 1000
i = i + 1 'Do something
Selection.Move Unit:=wdCharacter, Count:=1
Loop
MsgBox """i"" = " & i & " . This test meets the first condition" _
& " and moves the IP to the end of the document and exits" _
& " the loop."
End Sub

While these tests fail to explain why the two bookmark values will never be
equal, they offer proof and provide an alternative.
 
G

Greg Maxey

DJ,

In view of Jezebel's enlightening post, we can add a new Test2A.

Sub Test2a()

Dim i As Long

Selection.HomeKey Unit:=wdStory
i = 0

Do Until ActiveDocument.Bookmarks("\sel").Start = _
ActiveDocument.Bookmarks("\EndOfDoc").Start Or i = 1000
i = i + 1 'Do something
Selection.Move Unit:=wdCharacter, Count:=1 'Do something else
Loop
MsgBox """i"" = " & i & " . This test shows that when the two" _
& "bookmarks are referring to the same range then equality" _
& " can occur and meet the condition."

End Sub

-
Greg Maxey/Word MVP
A Peer in Peer to Peer Support
 
D

DJ

Jezebel,

The snippet you suggested is working good, but not great :) Thank you! I
find it appealing because it's clean and simple. I don't know what
advantages it has over the Selection object, or if there are any pitfalls to
the Paragraph object approach. Perhaps you could comment if and when you
have a moment.

One thing that I'm finding is that the "learning" loop I've coded using your
suggestion (see below) fails to reach the end of some of my documents.

The documents I'm running it against consist of simple lines of text
terminated with a carriage return (ENTER key, Chr(13), etc.) There's no
special formatting, graphics, idents, tabs, etc. After running the macro the
IP is positioned at the start of line 39 on page ten of an eleven page
document (there are 347 paragraphs and 547 lines in the document). If I copy
the offending section, and include a couple lines of text above and below
line 39, into a new document as unformatted text and run the macro, the IP
is at the end of the document.

If I copy the entire document and paste it into a new document as
unformatted text, the IP is at line 40 on page ten after running the macro.
If I do this again and run the macro, the IP is at line 41 on page ten. Can
you provide any insight on what may be causing this?

Sub IterateDocLines()

Dim result As String
Dim pPar As Word.Paragraph

Selection.HomeKey Unit:=wdStory
Selection.HomeKey Unit:=wdLine
stepnumber = 0

For Each pPar In ActiveDocument.Paragraphs
Selection.MoveRight Unit:=wdWord, Count:=1, Extend:=wdExtend
result = Selection.Text
Selection.MoveDown
Next

End Sub


Thanks again for you suggestion, explanations (and patience)!

~ Dave
 
D

DJ

Jezebel,

The snippet you suggested is working good, but not great :) Thank you! I
find it appealing because it's clean and simple. I don't know what
advantages it has over the Selection object, or if there are any pitfalls to
the Paragraph object approach. Perhaps you could comment if and when you
have a moment.

One thing that I'm finding is that the "learning" loop I've coded using your
suggestion (see below) fails to reach the end of some of my documents.

The documents I'm running it against consist of simple lines of text
terminated with a carriage return (ENTER key, Chr(13), etc.) There's no
special formatting, graphics, idents, tabs, etc. After running the macro the
IP is positioned at the start of line 39 on page ten of an eleven page
document (there are 347 paragraphs and 547 lines in the document). If I copy
the offending section, and include a couple lines of text above and below
line 39, into a new document as unformatted text and run the macro, the IP
is at the end of the document.

If I copy the entire document and paste it into a new document as
unformatted text, the IP is at line 40 on page ten after running the macro.
If I do this again and run the macro, the IP is at line 41 on page ten. Can
you provide any insight on what may be causing this?

Sub IterateDocLines()

Dim result As String
Dim pPar As Word.Paragraph

Selection.HomeKey Unit:=wdStory
Selection.HomeKey Unit:=wdLine
stepnumber = 0

For Each pPar In ActiveDocument.Paragraphs
Selection.MoveRight Unit:=wdWord, Count:=1, Extend:=wdExtend
result = Selection.Text
Selection.MoveDown
Next

End Sub


Thanks again for you suggestion, explanations (and patience)!

~ Dave
 
H

Helmut Weber

Hi,
a million ways to do that.
Here comes just one:

Sub test666()
Dim P1 As Long ' position 1
Dim P2 As Long ' position 2
Selection.ExtendMode = False
Selection.HomeKey Unit:=wdStory
P1 = Selection.Range.Start
ActiveDocument.Bookmarks("\line").Select
If Left(Selection.Text, 3) = "abc" Then
MsgBox "gotcha"
Exit Sub
Else
Selection.MoveDown Unit:=wdLine
P2 = Selection.Range.Start
While P1 <> P2
ActiveDocument.Bookmarks("\line").Select
If Left(Selection.Text, 3) = "abc" Then
MsgBox "gotcha"
Exit Sub
End If
P1 = Selection.Range.Start
Selection.MoveDown Unit:=wdLine
P2 = Selection.Range.Start
Wend
End If
MsgBox "nothing found"
End Sub

Greetings from Bavaria, Germany

Helmut Weber, MVP
"red.sys" & chr(64) & "t-online.de"
Word XP, Win 98
http://word.mvps.org/
 
G

Greg Maxey

Jezebel,

Your suggested code:

Sub IterateDocLines()
Dim pPar As Word.Paragraph
Dim myRange As Range

For Each pPar In ActiveDocument.Paragraphs
myRange = "XXX" & Mid(myRange, 4)
Next

End Sub

Seems to create a circular loop. It changes the first paragraph but then
goes no further. I can't figure out why.
 
G

Greg Maxey

Jezebel,

Ignore my last in part. What I provided as your suggested code was an
aborted attempt of mine to get some code to work.

Sub IterateDocLines()

Dim pPar As Word.Paragraph

For Each pPar In ActiveDocument.Paragraphs '1
pPar.Range = "XXX" & mid$(pPar.range,4) '2
Next ;3

End Sub

Loops continuously between lines 2 and 3
 
D

DJ

Jezebel,

Thanks for your valuable input. It dawned on me that I was moving through
the document by "lines" but iterating "paragraphs" shortly after submitting
this post. Turns out that the docs I was having issues with contained a few
sentences that wrapped to the next line and terminated with the soft return
instead of vbCR. I created a test doc with several single lines and several
wrapped lines then looked at the doc properties and saw it contained seven
paragraphs. Light dawned on Marblehead after I compared the number of lines
my macro was advancing (hmmm...... 7) to the number of paragraphs in the
doc.

I modified the Selection.MoveDown and changed it to "Selection.MoveDown
Unit:=wdParagraph, count:=1" and it's working much better.

What I'm trying to do is prepare Word documents for easy exporting into
TestDirector (I detest writing scripts in TD's interface). I have is a doc
consisting of step numbers, actions and results that look like this:

1
Action
Result

2
Action
Result

etc.....

The macro will create sequentially numbered bookmarks (using specific names
for steps, actions and results) at the beginning of each sentence, as well
as insert a specific, corresponding bitmap image. Since I do a lot of cut
and paste between scripts, the macro will also renumber the steps in
sequential order.

This is all working well. The only challenge I'm faced with now is that
while there is usually only a single action, there can be multiple results.
So I need a way to differentiate between actions and results. What I've
decided to do is base the division on line placement; multiple actions and
multiple results will be separated by a blank line, while the first result
will follow actions on the next immediate line. As the paragraphs are
iterated I need a way to determine if and when a blank line exists (or does
not exist) between paragraphs so I can create the necessary bookmark. Any
ideas?

Thanks again,

~ Dave
 
G

Greg Maxey

Jezebel,

I was on the road all day today (450 miles to attend a 1 hour meeting) :-(

I meant to try your range method on my Word2000 program at work this morning
before I left, but didn't have time.

Have you discovered a reason for the odd behaviour in Word2003
 
J

Jean-Guy Marcil

Jezebel was telling us:
Jezebel nous racontait que :
You'll make life easier for yourself if you can work entirely with
paragraphs rather than lines. As you've seen, the Word object model
doesn't actually include lines as such. Unless your paragraphs

Until recently, this is what I also thought... The other day I stumbled upon
something.
There are Page and Line collections in Word...

The page collection is under the Pane object, and the line collection is
under the rectangle collection which is under the page object from the page
collection.

Play around with this code:

'_______________________________________
Sub Test()

Dim MyPane As Pane
Dim MyPage As Page
Dim MyRect As Rectangle
Dim MyLine As Line
Dim PaneCount As Long
Dim PageCount As Long
Dim RectCount As Long
Dim LineCount As Long
Dim i As Long

PaneCount = ActiveWindow.Panes.Count
Set MyPane = ActiveWindow.ActivePane

PageCount = MyPane.Pages.Count
Set MyPage = MyPane.Pages(1)

RectCount = MyPage.Rectangles.Count
Set MyRect = MyPage.Rectangles(1)

LineCount = MyRect.Lines.Count
Set MyLine = MyRect.Lines(1)

For i = 1 To RectCount
Set MyRect = MyPage.Rectangles(i)
MsgBox MyRect.RectangleType
'0 = Text range
'1 = Shape
'7 = System > Drawing layer??? Will generate an error on the next line.
MyRect.Range.Select
Next

End Sub
'_______________________________________

Just type gibberish for a few pages, and try the code.
Then add an autoshape. You will go from 1 to 3 rectangles. One for the text
on the page, one for the shape itself and a mysterious one that belongs to
the System type.
Then add a text box. You will now have 5 rectangles, as above, plus one for
the textbox autoshape and one for the textbox text. Interestingly, it does
not matter how many shapes/textboxes you add to the page, the system
rectangle type is always the last one of the collection and it does not
appear if you have only text on the page.

Having just discovered those collections and never really having used them
in "real life," I was wondering if you, or anybody else reading these lines,
might have used them before, and thus could comment on their usefulness or
drawbacks.

If there are no real drawbacks, I think they offer interesting solutions for
certain problems we might sometimes face.

One drawback I can see is that these are new to Word 2003, so there might be
problems with backward compatibility...
--
Salut!
_______________________________________
Jean-Guy Marcil - Word MVP
(e-mail address removed)
Word MVP site: http://www.word.mvps.org
 
G

Greg

Jezebel,

I see the same odd behaviour using Word2000. I tried both of your
examples that it doesn't perform as you expect in Word203 and the
behaviour is identical. I am just a novice and have no clue what is
going on. I will be watching to see if someone comes around wiht an
explanation.
 
H

Helmut Weber

Hi Greg, hi Jezebel,
Set ppar = ActiveDocument.Paragraphs(1)
Do
i = i + 1
ppar.Range.Text = String$(i, Chr$(64 + i)) & vbCr
Loop Until ppar Is Nothing

may I add my own decent bit,

in former times, until Word 6.0, I think,
there was an end-of-doc-mark, represented by a diamond.
This symbol vanished in the windows-versions of word,
and was replaced by an ordinary paragraph symbol,
but only on the surface. The end-of-doc-mark is still there,
but hidden. It can't be replaced and can't be overwritten.

So ppar.Range.Text = String$(i, Chr$(64 + i)) & vbCr
results in an additional paragraph at the doc's end,
like replacing all ^p by ^p results in an additional paragraph.

The end-of-doc-mark can't be deleted, too, in way,
of course, as then the doc would be endless,
in Word's way of thinking. ;-)

You could delete the last paragraph mark,
if there is an immediately preceding paragraph mark,
but then the underlying end-of-doc-mark jumps to
the immediately preceding paragraph mark and hides there.
A rather naive way of explanation, I admit,
but there may be something to it.

Greetings from Bavaria, Germany

Helmut Weber, MVP
"red.sys" & chr(64) & "t-online.de"
Word XP, Win 98
http://word.mvps.org/
 
J

Jean-Guy Marcil

Jezebel was telling us:
Jezebel nous racontait que :
Interesting indeed. I've only just moved to W2003, so this is all new
to me too. A couple of observations:

- You have to be in Print Layout view for it to work. This could be a
problem with remote automation.

Right!
You could force it with ActivePane.View...
- There's something mysterious about these rectangles. I tried it
with a plain page of text and got three rectangles all of type
wdtextrectangle -- header, footer, and body in that order. Presumably
there's some way to work out which is which but it doesn't leap out.
Checking the .Top property, I guess.

Good catch, I had not tested it with headers/footers.
It seems that header/footer always come before body text in the index
enumeration. So that could help, if you knew there was a header/footer...
- As you observe, adding a textbox adds three more rectangles. The

Slight correction: adding the *first* shape adds the extra "system"
rectangle, all subsequent shapes do not.
But this special rectangle is always the last one in the collection.
text box, its content, and this wierd wdSystem rectangle, which the
documentation helpfully describes as 'Not applicable'. It seems to be
a non-object -- in the collection, but not retrievable and none of
the properties are valid.

So you can indeed iterate the document's lines, using code like --

Sub IterateDocLines()

Dim pPage As Word.Page
Dim pLine As Word.Line

For Each pPage In ActiveWindow.ActivePane.Pages
For Each pLine In pPage.Rectangles(3).Lines
Debug.Print pLine.Range
Next
Next

End Sub

(.. Rectangles(3) in my case because the documents have headers and
footers.) Strange things are going to happen if you change the lines
as you go (unless they are discrete paragraphs anyway) because
changes will affect the following lines.

In all, an interesting new feature. I'd suggest its value is for
automated formatting rather than automated editing. Need to think
about it some more. Thanks for pointing it out.

I think you are right about line editing... it would quickly become a mess.
But I like the Page collection, you can now get a page range in a range
object without using the selection object (.Bookmarks("\Page").Range
....etc.).

--
Salut!
_______________________________________
Jean-Guy Marcil - Word MVP
(e-mail address removed)
Word MVP site: http://www.word.mvps.org
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top