Write Place
Write Place

Reputation: 3

How to exclude content found within quotation marks

I have the following function, but I do not want it to replace anything within quotation marks when I call it:

Function AutoReplace(source As String, typeText As String)
    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = Trim(source)
        .Replacement.Text = typeText
        .Forward = True
        .Wrap = wdFindContinue
    End With
    Selection.Find.Execute Replace:=wdReplaceAll
End Function

Upvotes: 0

Views: 135

Answers (1)

Cindy Meister
Cindy Meister

Reputation: 25663

Wildcard search can't handle this, unfortunately, so a code solution is required.

The difficulty with this is determining when the search term is within quotes. And of course the search term could occur multiple times within a set of quotes. I tried to think of all permutations, including whether the term occurs at the beginning / end of the document, but I can't guarantee I caught them all...

The trick to the approach I propose is to compare the location in the text of the found term, the previous opening quotes and, if those were found, whether the previous closing quotes follow or precede the opening quotes. If no opening quotes are found, the term is obviously not in quotes. If the closing quotes follow the opening quotes, the term is not in quotes. Otherwise, it's assumed the quotes are in pairs and the term is indeed within quotes.

The coding could be more elegant (fewer nested levels), but I'm not being paid for it, so I leave that up to anyone who wants to use it...

Sub FindTermNotInQuotes()
  Dim sTerm As String, sReplacement As String
  Dim sOpenQuote As String, sCloseQuote As String
  Dim rngSearch As word.Range, rngOpenQuote As word.Range
  Dim rngTerm As word.Range, rngCloseQuote As word.Range
  Dim bFound As Boolean, rngFound As word.Range

  sTerm = "can't"
  sReplacement = "cannot"
  sOpenQuote = Chr(147)
  sCloseQuote = Chr(148)
  Set rngSearch = ActiveDocument.content
  Set rngFound = ActiveDocument.Range(2)
  Do
    With rngSearch.Find
      'Keep previous location so that we can check
      'If searching the open quote is a previous one
      rngFound.Collapse wdCollapseStart
      .ClearFormatting
      .Text = sTerm
      .Forward = True
      bFound = .Execute
      If bFound Then
        Set rngOpenQuote = rngSearch.Duplicate
        rngOpenQuote.Start = ActiveDocument.content.Start
        With rngOpenQuote.Find
            .Text = sOpenQuote
            .Forward = False
            If .Execute Then
                If rngOpenQuote.Start < rngFound.Start Then
                    'This quote is in front of the previous "hit"
                    'So we need to check if there's a closing quote
                    Set rngCloseQuote = rngSearch.Duplicate
                    rngCloseQuote.Start = ActiveDocument.content.Start
                    With rngCloseQuote.Find
                        .Text = sCloseQuote
                        .Forward = False
                        If .Execute Then
                            'It's not in a quote
                            If rngCloseQuote.Start > rngOpenQuote.Start Then
                                'If close quote is before open quote
                                'then the term is still within quotes
                                rngSearch.Text = sReplacement
                            End If
                        End If
                    End With
                End If
            End If
        End With
      End If
      Set rngFound = rngSearch.Duplicate
      rngSearch.Collapse wdCollapseEnd
      rngSearch.End = ActiveDocument.content.End
    End With
  Loop While bFound
End Sub

Upvotes: 1

Related Questions