To ensure that concordance searches in translation memories work properly and to increase fuzzy matches, many translators systematically replace curly apostrophes and quotation marks with straight ones before importing a document into their CAT tool, then revert them back to the curly variety before delivering the final document to the client.
Until recently, I used a very simple find/replace macro to achieve this, but then I realized that the macro didn’t replace apostrophes and quotation marks situated. I searched online and found a solution that works not only in the main document but also in footnotes and text boxes. Thanks to Doug Robbins and Greg Maxey, whose work I drew on to create one of the macros below.
Copy the following code into a single module in your normal.dotm template, then run the ReplaceQuotes macro before importing your document into your CAT tool and the ReinstateQuotes macro after you have exported from your CAT tool to Word.
I’ve included extensive comments so that you can understand what each line is doing and adapt it as necessary.
Sub ReplaceQuotes() ‘ Replace curly quotation marks and apostrophes with straight ones.
Options.AutoFormatAsYouTypeReplaceQuotes = False ‘ Sets autoformat option not to replace curly quotes with straight ones. This is reset in the final like of the QuotesReplacementBothWays macro.
Sub ReinstateQuotes() ‘ Replace straight quotation marks and apostrophes with curly ones.
Options.AutoFormatAsYouTypeReplaceQuotes = True ‘ Sets autoformat option to replace curly quotes with straight ones, in case the user has manually set the option to false before running the macro.
pFindTxtFromOtherMacro = “‘”
pReplaceTxtFromOtherMacro = “‘”
pFindTxtFromOtherMacro = “””” ‘ Find all quotation marks (smart or curly). Four quotation marks are needed because the ” symbol has a special meaning that must be cancelled.
pReplaceTxtFromOtherMacro = “””” ‘ Replaces with smart or curly, depending on whether ReplaceQuotes or ReinstateQuotes was run.
‘ Remove the apostrophes from the start of each line in this section to replace French guillemets with English-style straight quotation marks.
‘ pFindTxtFromOtherMacro = “« ” ‘ Find all opening guillemets followed by a space (incl. non-breaking spaces).
‘ pFindTxtFromOtherMacro = “«” ‘ Find remaining opening guillemets with no space after.
‘ pFindTxtFromOtherMacro = ” »” ‘ Find all closing guillemets preceded by a space (incl. non-breaking spaces).
‘ pFindTxtFromOtherMacro = “»” ‘ Find remaining closing guillemets with no space before.
pFindTxtFromOtherMacro = “” ‘ Makes the variable empty again
pReplaceTxtFromOtherMacro = “” ‘ Makes the variable empty again
Options.AutoFormatAsYouTypeReplaceQuotes = True ‘ Reverts to Word’s default setting. Change this to “False” if you prefer Word not to replace straight quotes with curly ones as you type.
Public Sub FindReplaceAnywhere()
‘Performs a find/replace on all parts of a text, including footnotes, text boxes, etc.
‘Found on various webpages, but seems to have been originally created by Doug Robbins and Greg Maxey (https://wordmvp.com/FAQs/Customization/ReplaceAnywhere.htm).
‘Adapted so that it can be run with the find and replace strings pre-defined by other macros.
Dim rngStory As Word.Range
Dim pFindTxt As String
Dim pReplaceTxt As String
Dim lngJunk As Long
Dim oShp As Shape
If pFindTxtFromOtherMacro = “” Then
‘ This macro can be used on its own, in which case the user is asked what Word should find.
pFindTxt = InputBox(“Enter the text that you want to find.” _
If pFindTxt = “” Then
MsgBox “Cancelled by User”
pFindTxt = pFindTxtFromOtherMacro
If pReplaceTxtFromOtherMacro = “” Then
‘ This macro can be used on its own, in which case the user is asked what Word should replace the found string with.
pReplaceTxt = InputBox(“Enter the replacement.”, “REPLACE”)
If pReplaceTxt = “” Then
If MsgBox(“Do you just want to delete the found text?”, _
vbYesNoCancel) = vbNo Then
ElseIf vbCancel Then
MsgBox “Cancelled by User.”
pReplaceTxt = pReplaceTxtFromOtherMacro
lngJunk = ActiveDocument.Sections(1).Headers(1).Range.StoryType ‘Fix the skipped blank Header/Footer problem
For Each rngStory In ActiveDocument.StoryRanges ‘Iterate through all story types in the current document
SearchAndReplaceInStory rngStory, pFindTxt, pReplaceTxt
On Error Resume Next
Select Case rngStory.StoryType
Case 6, 7, 8, 9, 10, 11
If rngStory.ShapeRange.Count > 0 Then
For Each oShp In rngStory.ShapeRange
If oShp.TextFrame.HasText Then
SearchAndReplaceInStory oShp.TextFrame.TextRange, _
On Error GoTo 0
Set rngStory = rngStory.NextStoryRange ‘Get next linked story (if any)
Loop Until rngStory Is Nothing ‘ Loops back to the “Do”
Next ‘ Loops back to “For Each rngStory”
Public Sub SearchAndReplaceInStory(ByVal rngStory As Word.Range, _
ByVal strSearch As String, ByVal strReplace As String)
.Text = strSearch
.Replacement.Text = strReplace
.Wrap = wdFindContinue