Advanced find/replace in code

J

Jeff Hunt

I would like to scan a document until a certain sequence of characters is
found (ie, <\B22>) then select from there until another sequence (</B22>) is
found, and then apply formatting changes to any characters in between. I
tried it with find/replace, but couldn't apply all the formatting changes I
wanted correctly to the "between" characters. Plus, I need to do this for
multiple characters with different formatting, so doing it in code will speed
that up. Any ideas on the best way to do this? FYI, I am proficient at VBA
in Access and Excel, but have never coded for Word, so I'm unfamiliar with
its functions. Oh, and it's Word 2003.

Thanks!
 
J

Jay Freedman

Jeff said:
I would like to scan a document until a certain sequence of
characters is found (ie, <\B22>) then select from there until another
sequence (</B22>) is found, and then apply formatting changes to any
characters in between. I tried it with find/replace, but couldn't
apply all the formatting changes I wanted correctly to the "between"
characters. Plus, I need to do this for multiple characters with
different formatting, so doing it in code will speed that up. Any
ideas on the best way to do this? FYI, I am proficient at VBA in
Access and Excel, but have never coded for Word, so I'm unfamiliar
with its functions. Oh, and it's Word 2003.

Thanks!

You can do this with wildcard searches. See
http://www.gmayor.com/replace_using_wildcards.htm.

If you get started and then get stuck, post back in this thread with a
detailed description of what's going wrong, and include whatever code you
have so far.

--
Regards,
Jay Freedman
Microsoft Word MVP
Email cannot be acknowledged; please post all follow-ups to the newsgroup so
all may benefit.
 
P

Pesach Shelnitz

Hi Jeff,

The following macro finds the text between all instances of pairs of your
two character sequences and formats it as italic.

Sub FindAndFormat()
Dim myRange As Range

Set myRange = ActiveDocument.Range
With myRange
.Start = 0
Do While .Find.Execute(FindText:="<\B22>", _
Wrap:=wdFindStop, Forward:=True) = True
.Select
With Selection
.Collapse Direction:=wdCollapseEnd
.Extend
.Find.ClearFormatting
If .Find.Execute(FindText:="</B22>", _
Forward:=True, Wrap:=wdFindStop) = True Then
.End = .End - 6
.Font.Italic = True
End If
.Collapse Direction:=wdCollapseEnd
End With
Loop
End With
Set myRange = Nothing
End Sub

Write back if you need more help getting it to do the exact formatting that
you want.
 
J

Jeff Hunt

That code works great, and I was able to get the formatting I needed to work.
However, I'm finding some inconsistent results. I modified your code to
make it easier for me to replicate it multiple times (there are about 30
different "field codes" I need to go through and format). This is roughly
what it looks like now:

strOpen = "<\B22>"
strClose = "</B22>"
With myRange
.Start = 0
Do While .Find.Execute(FindText:=strOpen, Wrap:=wdFindStop,
Forward:=True) = True
.Select
With Selection
.Collapse Direction:=wdCollapseEnd
.Extend
.Find.ClearFormatting
If .Find.Execute(FindText:=strClose, Forward:=True,
Wrap:=wdFindStop) = True Then
.End = .End - Len(strClose)
.Font.Bold = True
End If
.Collapse Direction:=wdCollapseEnd
End With
Loop
End With

As it goes through, it is working for a few of the field codes, then
skipping some, then working again. For example, after searching for <\B22>,
the next field code it looks for is <\FD> but it never finds any, even though
the document contains many instances of these field codes. It then works for
the next field code. The really weird part is that when I ran it on a
different document that used both of these codes, it ran just fine. Another
set it failed on was <\I> and <\U>. When I ran <\I> first, it never found
any <\U>. When I reversed these in the VBA, so <\U> ran first, it worked
fine for both codes.

Any ideas on what might be causing this, or how to prevent it? The "fix"
for <\U> and <\I> won't work for everything, because I can't spend that much
time testing and rearranging the sections of code because of the high volume
of field codes I would have to arrange.
 
J

Jeff Hunt

I had already determined that using wildcard searches wasn't going to cut it
for what I'm doing. Part of it is because some of the text I need to find
and format can be paragraphs long, including punctuation. This makes the
"find" section rather difficult to write, even with wildcards. I was also
having difficulty applying formatting, because some of what I wanted it to do
was apply borders and shading, which I could not get to work properly in the
Find/Replace dialog (I even tried making them Styles, which still didn't
quite work).

Having said all that, I do want to thank you for the reply, and not just for
the effort in making the post. The site you posted is definitely going to
help me in other aspects of what I do, so thank you very much for that!
 
D

Doug Robbins - Word MVP

Use

Dim myrange As Range
Selection.HomeKey wdStory
Selection.Find.ClearFormatting
With Selection.Find
Do While .Execute(FindText:="<\B22>", Forward:=True, _
MatchWildcards:=False, Wrap:=wdFindStop, MatchCase:=False) = True
Set myrange = Selection.Range
myrange.End = ActiveDocument.Range.End
myrange.End = myrange.Start + InStr(myrange, "</B22>") - 1
myrange.Start = myrange.Start + 6
'myrange will now contain all of the text between <\B22> and </B22>
'Do something with myrange
Selection.Collapse wdCollapseEnd
Loop
End With


--
Hope this helps.

Please reply to the newsgroup unless you wish to avail yourself of my
services on a paid consulting basis.

Doug Robbins - Word MVP, originally posted via msnews.microsoft.com
 
J

Jeff Hunt

Hmm, that didn't appear to do anything. When I run it on the document, it
does its thing without changing anything (I put a .font.bold = true where you
had the 'Do something with myrange), and ends up with the cursor placed right
after the last occurance of <\B22>. I stepped through the code, and it is
looping correctly, and progressing down the document, but all that it is
doing is highlighting the opening field code (<\B22>) and never selecting
anything between the codes. Unfortunately, I am not familar enough with
ranges to diagnose what it is supposed to be doing other than that.

Thanks.
 
D

Doug Robbins - Word MVP

That was to be expected. You must insert some code to do whatever it is
that you want to do with the text that is selected in place of the

'Do something with myrange

--
Hope this helps.

Please reply to the newsgroup unless you wish to avail yourself of my
services on a paid consulting basis.

Doug Robbins - Word MVP, originally posted via msnews.microsoft.com
 
J

Jeff Hunt

I did put an action there (.font.bold). See my previous post, inside the
parentheses. When I F8 stepped thru the code, I never saw it select anything
except the opening field code (<\B22>), which isn't the part that is supposed
to be changed.

After several days and at least as many reboots, the weirdness from the code
that Pesach Shelnitz posted seems to have gone away, and it is working
consistently now. If you figure out why your code doesn't seem to work for
me, I would be interested in knowing for learning's sake, but since I have
code that works now, you don't need to spend the time unless you want to.
Thanks for your input on my problem!
 
D

Doug Robbins - Word MVP

If you wanted to delete the tags and format the text in between them, you
should have said that was what you wanted to do.

This will do that:

Dim myrange As Range
Selection.HomeKey wdStory
Selection.Find.ClearFormatting
With Selection.Find
Do While .Execute(FindText:="<\B22>", Forward:=True, _
MatchWildcards:=False, Wrap:=wdFindStop, MatchCase:=False) = True
Set myrange = Selection.Range
myrange.End = ActiveDocument.Range.End
myrange.End = myrange.Start + InStr(myrange, "</B22>") + 5
myrange.Select
myrange.Text = Mid(myrange.Text, 7, Len(myrange.Text) - 12)
myrange.Font.Bold = True
Loop
End With



--
Hope this helps.

Please reply to the newsgroup unless you wish to avail yourself of my
services on a paid consulting basis.

Doug Robbins - Word MVP, originally posted via msnews.microsoft.com
 

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