1
votes

I have a Find and Replace macro that adds a space between the end of one sentence and the beginning of another when missing. This sometimes happens when I move sentences around in word.

I notice that if the cursor is to either side of the punctuation mark, the macro can’t see the Find pattern and doesn’t fix it. I assume it’s because Find and Replace starts searching from the cursor position. Is there a way to tweak the code so it finds them too?

I know I could just tell the macro to start from the beginning, but I would much rather it left the cursor in its current position, especially if I run it near the end of a long document.

Sub AddOneSpaceBetweenSentences()
' AddOneSpaceBetweenSentences Macro
'
 With Selection.Find
 .Forward = True
 .Text = "(?)([.\?\!])([A-Z])"
 .ClearFormatting
 .Replacement.Text = "\1\2 \3" 'there is a space between \2 and \3
 .MatchWildcards = True
 .Wrap = wdFindContinue
 .Execute Replace:=wdReplaceAll

End With

End Sub
3

3 Answers

2
votes

The most reliable way is to use Range objects instead of Selection. When working with a Range the selection in the document doesn't change.

  Sub AddOneSpaceBetweenSentences()
    ' AddOneSpaceBetweenSentences Macro
    '
     Dim rng as Word.Range

     Set rng = ActiveDocument.Content
     With rng.Find
       .Forward = True
       .Text = "(?)([.\?\!])([A-Z])"
       .ClearFormatting
       .Replacement.Text = "\1\2 \3" 'there is a space between \2 and \3
       .MatchWildcards = True
       .Wrap = wdFindContinue
       .Execute Replace:=wdReplaceAll
    End With

  End Sub
2
votes

Better still:

Sub AddOneSpaceBetweenSentences()
Application.ScreenUpdating = False
With ActiveDocument.Range.Find
  .ClearFormatting
  .Replacement.ClearFormatting
  .Forward = True
  .Format = False
  .MatchWildcards = True
  .Wrap = wdFindContinue
  .Text = "([.\?\!])([A-Z])"
  .Replacement.Text = "\1 \2"
  .Execute Replace:=wdReplaceAll
End With
Application.ScreenUpdating = True
End Sub
1
votes

Is it really necessary to have a character before the end signs . or ? or !
If not, just replace "([.\?\!])([A-Z])" by "\1 \2"


Simple attempt: Just extend the selection by 2 characters to the left.

If cursor is on the first two characters of the documents, you would get an error. To prevent that and to prevent counting of characters, I just used Selection.Start > 10

If Selection.Start > 10 Then
    Selection.Previous(Unit:=wdCharacter, Count:=2).Select
End If

... or do it a little more complicated:

Sub AddOneSpaceBetweenSentences()
    Dim SearchText As String
    Dim ReplaceText As String

    ' extend selection by 1 character
    If Selection.Start > 0 Then
        Selection.Previous(Unit:=wdCharacter, Count:=1).Select
    End If
    Selection.Collapse

    ' if selection begins directly before end of sentence (.?!)
    ' adapt search & replace pattern
    If InStr(1, ".?!", Selection.Characters(1), vbBinaryCompare) > 0 Then
        SearchText = "([.\?\!])([A-Z])"
        ReplaceText = "\1 \2"
    Else
        SearchText = "(?)([.\?\!])([A-Z])"
        ReplaceText = "\1\2 \3"
    End If

    With Selection.Find
        .Forward = True
        .text = SearchText
        .ClearFormatting
        .Replacement.text = ReplaceText
        .MatchWildcards = True
        .Wrap = wdFindContinue
        .Execute Replace:=wdReplaceAll
    End With
End Sub