How to loop until end of document?????

P

pjm

Hi, I hope someone here can help me with this... I've been perplexed b
this ever since WordBasic got dumped for VBA with all its "helpful
objects. I've messed with this until blue in the face and never foun
whatever the simple answer must be. Now I simply use Vi to do it bu
would LOVE to be able to do it in Word:
Simply: How do you repeat a recorded macro until the end of th
document, with the logic:
While NOT EOF
Repeat until end of document

For example, sometimes when dealing with really long database report
that are formatted for a # of lines per page, I'll record a macro tha
searches for the next occurence of a word, then move the cursor 5 char
to the right, then select to the end of the line, then delete, the
search for the previous instance of something else..etc.etc. And the
I want to do all this over and over again until the end of th
document.
I'll record the macro and would like to enclose it in a loop lik
above. But what to test for? I've tried making an infinite loop but i
seems to wrap to the top of the document when it hits the end. This i
such a simple and common problem, but for the life of me I can't figur
out how to do it!!! HELP!! Thanks, Pete
 
D

Doug Robbins - Word MVP - DELETE UPPERCASE CHARACT

Hi PJM,

The best way to do this is to us a Do While. Execute( ) = True loop as in
the following code to round all numbers in a document to 2 decimal places:

Selection.Find.ClearFormatting
With Selection.Find
Do While .Execute(FindText:="[0-9]{1,}.[0-9]{3,}", MatchWildcards: =
True, Wrap:=wdFindContinue, Forward:=True) = True
Selection.Range.Text = Round(Selection.Range.Text, 2)
Loop
End With

*If you're seeing this through Rubin's crappy web site, you should know
that he does not have my permission to include this message on his website.
I own the copyright, and I grant a license to Microsoft, Google and the
usenet community. I deny Rubin the right to repost my message on his site.*

Please post any further questions or followup to the newsgroups for the
benefit of others who may be interested. Unsolicited questions forwarded
directly to me will only be answered on a paid consulting basis.

Hope this helps
Doug Robbins - Word MVP
 
P

pjm

Couldn't get this to work on a test example. If there are many steps in
the recorded macro, multiple Selection.Finds, etc. it seems to not
work. For example I recorded a bunch of steps that might simulate
cursor movement within a database document. This is the code that
resulted:


Selection.Find.ClearFormatting
With Selection.Find
..Text = "rain"
..Replacement.Text = ""
..Forward = True
..Wrap = wdFindContinue
..Format = False
..MatchCase = False
..MatchWholeWord = False
..MatchWildcards = False
..MatchSoundsLike = False
..MatchAllWordForms = False
End With
Selection.Find.Execute
Selection.MoveRight Unit:=wdCharacter, Count:=1
Selection.MoveLeft Unit:=wdCharacter, Count:=3
Selection.TypeBackspace
Selection.TypeText Text:="R"
Selection.MoveRight Unit:=wdWord, Count:=6
Selection.EndKey Unit:=wdLine
Selection.Find.ClearFormatting
With Selection.Find
..Text = "rain"
..Replacement.Text = ""
..Forward = False
..Wrap = wdFindAsk
..Format = False
..MatchCase = False
..MatchWholeWord = False
..MatchWildcards = False
..MatchSoundsLike = False
..MatchAllWordForms = False
End With
Selection.Find.Execute
Selection.MoveLeft Unit:=wdWord, Count:=1
Selection.Delete Unit:=wdCharacter, Count:=1
Selection.TypeText Text:="R"
Selection.MoveDown Unit:=wdLine, Count:=1
Selection.HomeKey Unit:=wdLine)

What I want to do is carry out these steps, and then do it again and
again until it runs out of text to do it with! I couldn't place all of
this in the do while.execute()loop construct..
 
D

Dave Lett

Hi PJM,

Yes, as Doug recommends, you should put this in a Do ... While loop. However, I cannot figure out what you want to do.

For example, if I start at the beginning of a document and find the word "rain", then there are NO previous instances of "rain" when I find the first one. Okay, so let's say that you're not starting the routine at the beginning of the document.
1) Find the next occurrence of "rain"
2) From that point find the _previous_ instance of "rain"
3) Go to the end of the current line
3) Go to step one
You will be in an infinite loop because you have .MatchCase set to false and, therefore, you will always only be finding the one instance of "rain".
Also, the way you're want to change "rain" into "Rain" is much more complicated than it needs to be. Essentially, it looks like you want to make that change for the whole document, so you can use the .MatchCase property and .MatchWholeWord property of the .Find method.

From the code that you've provided, I can deduce only that you want to replace "rain" with "Rain". If that's it, then you don't need a loop. You can use the wdReplaceAll constant of the Replace parameter. What you want _sounds_ simple enough. You mentioned about selecting to the end of the line and deleting, but I don't see that in the recorded macro.

This is how we might be able help at this point:
Give us a numbered list of what you want to do and think in terms of what you have and what you want to end with. Don't worry about the code right now.
1) Find "rain" and replace with "Rain"
2) From the end of the word "Rain" delete the rest of the line (is this "line" also to the end of the current paragraph?)
3) Do this for every instance of "rain"
Anything else?
 
P

pjm

Thanks, I've been off for a while during the holidays. I'm trying to
keep this as SIMPLE as possible! Let's say you were going to do a
DO...WHILE loop and simply wanted it to run from any point in the
document until the end of the document. What would you test for in the
while's condition? Reading a file in Visual Basic you would have:

Do While Not EOF(1) ' Loop until end of file.
TextLine = LineInput(1) ' Read line into variable.
Debug.WriteLine(TextLine) ' Print to the Command window.
Loop

After the end of the file the thing terminates. Instead of reading
lines from a file, I'm trying to operate on a document in Word. Is
there a function similar to EOF() that signals that you have reached
the end of a document?

There are many different ways I have found to solve my problem, but
they do not involve Word, and the ease of macro recording it affords
me. As I said above, the documents in question are usually canned
database reports where I have no access to the database report
generator. It is very easy to open up the document in Word and create a
macro that creates a (any) series of steps. I would be careful to move
the cursor to it's new starting place before I finished recording the
macro. Now if I assign this useful little macro (which may clean up 1
record in the database report) to a hotkey, I can invoke it again to
clean up the next record. Great, it works. Now I want to progamatically
run it again and again until it runs out of database "records".
Thanks... Peter
 
T

tzulah

I have also been searching for a solution to loop to EOF in a Word
macro. Doug's solution looks just like what I need, but it doesn't
work in a test macro for me either. It never gets into the loop body -
it skips out on the first pass. Yes, I am using a document with plenty
of content, and the cursor is placed somewhere near the beginning.

My purpose is to read a structured document and extract bits of
information into a comma-delimited file. Right now, I am using While
(InStr(Selection.Text, "APPENDIX") = 0), but this only works on
documents that have at least one appendix. Since this method does work
for me though, I will be forced to continue using it unless I can find
a better way of finding the end of file.

I suspect the problem lies in (FindText:="[0-9]{1,}.[0-9]{3,}"), but my
grasp of regular expressions isn't good enough to be able tweak it to
work for me.

Can anybody suggest anything?
 
D

Doug Robbins - Word MVP - DELETE UPPERCASE CHARACT

Hi Tzulah,

The FindText:="[0-9]{1,}.[0-9]{3,}" was specific to that example which was
looking for all numbers containing more than 3 decimal places in the
document and rounding them to two decimal places. Somewhat different from
what you are trying to achieve.

I can't quite work out for your (InStr(Selection.Text, "APPENDIX") = 0),
exactly what it is that you are try to extract into the comma delimited
file. Tell us some more about that and we may be able to help.

Please post any further questions or followup to the newsgroups for the
benefit of others who may be interested. Unsolicited questions forwarded
directly to me will only be answered on a paid consulting basis.
Hope this helps
Doug Robbins - Word MVP
 
D

Doug Robbins - Word MVP - DELETE UPPERCASE CHARACT

Hi pjm,

Recording macros in Word is generally not the best way of producing code.
It's still not really clear what it is that you want to do, but I would
still suggest that a Do While. Execute( ) = True loop is what you should be
using.

Give us a more specific example and we can probably help.

Please post any further questions or followup to the newsgroups for the
benefit of others who may be interested. Unsolicited questions forwarded
directly to me will only be answered on a paid consulting basis.
Hope this helps
Doug Robbins - Word MVP
 
P

pjm

The reason why I'm shying off giving a specific example is that I am
looking for a general answer to the question: How do you loop a
recorded macro until the end of a document?
But I'll try to contrive a document, and show you what I mean:
EDIT: I JUST NOTICED THE FORUM SOFTWARE REMOVES MULTIPLE SPACES. THE
EXAMPLE DOCUMENT BELOW IS SUPPOSED TO HAVE 5 SPACE BETWEEN EACH "FIELD"
WITH THE FIELDS BEING NAME,QUANTITY,DESCRIPTION,PRICE!!

January 7th, 2004 Monkeytronics International P.1

User criminy Report 5:47 pm

smith, samuel 7 small robotic monkey oiler 7.95
einstien, albert 1 large simian servo motor 25.99
wonderland, alice 2 silicon orang glove, rt 11.99

----------------INTERNAL USE ONLY BY M.I. ONLY---------------------

January 7th, 2004 Monkeytronics International P.2

User criminy Report 5:47 pm

goodall, jane 2 hurdy-gurdy synth modules 20.99
mason, perry 1 kevlar breast plate, gorilla 22.59
killy, jean-claude 6 deep charge batteries 50.00

----------------INTERNAL USE ONLY BY M.I. ONLY---------------------

I record a macro to format the report the way I want it, specifically
to uppercase the first and last names, and to put a $ in front of the
price field. Note that the fields are separated by 5 spaces, and the
first and last names are separated by a comma and a space. This macro
works fine. If I execute it several times, each line that contains a
name (identified by ", " will be upper-cased, and each price will have
a $ in front of it (identified by finding the first numeric character
which is preceded by 5 spaces from the end of the line):
Sub monkey()
'
' monkey Macro
' Macro recorded 1/8/2004 by pjm
'
Selection.Find.ClearFormatting
With Selection.Find
Text = "[a-z], [a-z]"
Forward = True
Wrap = wdFindContinue
Format = False
MatchCase = False
MatchWholeWord = False
MatchAllWordForms = False
MatchSoundsLike = False
MatchWildcards = True
End With
Selection.Find.Execute
Selection.HomeKey Unit:=wdLine
Selection.MoveRight Unit:=wdCharacter, Count:=1, Extend:=wdExtend
Selection.Range.Case = wdUpperCase
Selection.HomeKey Unit:=wdLine
Selection.Find.ClearFormatting
With Selection.Find
Text = "[a-z], [a-z]"
Forward = True
Wrap = wdFindContinue
Format = False
MatchCase = False
MatchWholeWord = False
MatchAllWordForms = False
MatchSoundsLike = False
MatchWildcards = True
End With
Selection.Find.Execute
Selection.MoveLeft Unit:=wdCharacter, Count:=1
Selection.MoveRight Unit:=wdCharacter, Count:=3
Selection.MoveRight Unit:=wdCharacter, Count:=1, Extend:=wdExtend
Selection.Range.Case = wdUpperCase
Selection.EndKey Unit:=wdLine
Selection.Find.ClearFormatting
With Selection.Find
Text = " [0-9]"
Forward = False
Wrap = wdFindAsk
Format = False
MatchCase = False
MatchWholeWord = False
MatchAllWordForms = False
MatchSoundsLike = False
MatchWildcards = True
End With
Selection.Find.Execute
Selection.MoveRight Unit:=wdCharacter, Count:=1
Selection.MoveLeft Unit:=wdCharacter, Count:=1
Selection.TypeText Text:="$"
Selection.EndKey Unit:=wdLine
End Sub

Now this report goes on for, lets say, 7029 pages. In this simple
example I suppose you could figure that there are 3 data lines per page
in the report, but in real reports, it might not be so consistent. The
question is - How to loop this macro to keep executing until it reaches
the end of the document?
 
E

Ed

Have you looked at Predefined Bookmarks in Word VBA HELP? There's a
"\EndOfDoc" bookmark in every document, it says. I haven't used this yet,
but it sounds like it's worth exploring.

Ed

pjm said:
The reason why I'm shying off giving a specific example is that I am
looking for a general answer to the question: How do you loop a
recorded macro until the end of a document?
But I'll try to contrive a document, and show you what I mean:
EDIT: I JUST NOTICED THE FORUM SOFTWARE REMOVES MULTIPLE SPACES. THE
EXAMPLE DOCUMENT BELOW IS SUPPOSED TO HAVE 5 SPACE BETWEEN EACH "FIELD"
WITH THE FIELDS BEING NAME,QUANTITY,DESCRIPTION,PRICE!!

January 7th, 2004 Monkeytronics International P.1

User criminy Report 5:47 pm

smith, samuel 7 small robotic monkey oiler 7.95
einstien, albert 1 large simian servo motor 25.99
wonderland, alice 2 silicon orang glove, rt 11.99

----------------INTERNAL USE ONLY BY M.I. ONLY---------------------

January 7th, 2004 Monkeytronics International P.2

User criminy Report 5:47 pm

goodall, jane 2 hurdy-gurdy synth modules 20.99
mason, perry 1 kevlar breast plate, gorilla 22.59
killy, jean-claude 6 deep charge batteries 50.00

----------------INTERNAL USE ONLY BY M.I. ONLY---------------------

I record a macro to format the report the way I want it, specifically
to uppercase the first and last names, and to put a $ in front of the
price field. Note that the fields are separated by 5 spaces, and the
first and last names are separated by a comma and a space. This macro
works fine. If I execute it several times, each line that contains a
name (identified by ", " will be upper-cased, and each price will have
a $ in front of it (identified by finding the first numeric character
which is preceded by 5 spaces from the end of the line):
Sub monkey()
'
' monkey Macro
' Macro recorded 1/8/2004 by pjm
'
Selection.Find.ClearFormatting
With Selection.Find
Text = "[a-z], [a-z]"
Forward = True
Wrap = wdFindContinue
Format = False
MatchCase = False
MatchWholeWord = False
MatchAllWordForms = False
MatchSoundsLike = False
MatchWildcards = True
End With
Selection.Find.Execute
Selection.HomeKey Unit:=wdLine
Selection.MoveRight Unit:=wdCharacter, Count:=1, Extend:=wdExtend
Selection.Range.Case = wdUpperCase
Selection.HomeKey Unit:=wdLine
Selection.Find.ClearFormatting
With Selection.Find
Text = "[a-z], [a-z]"
Forward = True
Wrap = wdFindContinue
Format = False
MatchCase = False
MatchWholeWord = False
MatchAllWordForms = False
MatchSoundsLike = False
MatchWildcards = True
End With
Selection.Find.Execute
Selection.MoveLeft Unit:=wdCharacter, Count:=1
Selection.MoveRight Unit:=wdCharacter, Count:=3
Selection.MoveRight Unit:=wdCharacter, Count:=1, Extend:=wdExtend
Selection.Range.Case = wdUpperCase
Selection.EndKey Unit:=wdLine
Selection.Find.ClearFormatting
With Selection.Find
Text = " [0-9]"
Forward = False
Wrap = wdFindAsk
Format = False
MatchCase = False
MatchWholeWord = False
MatchAllWordForms = False
MatchSoundsLike = False
MatchWildcards = True
End With
Selection.Find.Execute
Selection.MoveRight Unit:=wdCharacter, Count:=1
Selection.MoveLeft Unit:=wdCharacter, Count:=1
Selection.TypeText Text:="$"
Selection.EndKey Unit:=wdLine
End Sub

Now this report goes on for, lets say, 7029 pages. In this simple
example I suppose you could figure that there are 3 data lines per page
in the report, but in real reports, it might not be so consistent. The
question is - How to loop this macro to keep executing until it reaches
the end of the document?
 
D

Dave Lett

Hi Peter

I understand your hesitancy to provide a specific example, but the goal often determines the method. I think what you're looking for is the .Wrap parameter. In the example you provide, the setting is WdFindContinue. If you change that to WdFindStop, Word will only search to the end of the file. Nevertheless, as Doug mentions, using the recorder is not the best way to generate code (in short, it's bloated). The good side is that it might expose you to methods and properties that you don't know about. The worst part of using the recorder is that you cannot recorder _any_ decision structures or loops. Looking at your code and what you have said you want to accomplish, I have generated the following code (it's much shorter than the example you provided if you remove the copious comments, which I've provided because it might help understand what I've done)

Dim oRng As Rang
''' set the range variable to equal the current selectio
Set oRng = Selection.Rang

With Selection.Fin
''' find a word, a comma, and a wor
.Text = "<*>, <*>
.ClearFormattin
.MatchWildcards = Tru
''' go only to the end of the documen
.Wrap = wdFindSto
Do While .Execut
With Selectio
''' if the word, comma, and word are at the beginnin
''' of a paragraph, then change the cas
If .Start = .Paragraphs(1).Range.Start The
.Range.Case = wdTitleWor
.MoveDown unit:=wdParagraph, Count:=
End I
End Wit
Loo
''' reselect the original selectio
''' add a dollar sign in front of al
''' numbers that are 1 or more AND followe
''' by a period AND followed by any 2 number
''' this will replace 1234.44 with $1234.44 bu
''' will handle 1,234.44 as 1,$234.44 (we can mak
''' that adjustment if needed
oRng.Selec
.Text = "([0-9]{1,}.[0-9]{2,2})
With .Replacemen
.Text = "$\1
.ClearFormattin
End Wit
.Execute Replace:=wdReplaceAl
End Wit

If you need more guidance on wildcard searches, then have a look at the Word MVP website. Among other things, they have a couple of great articles devoted to wildcard searches (one on understanding the wildcard options, and one on preventing errors after an unsuccessful search)

HTH
Dave
 
D

Dave Lett

Well, I tried to reply this message two other times today, and I don't see either of the posts, so here's to hoping that third time's a charm

Peter, I think you might NOT need a VBA routine at all. You see, after these several posts, you mentioned "fields" and "7029 pages", which leads me to believe that you're doing some type of mailmerge. Consequently, you only have to use field switches to format the data as you want it. That is, add the *\ Caps switch to the Name field and the \# $#,###.00 switch to the Price field. Word will format the data for you, and no messy routines and whatnot

HTH
Dave
 
D

DoEventsXoc

Hey guys - I ran across this discussion trying to get the same answe
myself. Well, a bit googling and a bit of experimenting and I did it.

Here's how to loop until the end of the document:

Do
//whatever

Loop Until (Selection.End = ActiveDocument.Content.End - 1)


Hope this helps
 
R

rachelle34

I need the following while loop to end at the end of the document.
have tried both the previous examples.

endParameter = True
While (endParameter)
If ((Right(Selection.Text, 10) = "Event Date") Or
(Right(Selection.Text, 10) = "EVENT DATE")) Then
endParameter = False
Else
Selection.MoveRight Unit:=wdWord, Count:=1, Extend:=wdExtend
End If
Wen
 
D

Doug Robbins - Word MVP - DELETE UPPERCASE CHARACT

Response in vba.beginnners

--
Please post any further questions or followup to the newsgroups for the
benefit of others who may be interested. Unsolicited questions forwarded
directly to me will only be answered on a paid consulting basis.
Hope this helps
Doug Robbins - Word MVP
 

ptb

Joined
Jan 27, 2021
Messages
1
Reaction score
0
Do
//whatever

Loop Until (Selection.End = ActiveDocument.Content.End - 1)
Thanks a lot for this simplest of solutions. Somehow I was not able to make eof works and now you have opened a new universe of possibility!
 

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