Help with looping a macro

F

Fred Goldman

I'm trying to loop this macro until it doesn't find anymore occurences. I
would very much appreciate any help.

Here's the macro:

Selection.Find.ClearFormatting
With Selection.Find
.Text = ",^$"
.Forward = True
.Wrap = wdFindContinue
End With
Selection.Find.Execute
Selection.MoveLeft Unit:=wdCharacter, Count:=1
Selection.MoveRight Unit:=wdCharacter, Count:=1
Selection.TypeBackspace
Selection.TypeText Text:=""""
End Sub
 
G

Greg Maxey

Fred,

Not sure I follow. Do you want to replace the literal text ,^$ with the
literal text "^$ ?

Assuming yes. Test below is a modification of your code. Test2 is a
replace all method.


Sub Test()

With Selection.Find
.ClearFormatting
.Find
.Text = ",^^$"
.Forward = True
.Wrap = wdFindContinue
Do While .Execute
With Selection
.MoveLeft Unit:=wdCharacter, Count:=1
.MoveRight Unit:=wdCharacter, Count:=1
.TypeBackspace
.TypeText Text:=""""
End With
Loop
End With
End Sub


Sub Test2()
Dim myRng As Word.Range
Set myRng = ActiveDocument.Content
With myRng.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = ",(^^$)"
.MatchWildcards = True
.Replacement.Text = """\1"
.Execute Replace:=wdReplaceAll
End With

End Sub
 
F

Fred Goldman

Greg,

Thanks a lot! The first one worked like a charm! What I was actually trying
to do was find every occurence of a comma and any letter right afterwords
(I'm working in Hebrew so it's right to left) and replace the comma with a ".

For example (in English) t,g or g,r I would like to replace with t"g g"r.

You can't put a any character sign in the replace field so I had the macro
replace it manually.

Will Do While .Execute ... Loop work in general when I want to loop any find
macro? Is there any general rule even a beginner can figure out regarding
looping macros (I mean without conditions)?

Thank you!
 
G

Greg Maxey

Fred

Based on your update, you really don't need a macro at all. You can use
Edit>Replace>More>Use Wildcards.

Type ,(?) in the find what field
Type "\1 in the replace with field
Click replace all (Of course always have a backup :) )

For more on Find and Replace, see:
http://www.gmayor.com/replace_using_wildcards.htm

For your follow-on question you will have to accept that while I am not a
beginnner neither am I a Titan.

I have monkeyed around with Find and Replace code to the point of sweeping
up clumps of hair off the floor in some of my more "quiet moments." Here is
the fruit of my madness:

'In each example, collapse the range to the end of the found term each time.
'In each example, Wrap is set to wdFindStop
'This prevents a circular loop
Sub ScratchMacro1()
Dim rngstory As Word.Range
Set rngstory = ActiveDocument.Range
With rngstory.Find
.ClearFormatting
.Replacement.ClearFormatting
.MatchWildcards = False
.MatchWholeWord = True
.Wrap = wdFindStop
.Text = "Apples"
'Don't bother with .Replacement method just redefine the found range
While .Execute
rngstory.Text = .Text
rngstory.Font.Bold = True
rngstory.Collapse Direction:=wdCollapseEnd
ActiveDocument.Indexes.MarkEntry Range:=rngstory, Entry:=.Text
Wend
End With
End Sub
Sub ScratchMacro2()
Dim rngstory As Word.Range
Set rngstory = ActiveDocument.Range
With rngstory.Find
.ClearFormatting
.Replacement.ClearFormatting
.MatchWildcards = False
.MatchWholeWord = True
.Wrap = wdFindStop
.Text = "Apples"
.Replacement.Text = .Text
.Replacement.Font.Bold = True
'Loop while found and perform if found (not very clean)
Do
.Execute Replace:=wdReplaceOne
rngstory.Collapse Direction:=wdCollapseEnd
If .Found Then
ActiveDocument.Indexes.MarkEntry _
Range:=rngstory, Entry:=.Text
End If
Loop While .Found
End With
End Sub
Sub ScratchMacro3()
Dim rngstory As Word.Range
Set rngstory = ActiveDocument.Range
With rngstory.Find
.ClearFormatting
.Replacement.ClearFormatting
.MatchWildcards = False
.MatchWholeWord = True
.Wrap = wdFindStop
.Text = "Apples"
.Replacement.Text = .Text
.Replacement.Font.Bold = True
'Find once then enter the loop and perform while found
.Execute Replace:=wdReplaceOne
Do While .Found
rngstory.Collapse Direction:=wdCollapseEnd
ActiveDocument.Indexes.MarkEntry _
Range:=rngstory, Entry:=.Text
.Execute Replace:=wdReplaceOne
Loop
End With
End Sub
Sub DemonstrationMacro()
Dim rngstory As Word.Range

'ReplaceAll. Word finds all intances of the .find.text
'and replaces with the replacement text globally as determined
'by .Wrap in fell swoop.
Set rngstory = ActiveDocument.Range
With rngstory.Find
.ClearFormatting
.Replacement.ClearFormatting
'.Wrap = wdFindContinue or wdFindStop doesn't matter
.MatchWholeWord = True
.Wrap = wdFindContinue
.Text = "apples"
.Replacement.Text = "peaches"
.Execute Replace:=wdReplaceAll
End With

'ReplaceOne. In this example .Execute finds and "replaces" the first
'instance of the .find.text. Then enters a Do Loop. The found range
'bounds the found text. The found text and .Find.Text are different.
Set rngstory = ActiveDocument.Range
With rngstory.Find
.ClearFormatting
.Replacement.ClearFormatting
.MatchWholeWord = True
'.Wrap = wdFindStop 'If set routine only finds the first
'instance of .Find.Text
.Wrap = wdFindContinue
.Text = "peaches"
.Replacement.Text = "pears"
.Execute Replace:=wdReplaceOne
Do While .Found
rngstory.Select
'As you can see from the selection the .Find.Text "peaches"
'is no longer in the found range. The next .Execute will
'search from the start of the found range forward looking for
'the next intance of .Find.Text. If wdFindStop is set,
'.Execute searches only the found range and will return False.
.Execute Replace:=wdReplaceOne
Loop
End With
'ReplaceOne. In this example .Execute finds and "alters" the first
'instance of the .find.text. Then enters a Do Loop. The text in the
'found range is the same as the .Find.Text. You must use both
'.Wrap and a line of code to collapse the found range to prevent a
'circular loop
Set rngstory = ActiveDocument.Range
With rngstory.Find
.ClearFormatting
.Replacement.ClearFormatting
.MatchWholeWord = True
.Wrap = wdFindStop 'Prevents a circular loop
'.Wrap = wdFindContinue 'Will cause a circular loop
.Text = "pears"
.Replacement.Text = "pears"
.Replacement.Font.Bold = True
.Execute Replace:=wdReplaceOne
Do While .Found
rngstory.Select
'As you can see from the selection the .Find.Text "pears"
'is in the found range. Without additional code, the
'next .Execute searches from the start of the found range forward.
'The .Find.Text is immediately found and a circular loop is created.
rngstory.Collapse Direction:=wdCollapseEnd
'Collapsing the found range moves the next .Execute starting point
'past the point causing the cicular loop. The .Execute will search
'the range of text from the collapse point to the end of the
'document determined by .Wrap = wdFindStop
rngstory.Select
.Execute Replace:=wdReplaceOne
'It should be clear that since the .Find.Text is only altered and
'"not changed" using .Wrap = wdFindContinue would also result in
'a cicular loop.
Loop
End With

'The next few examples don't use the Replace option at all. Instead
'the found range is processed directly with each .Execute. .Execute
'without differs 'from .Execute Replace in that the following search
'is perfromed from the end of the previous found range

Set rngstory = ActiveDocument.Range
With rngstory.Find
.ClearFormatting
.Replacement.ClearFormatting
.MatchWholeWord = True
'.Wrap = wdFindContinue 'Causes circular loop will occur because the
'.Find.Text is altered but not changed
.Wrap = wdFindStop
.Text = "pears"
While .Execute
rngstory.Font.Bold = False
rngstory.Select
'The next .Execute will automatically collapse the search range
'to the end of the found range. It just does :)
Wend
End With

'Here the .Find.Text is changed.
Set rngstory = ActiveDocument.Range
With rngstory.Find
.ClearFormatting
'Wrap can be either
'.Wrap = wdFindStop
'.Wrap = wdFindContinue
.Replacement.ClearFormatting
.MatchWholeWord = True
.Wrap = wdFindContinue
.Text = "pears"
While .Execute
rngstory.Text = "apples"
Wend
End With
End Sub
 
F

Fred Goldman

Thank you very much for your tips. The reason I can't use wildcards is
because I don't want to change commas to " where there is a space afterwards
for example: the little red riding hood, wen,t to lunc,h. Iwould like the
wen,t and lunch ti change to wen"t and lunc"h, but not hood, to change to
hood".
 
H

Helmut Weber

Hi Fred,

maybe the following is sufficient:

Sub Test0023()
Dim oRng As Range
Set oRng = ActiveDocument.Range
ResetSearch
With oRng.Find
.Text = "(,)([a-zA-Z])"
.Replacement.Text = Chr$(34) & "\2"
.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
.Execute
End With
End Sub

Means: a comma followed by any of the letters in square brackets
is being replaced by a " plus that letter.

For left to right writing.

It's kind of hard, to check here, what modifications,
if any, have to made for from right from left writing.

HTH

--
Greetings from Bavaria, Germany

Helmut Weber, MVP WordVBA

Win XP, Office 2003
"red.sys" & Chr$(64) & "t-online.de"
 
G

Greg

Fred,

Wildcard searches are very powerful. Try find: ,([! ])
Replace "\1



That means a commma and any character but a space. Solves the problem
in your example ;-)
 
H

Helmut Weber

Hi Submariner,
Try find: ,([! ]) Replace "\1

very tempting. Very probably best, with some luck. ;-)

How about 10,000.67?

Of course, without previous knowledge about the data,
one might suggest a most often working, fast and simple method,
or a slower and more complicated method,
which won't work always either.

Same as with sorting. You never know the fastest method, unless
You analyze the data before and the resources You've got (stack),
which takes some time, too.

Have a nice day!

--
Greetings from Bavaria, Germany

Helmut Weber, MVP WordVBA

Win XP, Office 2003
"red.sys" & Chr$(64) & "t-online.de"
 

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