Some actions can be readily applied to multiple document elements all of which might be useful, so this workhorse function inserts or removes double quotes around any given range.
Thanks for your interest
This content is part of a paid plan.
Toggle Quotes around Range
It’s natural to apply double quotes to a paragraph, sentence, or a specific selected range. It’s messy to copy and change a function with only minor changes, or worse, to recreate everything from scratch for each use case.
Why not create a tool we can use for any of them?
In this function, we'll toggle double quotes around a given range rather than a specific document element like a paragraph or sentence.
It would be natural to go ahead and extend it to also work with parentheses or single quotes since toggling those punctuation marks around a range would share almost identical logic. However, we’ll stick with double quotes for this article to keep the commentary more targeted but see the more general version if you prefer to start there since the articles overlap.
Other functions
This function uses a little helper function TrimRange to trim any blank space off both ends of the initial range. Also, the left and right double quotes are different characters in Word for Mac and Windows, so we use another pair of simple functions for them.
What’s the plan?
Digging into the details, how do we detect and then add or remove quotes around a given range?
- Trim any spaces or paragraph marks off either side of the range (simplifies any later tests).
- Check whether any double quotes are just outside the range on either side. If so, include them in the range.
- Test whether double quotes exist on both sides. If so, delete them. If not, add them to both sides or add the missing double quote.
The initial step of trimming the blank space from either side sets up a clear starting condition for the rest of the function. It’s easier to work with a range when we know a regular character is present on either side since there are fewer variations to consider.
What about straight double quotes?
For simplicity, we will not consider straight double quotes as character Chr(34) since I almost never use them in the context of writing a novel or novel notes. If you prefer using straight quotes in Word, it’s not difficult to change the final function to accommodate them, or the generalized function will handle them alone.
What if there are double quotes just outside the given range?
Ahhhh, yeah, little questions like this are inevitable.
This is a bit of a judgement call. On the one hand, should we work outside the given range at all?
A user might argue, “Hey, what are you doing? I gave you that range to work on! What are you doing grabbing something outside it?”
I tend to err on the other side of making a macro or function more convenient to use, so I think the better option is to check for and include any double quotes just outside the given range.
Why?
I think it would be weird to insert a new double quote next to another double quote if it’s just a character outside the given range. Checking only requires a few extra steps in the macro, and it’s easier to manipulate the text if it’s inside the range.
Just be clear what the macro or function does and how it works in the description (add a few comment lines at the top of the macro).
Create the function skeleton
Start by creating the function skeleton.
What parameters to use?
We accept the target range rTarget to trim. This variable is not changed during the function (normal range variables could be changed; see this article on ranges for a brief explanation).
Return type
We return the resulting modified range which we determine by the end of the finished function.
What if we're given an invalid range?
First, what if a macro provides our function an invalid range?
This is usually indicated by a Nothing value for the range or any object variable (see previous article on ranges for more explanation). We add an initial validation check and quit the function if the range isn’t valid.
The “Is” keyword compares objects in VBA similar to an equals = sign for regular values, and we use “Is Nothing” because Nothing is not an actual value like a 0 or -1.
Return Nothing for invalid range
If we detect and invalid given range, we first Set the return value (via the function name) to Nothing to indicate an invalid result for the function.
Exit Function
Then we exit the function immediately.
Putting it together, we have:
After this conditional statement, we at least know the target range is valid.
Create duplicate working range
We want to avoid unintended changes to the rTarget range, so we immediately create a duplicate of it which we call r just to keep the name short.
Now our working range r is independent of the given range rTarget, so a user won’t be unpleasantly surprised by the target range being changed during the function.
We needed to declare the range explicitly using a Dim command since we're passing it to a function below. VBA is picky about knowing for sure what the argument type is.
Trim the blank space
Using a previous function, we quickly trim any blank space off either side of the working range.
We reassign the result back to the working range r. This task is common enough that we created a separate function.
Recall we use "Set" because a range is an object containing more data just a plain value.
Check whether double quotes exist already
We start by checking whether any double quotes exist just outside the range and include them in the range.
Including nearby double quotes just outside the working range is a preference, and some could argue it logically shouldn’t be done that way since the user “specifically” provided the target range. I think including any nearby double quotes makes the function a little more general and convenient to use, but omit these steps if you don’t like them. It won’t affect the rest of the function steps.
Why bother?
Just for convenience and clarity with the following function steps.
After we include any preceding or trailing double quotes outside the working range, we know any existing quotes should be at none, one, or both sides of the working range; so we can make upcoming decisions more easily. See also the gotcha for duplicated double quotes, but we ignore this infrequent possibility here.
Get previous and next characters
We need the previous and next characters before and after the working range.
These methods Previous and Next both return a range outside our working range r corresponding to the previous or next document Unit specified. We indicate wdCharacter here. We then had to access the Text property to get the plain text character.
Assigning the function result to a variable and accessing the Text property both required parentheses to be used around the Unit argument.
If either character just outside the working range is a double quote, we'll extend the range below to include it.
Include left double quote
For the first character of the range, we check whether it is a left double quote. If so, we extend the Start position of the range backward over the character.
The default move Unit is by character, so we don’t need to specify it. The Count option assigned as -1 tells the command to move the Start position backward one unit in the document.
Since we only have one brief command here, we can shorten the conditional statement.
It makes the steps a little harder to read, but it helps keep our function cleaner and smaller. I generally prefer this presentation if the steps are clear enough.
The double quote characters use two previous functions LeftDQ and RightDQ (below), respectively, because the character values depend on whether you’re using Word for Mac or Windows.
Include right double quote
For the rightmost character of the range, we check whether it is a right double quote. If so, we extend the End position of the range forward over the character.
The default move Unit is again by character, and the default Count is by 1 unit, so we don’t need to specify either of them.
Again, we can shorten the conditional statement if we wish.
See this previous article if you would like to review conditional statements.
Check for double quotes
Given the current first or last characters of the range, we have three cases:
- Double quotes on both sides → delete both of them
- Double quote only on one side → add the missing double quote
- No quotes on either side → add double quotes on both sides
Let’s translate these into VBA.
Get first and last characters
For all cases above, we need the first and last characters of the range to do our checking.
These commands use the Characters collection of the range. The First or Last references return ranges corresponding to the respective character positions. We finally refer to the Text property to get the actual plain text character which we then store (using the equals = assignments) in the respective variable, FirstCharacter or LastCharacter.
Double quotes on both sides
Similar to the above conditions for the previous and next characters, we check whether the first or last characters are a left or right double quote, respectively.
In this case, both sides must be double quotes before we delete them, so we use an And operator between the conditions.
Note the “FirstCharacter = SomeCharacter” notation in this conditional statement is actually a condition not an assignment to a variable like above. It is an unfortunate ambiguity in VBA, but we don’t need to think much about it because VBA is able to determine the proper usage by context.
Delete double quotes
To delete the double quotes, we again refer to the ranges returned by the respective First and Last references from the Characters collection. We then refer to the Delete method to delete the two single-character ranges.
These commands remove them from the document not just the range.
Cannot delete the Text property
Note we are not deleting the “Text” of the range because Text is a property.
This doesn’t work because the Text property of a range has no Delete method. It just represents the string of plain text characters spanned by the range in the document.
Double quotes on one or no sides
There are a few ways to detect and change double quotes on either or both sides of the range. Let’s briefly explore an alternative as practice.
Longer variation
The logic to detect the presence of double quotes on either or both sides can stretch out a little and make the function messier than I prefer.
Ughhh.
We use a Not operator to reverse the True-False (Boolean) value of one of the character comparisons. We could’ve used a not equals <> comparison instead which works fine with strings (two strings being "equal" requires an exact match including any upper or lower case characters). It’s just a preference, but I thought the Not looked better here.
On the plus side, it’s clear and … it works, I suppose, but I don’t like it. It’s just too long for me, so I won’t break it down with any more commentary.
Shorter variation
I went with a shorter solution.
I felt like this shorter version was cleaner, but your mileage and preferences may vary.
Left double quote
To add the double quotes to the left side of the range in this version, we check and add it to the side that doesn’t already have one.
Recall the <> symbol is “not equal,” so we basically add the left double quote if it doesn’t already exist on the starting (left) side.
InsertBefore inserts the given plain text in the Text option on the left side of the range, and the range automatically extends to include the new text.
Right double quote
Similarly, we can check whether the last character of the range is a right double quote and add one if not.
InsertAfter inserts the given plain Text in the option on the right side of the range. The range automatically extends to include the new text.
Independent checks
Notice these conditional statements are not connected. The function checks each condition separately since we don’t know which double quote is missing or if both are needed.
Again, these conditional statements are relatively concise, so we can shorten them if you prefer.
Return the modified range
We finally return the working range with any modifications in case the user wants to do anything with it.
In many of my own use cases, I don’t care about the returned range, but it’s good to be more general with a function if it makes sense. It’s also more work to modify the function later if we decide we need the resulting range in some other macro because we would need to work through the logic again perhaps months after finishing it.
Gotchas
Where could all this go wrong?
This function does modify the document, so as a general rule, we should be careful before assuming the function is “done.” Still, it is relatively safe since we’re only adding or removing specific individual characters.
What if an empty range is passed to the function?
We’re assuming this is a valid empty range since we already accounted for an invalid range in the function.
This function just inserts the double quotes around the empty range as normal. The various steps handle it without a problem even when the first or last characters happen to refer to the same character position in the document.
Duplicated double quotes?
We don’t check for duplicated quotes at either side of the range.
This case is unusual enough that it’s a reasonable compromise to not bloat the function by checking and correcting unusual special cases.
Final Function
Putting everything together, the function is:
Another common use case is with parentheses. You could copy this function and change left double quote LeftDQ to open parenthesis “(“ and right double quote RightDQ to close parenthesis “)”, but that would half defeat the point of implementing the function for a range. See the more general version that works with any left and right characters (there is significant overlap in the commentary, but both articles stand on their own).