PDA

View Full Version : Solved: Find ALL instances and format entire line



Jinky Julie
04-07-2009, 12:31 PM
Hi again...

I think I am in over my head on this one... :dunno I am new to VBA and playing with .Parent !?!?!?! Yikes!!!

I trying to find all instances of a word, select the entire line that it is found in and change the line to red. (not sure if this matters... but there can be no more than four instances in the document... and the lines are short... three or four words... boss' requirements... not mine...)

This works... sort of... It catches the first instance fine and formats it OK, but misses the rest and gets caught in an endless loop... I am not sure why...




With ActiveDocument.Content.Find
.Text = "banana"
Do While .Execute(findText:="banana", Forward:=True, _
Wrap:=wdFindContinue, Format:=True) = True
With .Parent
.StartOf Unit:=wdParagraph, Extend:=wdExtend
.Font.Color = wdColorRed
End With
Loop
End With



Any hints or suggestions would be most appreciated.... Maybe there's a better way... this looked good and I've adapted it to my needs... but...

Thanks, as always...

Julie

Jinky Julie
04-07-2009, 12:33 PM
(not sure if this matters... but there can be no more than four instances in the document... )

This does not matter... just mentioned it in case it was germane... it's not...

fumei
04-07-2009, 01:28 PM
It makes an endless loop because you have changed the range.

Here are the rules for .Find.

The range itself is changed to the range of .Found. Perhaps a demonstration, keeping it simple....

ActiveDocument.Content.Find

is the whole document, right? Let's say the whole document is:

This is one banana.
This is another banana.
This paragraph does not have THAT word.
Oh my goodness, here is a whole..ummmm, bunch of banana.

OK. So, at the start, with ActiveDocument.Content.Find , the range is (in bold):

This is one banana.
This is another banana.
This paragraph does not have THAT word.
Oh my goodness, here is a whole..ummmm, bunch of banana.

The whole thing. On the first .Found = True, the range ITSELF is changed to (in bold):

This is one banana.
This is another banana.
This paragraph does not have THAT word.
Oh my goodness, here is a whole..ummmm, bunch of banana.

Your code:With .Parent
.StartOf Unit:=wdParagraph, Extend:=wdExtend
changes the range itself.

RULE: in a .Find operation, if the range itself is altered, the .Find continues on starting at the start of the current range.

So...... when you used .Parent, and the .Extend, the range became (in bold):

This is one banana.
This is another banana.
This paragraph does not have THAT word.
Oh my goodness, here is a whole..ummmm, bunch of banana.

So.....the next .Found will be.....

This is one banana.
This is another banana.
This paragraph does not have THAT word.
Oh my goodness, here is a whole..ummmm, bunch of banana.

Again.

And again.

And again.

An endless loop.

Got that? What to do? Fortunately, this is easy.

1. use a range object
2. collapse the range after each iteration.

BTW: there is no need to define your search string twice.
Sub RedBanana()
' declare and set range object
Dim r As Range
Set r = ActiveDocument.Range
With r.Find
Do While .Execute(findText:="banana", Forward:=True) = True
With r ' thus using the range object itself
.StartOf Unit:=wdParagraph, Extend:=wdExtend
.Font.Color = wdColorRed
End With
' collapse the range to its end
r.Collapse Direction:=wdCollapseEnd
Loop
End With
End Sub
In other words...you do not even have to use .Parent.

Demo attached. Click "Red Banana" on the top toolbar.

fumei
04-07-2009, 01:38 PM
Oh, and please try and be careful with terms. I think I understood what you meant because you used "wdParagraph" in your code.

"lines" is an imprecise term in Word. You meant "paragraph". I understand when we look at a document we - as humans looking at the document - think..."lines". However, Word, does not.

Word deals with paragraphs. Using the standard <p> to represent a paragraph mark.....

This is ONE paragraph
that has been made into
four "lines" by using
line breaks.<p>

This is FOUR paragraphs<p>
that has been made into<p>
four "lines" by using<p>
paragraph marks.<p>

Can you see how similar they are? Both are seen by our eyes as FOUR "lines", but in one case it is ONE paragraph, in the other it is FOUR paragraphs.

This is a big - HUGE! - difference. Especially when coding in VBA.

This is why, if you are serious, you should keep Show/Hide set as ON.

Jinky Julie
04-08-2009, 04:03 AM
Fumei, you rule!!!

Twice in one day no less.... Thank you so very much for your help and the explanation... that what makes it.... you help us learn...

Best regards,

Julie

Paul_Hossler
04-08-2009, 04:39 AM
This was VERY enlightening and clear about .Find

Is this sort of tutorial documented or captured in the KB or anywhere else?

Paul

fumei
04-08-2009, 11:35 AM
Not that I know of. I have mentioned how .Find works a number of times in threads. I know, I know...I should get it into the KB. Just have not got around to it.

No, how .Find really works is not documented, at least by Microsoft. It is not in VBA Help.

The way I found out how it works - exactly - is by carefully stepping through a .Find operation and actually looking to see what goes on.

Stepping through your code is a very good learning tool. A lot of people do not, but it is an approach I strongly recommend.