erros84
09-05-2013, 10:35 PM
Hi all, I have a weird response from VBA when I use rng.Find.Execute Replace:=wdReplaceOne.
Program/Platform: Word 2010 x64, Windows 7 x64
This is a snippet of code from a much larger project, but basically I want the process to replace ONLY the first search result in the range on each loop until done. In my full program, the .Replacement.Text is a much more clever result from another process, and multiple different find-replaces are done per loop on the same paragraph.
I've been told that it's better to use ranges than selections...and it's been nothing short of exhausting making this work. Ranges just don't behave the way I expect them to.
When I use wdReplaceAll in the first snippet, the range (the current paragraph) stays the same, and it does exactly what I expect. The range and the paragraph in the document reflect the changes of a standard replace all.
Sample Document:
et at ot et
Working code:
Sub CleanReplace()
Dim re2 As Object
Dim i As Integer
Dim Reference As Range
Dim myMatches, ResultString
Set re2 = CreateObject("vbscript.regexp")
re2.pattern = "(a|e)t"
re2.IgnoreCase = True
re2.Global = True
re2.MultiLine = False
Dim para As Paragraph
For Each para In ActiveDocument.Paragraphs
Dim CurrentStyle As Object
Set rng = para.Range
Dim FoundMatch
If rng <> "" Then
FoundMatch = re2.Test(rng.Text)
If FoundMatch = True Then
Set myMatches = re2.Execute(rng)
If myMatches.count >= 1 Then
'ResultString = myMatches(0).Value
'do replaces on array
For i = 0 To (myMatches.count - 1)
tempstring = myMatches(i).Value
rangeStart = Len(rng)
' Selection.Find.ClearFormatting
' Selection.Find.Replacement.ClearFormatting
With rng.Find
.Text = tempstring
.Replacement.Text = "est"
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True
End With
rng.Find.Execute Replace:=wdReplaceAll
MsgBox (rng.Text)
Next i
End If
End If
End If
Next para
End Sub
As expected, the message box appears with "est est ot est".
Unfortunately, when I use .wdReplaceOne (as in the second snippet) the document reflects the change of a replace one, BUT then the range contracts down, showing only the replacement text from that operation. At this point, I can no longer continue replacements in this paragraph because my range no longer contains the whole paragraph. Shouldn't the msgbox in the second code snippet show the result "est at ot et" instead of simply "est"?
I have a watch on the variable "rng", and it's driving me insane why a find/replace with wdReplaceOne corrupts the range and wd_ReplaceAll does not.
What am I misunderstanding?
Broken Code:
Sub CleanReplace()
Dim re2 As Object
Dim i As Integer
Dim Reference As Range
Dim myMatches, ResultString
Set re2 = CreateObject("vbscript.regexp")
re2.pattern = "(a|e)t"
re2.IgnoreCase = True
re2.Global = True
re2.MultiLine = False
Dim para As Paragraph
For Each para In ActiveDocument.Paragraphs
Dim CurrentStyle As Object
Set rng = para.Range
Dim FoundMatch
If rng <> "" Then
FoundMatch = re2.Test(rng.Text)
If FoundMatch = True Then
Set myMatches = re2.Execute(rng)
If myMatches.count >= 1 Then
'ResultString = myMatches(0).Value
'do replaces on array
For i = 0 To (myMatches.count - 1)
tempstring = myMatches(i).Value
rangeStart = Len(rng)
' Selection.Find.ClearFormatting
' Selection.Find.Replacement.ClearFormatting
With rng.Find
.Text = tempstring
.Replacement.Text = "est"
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True
End With
rng.Find.Execute Replace:=wdReplaceOne
MsgBox (rng.Text)
Next i
End If
End If
End If
Next para
End Sub
The messagebox appears with only "est", losing the rest of the paragraph.
Program/Platform: Word 2010 x64, Windows 7 x64
This is a snippet of code from a much larger project, but basically I want the process to replace ONLY the first search result in the range on each loop until done. In my full program, the .Replacement.Text is a much more clever result from another process, and multiple different find-replaces are done per loop on the same paragraph.
I've been told that it's better to use ranges than selections...and it's been nothing short of exhausting making this work. Ranges just don't behave the way I expect them to.
When I use wdReplaceAll in the first snippet, the range (the current paragraph) stays the same, and it does exactly what I expect. The range and the paragraph in the document reflect the changes of a standard replace all.
Sample Document:
et at ot et
Working code:
Sub CleanReplace()
Dim re2 As Object
Dim i As Integer
Dim Reference As Range
Dim myMatches, ResultString
Set re2 = CreateObject("vbscript.regexp")
re2.pattern = "(a|e)t"
re2.IgnoreCase = True
re2.Global = True
re2.MultiLine = False
Dim para As Paragraph
For Each para In ActiveDocument.Paragraphs
Dim CurrentStyle As Object
Set rng = para.Range
Dim FoundMatch
If rng <> "" Then
FoundMatch = re2.Test(rng.Text)
If FoundMatch = True Then
Set myMatches = re2.Execute(rng)
If myMatches.count >= 1 Then
'ResultString = myMatches(0).Value
'do replaces on array
For i = 0 To (myMatches.count - 1)
tempstring = myMatches(i).Value
rangeStart = Len(rng)
' Selection.Find.ClearFormatting
' Selection.Find.Replacement.ClearFormatting
With rng.Find
.Text = tempstring
.Replacement.Text = "est"
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True
End With
rng.Find.Execute Replace:=wdReplaceAll
MsgBox (rng.Text)
Next i
End If
End If
End If
Next para
End Sub
As expected, the message box appears with "est est ot est".
Unfortunately, when I use .wdReplaceOne (as in the second snippet) the document reflects the change of a replace one, BUT then the range contracts down, showing only the replacement text from that operation. At this point, I can no longer continue replacements in this paragraph because my range no longer contains the whole paragraph. Shouldn't the msgbox in the second code snippet show the result "est at ot et" instead of simply "est"?
I have a watch on the variable "rng", and it's driving me insane why a find/replace with wdReplaceOne corrupts the range and wd_ReplaceAll does not.
What am I misunderstanding?
Broken Code:
Sub CleanReplace()
Dim re2 As Object
Dim i As Integer
Dim Reference As Range
Dim myMatches, ResultString
Set re2 = CreateObject("vbscript.regexp")
re2.pattern = "(a|e)t"
re2.IgnoreCase = True
re2.Global = True
re2.MultiLine = False
Dim para As Paragraph
For Each para In ActiveDocument.Paragraphs
Dim CurrentStyle As Object
Set rng = para.Range
Dim FoundMatch
If rng <> "" Then
FoundMatch = re2.Test(rng.Text)
If FoundMatch = True Then
Set myMatches = re2.Execute(rng)
If myMatches.count >= 1 Then
'ResultString = myMatches(0).Value
'do replaces on array
For i = 0 To (myMatches.count - 1)
tempstring = myMatches(i).Value
rangeStart = Len(rng)
' Selection.Find.ClearFormatting
' Selection.Find.Replacement.ClearFormatting
With rng.Find
.Text = tempstring
.Replacement.Text = "est"
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True
End With
rng.Find.Execute Replace:=wdReplaceOne
MsgBox (rng.Text)
Next i
End If
End If
End If
Next para
End Sub
The messagebox appears with only "est", losing the rest of the paragraph.