Converting Format tags

P

Peter

Hi,
I'm trying to write a macro to convert tags (like html tags) using the Range
object.
I can do it using the selection object easy enough but would like to convert
to using a range object for performance.
Here is a the selection object code.

Selection.StartOf (6) ' Convert Bold tags
Selection.Find.Text = "<B>"
Selection.Find.Execute
Do While Selection.Find.Found
Selection.ExtendMode = True
Selection.Find.Text = "<P>" ' end of bold
Selection.Find.Execute
Selection.Font.Bold = True
Selection.MoveRight 1, 1
Selection.ExtendMode = False
Selection.Find.Text = "<B>"
Selection.Find.Execute
Loop

Any help much appreciated.

Thanks Peter
 
G

Greg

Peter,

Maybe something like:
Sub Test()
Dim myRange As Word.Range
Set myRange = ActiveDocument.Range

With myRange.Find
.ClearFormatting
.Replacement.ClearFormatting
.MatchWildcards = True
.Text = "\<B\>*\<P\>"
.Replacement.Text = "^&"
.Replacement.Font.Bold = True
.Execute Replace:=wdReplaceAll
End With
Set myRange = Nothing
End Sub
 
H

Helmut Weber

Hi Peter,

like this:

Sub Makro3()
Dim rDcm As Range
Set rDcm = ActiveDocument.Range
ResetSearch
With rDcm.Find
.Text = "<B>*<P>"
.Replacement.Text = "^&"
.Replacement.Font.Bold = True
.MatchWildcards = True
.Execute Replace:=wdReplaceAll
End With
ResetSearch
End Sub
' ----
Public Sub ResetSearch()
With Selection.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = ""
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
' plus some more if needed
.Execute
End With
End Sub

See: http://word.mvps.org/faqs/General/UsingWildcards.htm

and I think, you'd better exclude the tags from formatting.

But that's somewhat more complicated.

Greetings from Bavaria, Germany

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

Helmut Weber

Hi Greg,

right you are,

didn't think of all the backslashes

"\<B\>*\<P\>"

Helmut Weber
 
J

Jay Freedman

Hi Peter,

You're going about this completely the wrong way. Switch over to using a
wildcard search (http://word.mvps.org/faqs/general/UsingWildcards.htm) for
the entire phrase from the start tag all the way to the end tag, and then
you can use the wdReplaceAll parameter in the .Execute to process the entire
document in one shot. This will be orders of magnitude faster than crawling
through the document the way you're doing it now.

This sample macro shows a number of features: How to use a range object for
Replace; how to use a subroutine with an argument to change its behavior;
how to use Select Case to do different actions based on the value of the
argument; and how to use a wildcard expression to match HTML tags (more on
this subject below the macro).

Private Sub ReplaceFormattingTags(strTag As String)
Dim oRg As Range
Set oRg = ActiveDocument.Range
With oRg.Find
.MatchWildcards = True
.ClearFormatting
.Replacement.ClearFormatting
.Format = False
.Forward = True
.MatchCase = False
.Text = "\<" & strTag & "\>([!\<\>]@)\</" & strTag & "\>"
.Replacement.Text = "\1"
Select Case strTag
Case "i", "I"
.Replacement.Font.Italic = True
.Execute Replace:=wdReplaceAll
Case "b", "B"
.Replacement.Font.Bold = True
.Execute Replace:=wdReplaceAll
Case "u", "U"
.Replacement.Font.Underline = wdUnderlineSingle
.Execute Replace:=wdReplaceAll
' add more cases for tags you want to handle
Case Else
' do nothing
End Select
End With
End Sub

Public Sub test()
ReplaceFormattingTags ("i")
ReplaceFormattingTags ("b")
End Sub

The wildcard expression in the macro is constructed like this:

Depending on the value of the argument strTag, the first portion "\<" &
strTag & "\> will match an opening tag like <i> or <I> (it will match either
because of the .MatchCase = False setting). As explained in the Wildcards
article, the backslashes tell VBA to treat the < and > as actual characters
to be matched, rather than their special wildcard meanings (start and end of
words).

Similarly, the ending portion \</" & strTag & "\>" will match the
corresponding closing tag like </i> or </I>.

The portion ([!\<\>]@) will match any sequence of characters that does *not*
contain any < or > character. The ( ) tell VBA that whatever is matched by
this portion will be given the alias \1 for use in the .Replacement.Text.
The effect of this is to remove the tags while simultaneously applying the
specified formatting to the text between the tags.
 
P

Peter

Hi Jay/Greg/Helmut,
Many thanks for the help, this has set me on the right track,

I simply used the * wildcard in the end since I strip all the tags at the
end. Also the .Replacement.Text was not needed and in fact caused an error.

I also forgot to mention that this code will come from a Visual FoxPro app.
so I'm busy trying to convert.
So far so good but i've falling at the last hurdle when trying to adapt the
..execute bit and I've also got to rearrange the DO CASE so that i can pass
strTag each time.

Anyway I dunno if you are VFP gurus but I'd thought let you know how i'm
doing.

Here's how far I've come...

#DEFINE wdReplaceAll 0
Local oRg, strTag, strTag2
strTag=
strTag2=[D]
#DEFINE wdUnderlineSingle 1
oRg = oWord.ActiveDocument.Range
With oRg.Find
.MatchWildcards = .t.
.ClearFormatting
.Replacement.ClearFormatting
.Format = .f.
.Forward = .t.
.MatchCase = .f.
.Text = [<] + strTag + [>*<] + strTag2 + [>]
.Replace = wdReplaceAll
DO CASE strTag
Case strTag=
.Replacement.Font.Italic = .T.
.Execute.Replace = wdReplaceAll
Case strTag=
.Replacement.Font.Bold = .t.
.Execute && this bit blows up. How do I pass the VBA equivelant of
Replace:= wdReplaceAll ?
Case strTag=
.Replacement.Font.Underline = wdUnderlineSingle
.Execute.Replace = wdReplaceAll
OTHERWISE
&& do nothing
ENDCASE
EndWith


Jay Freedman said:
Hi Peter,

You're going about this completely the wrong way. Switch over to using a
wildcard search (http://word.mvps.org/faqs/general/UsingWildcards.htm) for
the entire phrase from the start tag all the way to the end tag, and then
you can use the wdReplaceAll parameter in the .Execute to process the
entire
document in one shot. This will be orders of magnitude faster than
crawling
through the document the way you're doing it now.

This sample macro shows a number of features: How to use a range object
for
Replace; how to use a subroutine with an argument to change its behavior;
how to use Select Case to do different actions based on the value of the
argument; and how to use a wildcard expression to match HTML tags (more on
this subject below the macro).

Private Sub ReplaceFormattingTags(strTag As String)
Dim oRg As Range
Set oRg = ActiveDocument.Range
With oRg.Find
.MatchWildcards = True
.ClearFormatting
.Replacement.ClearFormatting
.Format = False
.Forward = True
.MatchCase = False
.Text = "\<" & strTag & "\>([!\<\>]@)\</" & strTag & "\>"
.Replacement.Text = "\1"
Select Case strTag
Case "i", "I"
.Replacement.Font.Italic = True
.Execute Replace:=wdReplaceAll
Case "b", "B"
.Replacement.Font.Bold = True
.Execute Replace:=wdReplaceAll
Case "u", "U"
.Replacement.Font.Underline = wdUnderlineSingle
.Execute Replace:=wdReplaceAll
' add more cases for tags you want to handle
Case Else
' do nothing
End Select
End With
End Sub

Public Sub test()
ReplaceFormattingTags ("i")
ReplaceFormattingTags ("b")
End Sub

The wildcard expression in the macro is constructed like this:

Depending on the value of the argument strTag, the first portion "\<" &
strTag & "\> will match an opening tag like <i> or <I> (it will match
either
because of the .MatchCase = False setting). As explained in the Wildcards
article, the backslashes tell VBA to treat the < and > as actual
characters
to be matched, rather than their special wildcard meanings (start and end
of
words).

Similarly, the ending portion \</" & strTag & "\>" will match the
corresponding closing tag like </i> or </I>.

The portion ([!\<\>]@) will match any sequence of characters that does
*not*
contain any < or > character. The ( ) tell VBA that whatever is matched by
this portion will be given the alias \1 for use in the .Replacement.Text.
The effect of this is to remove the tags while simultaneously applying the
specified formatting to the text between the tags.

--
Regards,
Jay Freedman
Microsoft Word MVP
Hi,
I'm trying to write a macro to convert tags (like html tags) using
the Range object.
I can do it using the selection object easy enough but would like to
convert to using a range object for performance.
Here is a the selection object code.

Selection.StartOf (6) ' Convert Bold tags
Selection.Find.Text = "<B>"
Selection.Find.Execute
Do While Selection.Find.Found
Selection.ExtendMode = True
Selection.Find.Text = "<P>" ' end of bold
Selection.Find.Execute
Selection.Font.Bold = True
Selection.MoveRight 1, 1
Selection.ExtendMode = False
Selection.Find.Text = "<B>"
Selection.Find.Execute
Loop

Any help much appreciated.

Thanks Peter
 
J

Jay Freedman

Hi Peter,

Well, I know nothing at all about VFP, but I'll guess that it doesn't
support named arguments in method calls and you have to pass arguments
by position. The .Execute method has 15 arguments, all of them
optional, and the Replace argument is the 11th one. So whatever syntax
VFP uses to represent omitted arguments, use it for the first 10 and
then pass the wdReplaceAll value (either pass an explicit value of 2
or fix your #DEFINE statement to make it 2 instead of 0).

I'm also not sure about the syntax
.Execute.Replace = wdReplaceAll
I don't think that's going to work.

--
Regards,
Jay Freedman
Microsoft Word MVP

Hi Jay/Greg/Helmut,
Many thanks for the help, this has set me on the right track,

I simply used the * wildcard in the end since I strip all the tags at the
end. Also the .Replacement.Text was not needed and in fact caused an error.

I also forgot to mention that this code will come from a Visual FoxPro app.
so I'm busy trying to convert.
So far so good but i've falling at the last hurdle when trying to adapt the
.execute bit and I've also got to rearrange the DO CASE so that i can pass
strTag each time.

Anyway I dunno if you are VFP gurus but I'd thought let you know how i'm
doing.

Here's how far I've come...

#DEFINE wdReplaceAll 0
Local oRg, strTag, strTag2
strTag=
strTag2=[D]
#DEFINE wdUnderlineSingle 1
oRg = oWord.ActiveDocument.Range
With oRg.Find
.MatchWildcards = .t.
.ClearFormatting
.Replacement.ClearFormatting
.Format = .f.
.Forward = .t.
.MatchCase = .f.
.Text = [<] + strTag + [>*<] + strTag2 + [>]
.Replace = wdReplaceAll
DO CASE strTag
Case strTag=
.Replacement.Font.Italic = .T.
.Execute.Replace = wdReplaceAll
Case strTag=
.Replacement.Font.Bold = .t.
.Execute && this bit blows up. How do I pass the VBA equivelant of
Replace:= wdReplaceAll ?
Case strTag=
.Replacement.Font.Underline = wdUnderlineSingle
.Execute.Replace = wdReplaceAll
OTHERWISE
&& do nothing
ENDCASE
EndWith


Jay Freedman said:
Hi Peter,

You're going about this completely the wrong way. Switch over to using a
wildcard search (http://word.mvps.org/faqs/general/UsingWildcards.htm) for
the entire phrase from the start tag all the way to the end tag, and then
you can use the wdReplaceAll parameter in the .Execute to process the
entire
document in one shot. This will be orders of magnitude faster than
crawling
through the document the way you're doing it now.

This sample macro shows a number of features: How to use a range object
for
Replace; how to use a subroutine with an argument to change its behavior;
how to use Select Case to do different actions based on the value of the
argument; and how to use a wildcard expression to match HTML tags (more on
this subject below the macro).

Private Sub ReplaceFormattingTags(strTag As String)
Dim oRg As Range
Set oRg = ActiveDocument.Range
With oRg.Find
.MatchWildcards = True
.ClearFormatting
.Replacement.ClearFormatting
.Format = False
.Forward = True
.MatchCase = False
.Text = "\<" & strTag & "\>([!\<\>]@)\</" & strTag & "\>"
.Replacement.Text = "\1"
Select Case strTag
Case "i", "I"
.Replacement.Font.Italic = True
.Execute Replace:=wdReplaceAll
Case "b", "B"
.Replacement.Font.Bold = True
.Execute Replace:=wdReplaceAll
Case "u", "U"
.Replacement.Font.Underline = wdUnderlineSingle
.Execute Replace:=wdReplaceAll
' add more cases for tags you want to handle
Case Else
' do nothing
End Select
End With
End Sub

Public Sub test()
ReplaceFormattingTags ("i")
ReplaceFormattingTags ("b")
End Sub

The wildcard expression in the macro is constructed like this:

Depending on the value of the argument strTag, the first portion "\<" &
strTag & "\> will match an opening tag like <i> or <I> (it will match
either
because of the .MatchCase = False setting). As explained in the Wildcards
article, the backslashes tell VBA to treat the < and > as actual
characters
to be matched, rather than their special wildcard meanings (start and end
of
words).

Similarly, the ending portion \</" & strTag & "\>" will match the
corresponding closing tag like </i> or </I>.

The portion ([!\<\>]@) will match any sequence of characters that does
*not*
contain any < or > character. The ( ) tell VBA that whatever is matched by
this portion will be given the alias \1 for use in the .Replacement.Text.
The effect of this is to remove the tags while simultaneously applying the
specified formatting to the text between the tags.

--
Regards,
Jay Freedman
Microsoft Word MVP
Hi,
I'm trying to write a macro to convert tags (like html tags) using
the Range object.
I can do it using the selection object easy enough but would like to
convert to using a range object for performance.
Here is a the selection object code.

Selection.StartOf (6) ' Convert Bold tags
Selection.Find.Text = "<B>"
Selection.Find.Execute
Do While Selection.Find.Found
Selection.ExtendMode = True
Selection.Find.Text = "<P>" ' end of bold
Selection.Find.Execute
Selection.Font.Bold = True
Selection.MoveRight 1, 1
Selection.ExtendMode = False
Selection.Find.Text = "<B>"
Selection.Find.Execute
Loop

Any help much appreciated.

Thanks Peter
 

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