Heading

This is some text inside of a div block.
This is some text inside of a div block.
This is some text inside of a div block.
min read

Delete current sentence allowing for dialog

Word • Macros • Editing
Peter Ronhovde
35
min read

As writers, we need our editing macros to work as smoothly and intuitively as possible. If our macro does not properly handle punctuation, we may as well just edit manually like they did in the stone ages. Toward that goal, we improve a previous delete sentence macro to intuitively handle dialog or parentheses.

Thanks for your interest

This content is part of a paid plan.

Improved delete sentence macro

What if we took a nice Word macro for deleting sentences and betterified it!

Writers work with dialog a lot, so it's annoying if our little helper macros work against us by deleting necessary punctuation. Our macros should work as smoothly and intuitively as possible with our writing and editing process … which means the previous macro needs to be a little smarter when working with or near punctuation.

More techy territory ahead

If you're following along with our articles in sequence, this macro uses more concepts at the same time than the earlier ones. It’s not much if you’re already a programmer, but for everyone else that wants to speedify their editing game, rest assured. I take a lot of time to explain the details.

Stick with me. I think you'll like the result.

How can we handle dialog naturally?

Punctuation is a specific document element we can check inside the macro and make decisions based on what we find. The details get a little involved, but the idea is simple. I’m a writer, and I’d like my sentence manipulation macros to handle dialog without deleting double quotes unnecessarily.

It seems like a small task on the surface. Couldn't we just use the macro and then manually tweak the result? Yeah, but that half defeats the point of creating the macro. Plus, the little niceties add up (or lack thereof hinders) when you’re in the flow. I will refer to double quotes or dialog as we move forward, but the resulting macro can be almost trivially modified to work with parentheses also.

What does “intuitively” mean for dialog?

If the dialog amounts to only one sentence, then delete everything as normal along with the quotes.

Example of deleting a single dialog sentence
Example of deleting a single dialog sentence (removes the double quotes)

But if more than one sentence is inside double quotes, delete the sentence but not the quotes.

Example of deleting a sentence within dialog
Example of deleting a sentence within dialog (leaves the double quote)

Simple delete sentence macro

For those that haven’t seen it, the previous simpler Delete current sentence macro was:

Sub DeleteSentence()
' Delete the current sentence or any partially selected sentences
Selection.Expand Unit:=wdSentence
Selection.Delete
End Sub

The macro only consists of two lines which is wonderful considering how useful it is for a writer, but it makes no allowance for dialog.

Selection versus Range caveat

We use the Selection object in many articles because it an easier approach for beginners with fewer topics to introduce up front; however, I am not recommending experienced macro users use the Selection object for anything beyond a few simple steps. Overuse of the Selection can make your screen “flicker” in more complicated macros because any changes are immediately displayed on the screen.

Declare a Range variable for the sentence

Toward that end, it's a simple upgrade to use a Range variable in this macro instead of manipulating the Selection directly. Technically, we do not have to declare the Range variable in standard VBA, just assign a Range object to it; but as the macros get more complex, we should be more careful and explicit with our intentions.

Dim rSentence As Range

Dim is the main way we "declare" a variable in VBA. The "As Range" tells VBA what type of variable we want.

Variable naming convention

I like to pick descriptive variable names with a reasonable length. I apply a few basic naming patterns to help me remember what the variables are and do, but VBA does not care as long as its naming restrictions are followed. In this variable, the first letter "r" indicates a Range variable. The fact that the first letter is lower case means it probably changes in the macro, but I am not strict about this detail for presentation purposes. Then I capitalize each successive Word. The result is a variation of a common convention called "camel case." People use different conventions, so pick what looks good to you and helps you remember what the variable does at a glance.

Variable name restrictions

VBA variable names cannot be a VBA keyword like Dim or Else. They also cannot include punctuation other than an underscore _, any special characters like @, nor spaces. In VBA, variable names are not case sensitive, so firstcharacter and FirstCharacter are the same variable. In fact, the VBA editor will automatically change the capitalization of later uses of the variable to be consistent with how it's first used or declared.

Why declare variables?

Letting VBA handle the variable type for us is definitely convenient, but it's a double-edged sword. Actually, a better analogy might be a trap hidden by the snow. If you later type the variable name and make a spelling error, VBA just thinks you're creating another variable. After you spend an hour or more tracking down a stupid spelling error in a variable name, you'll probably get over the aggravation of taking the time to declare variables. If you want to force yourself to do so, add Option Explicit, at the top of the project file.

If you declare a specific variable type, VBA will also help you with suggestions as you type which is nice at times.

If you prefer to let VBA always handle variable types, one suggestion I read somewhere is to type the variable name in all lowercase on purpose. If the VBA editor does not automatically correct the name based on the previous capitalization for that variable, it was typed incorrectly. It's an interesting compromise.

Advantage of Range variables

Changes to the Selection are immediately displayed on the screen (although a work around exists to temporarily disable screen updates), so the advantage of using a Range variable is all the individual range manipulations are invisible to the user until the end when we finally delete the target sentence. Only actions that directly change document content are seen by the user.

Distinction between a Range and the Selection

The Selection (see our brief review) encompasses VBAs representation of the insertion point or literal selection we see in the document. At a very basic level, it has Start and End positions in the document, but it also includes additional properties and methods for VBA to track and manipulate it.

Range variables (see our introduction to Ranges for more details) are like invisible, independent selections in the document. They are similar to the Selection object. Both object types have Start and End positions as well as similar move commands and other actions (methods) and data (properties). The Selection is more specialized with additional data and features, and only one can exist in each document. We can declare as many Range variables as we want to accomplish the necessary macro logic.

Set the range variable

We want the working range rSentence to initially be the same as the Selection.

' Set a working range variable to the initial Selection range
Set rSentence = Selection.Range

For VBA "objects" we need to use Set in addition to the equals = sign since they contain more information than just a value like a number or string of plain text. Until we Set the range to some valid document content, it literally refers to Nothing, so it cannot be used to do anything in the document.

Since the Selection is "more" than just a Range, we need to tell the Set command to equate rSentence to its Range property. Now we can modify the rSentence range and nothing in the document will change until we specifically use a command that does so.

Expand the range over the initial sentence

Like we did with the Selection in the original macro, we need to expand the initial working range rSentence over the current sentence.

' Expand the working range over the initial sentence
rSentence.Expand Unit:=wdSentence

Briefly, the Expand command extends the range boundaries in both directions until it reaches the respective limit of the given document unit. Typical document units from the WdUnits constants table include: wdWord, wdSentence, or wdParagraph. More unit constants exist but Expand only works with a subset of them. We use a Unit option with a colon equals := symbol to assign the desired unit size.

Now our sentence range mimics what the original macro was doing with the initial Selection expansion.

Detect the punctuation

We need to detect the punctuation and act accordingly, but we should handle a detail first, or it might thwart our efforts later.

Word automatically handles some spacing issues between content as we modify text. Much of the time, it's helpful. Word might automatically remove an extra space between sentences that we did not properly select, but the default behavior is more useful for real time editing than when creating automated macros. Occasionally, the extra edits Word makes can cause headaches for us if we do not detect and correct for them.

Trim extra blank space from end

In the context of sentence selections, Word includes any trailing space(s) or paragraph marks in a selection (we're ignoring tabs to make it a tad simpler), so before checking for any double quotes, we should remove any extra blank space on the right side of the selected sentence. This will make the later logic easier.

We just need to move the end of the range backward if there are any spaces or paragraph markers present. To accomplish this subtask, we introduce a lesser-used Word VBA command, MoveEndWhile.

rSentence.MoveEndWhile ' Not done ...

Let's unpack this command and add the necessary details.

Command essentials

The MoveEndWhile method adds or removes any of a set of specified characters to or from the End of the range. Whether it adds or removes characters depends on the direction specified with the Count option (see below), but let's assume our main use case of removing characters.

MoveEndWhile requires a character set option called Cset. The command compares each successive character in the document at the End position of the range to the characters in Cset. If it matches, the character is removed from the selection (not the document). The process stops when the command finds any character not included in Cset or when it reaches the maximum number of allowed match attempts.

A sibling command MoveStartWhile exists with similar requirements and function, but it works with the Start of the range.

Exclude spaces

To exclude spaces, we assign a space inside double quotes literally as " " to Cset. The character set option looks like Cset := " ".

' Moves the range End position past any spaces
rSentence.MoveEndWhile CSet:=" " ' Not done ...

The colon equals := symbol next to Cset is how we assign a value to a command parameter. With Cset, we usually need to specify the desired characters in double quotes, but any special characters like paragraph markers will need to be included separately.

Exclude paragraph markers

In general, the initial expanded sentence selection will also include any paragraph markers for sentences at the end of the current paragraph. It may even extend over multiple paragraph markers if empty paragraphs exist immediately after the sentence. The return character is defined as vbCr (actually three variations exist, but this one is sufficient for our needs) in a Word VBA constants table.

Adding text strings (concatenation)

We use a plus + sign to "add" the two "strings" together (called string concatenation). The character set option now looks like Cset := " " + vbCr. With this set, the MoveEndWhile command keeps moving the End of the selection for either a space or a paragraph marker.

' Moves the range End position past any spaces or paragraph markers
rSentence.MoveEndWhile CSet:=" " + vbCr ' Not done ...

An ampersand & also works for string concatenation with some tiny differences in how they can be used, but I prefer the plus + sign for its similarity to mathematical addition.

Set the move direction

The Count option specifies the maximum number character match attempts, so it limits how far the command could extend the End of the range. Positive counting numbers will move the End position forward in the document, so we could limit the number of characters to check perhaps a maximum of 3 characters. As such, the command would look no further than 3 characters away from the current position whether or not the End position moved. The default is any number of characters forward, so the Count option would be equal to the default value of wdForward (which is defined in yet another Word constants table).

Negative numbers move the End position backward in the document. If we want to move backward by any number of matched characters, we set Count equal to wdBackward which is defined in the same constants table.

' Moves the range End position backward past any spaces or paragraph markers
rSentence.MoveEndWhile CSet:=" " + vbCr, Count:=wdBackward

We need to separate the two options with a comma. If the End position moves before the Start position, the Start is set equal to the End which effectively collapses the range.

Double quotes in Mac and Windows

Unfortunately, double quotes are represented differently between Mac and Windows systems which includes Microsoft Word, so we have to get a little more technical.

Some standard character constants

In computer land, text characters are actually defined as numbers, so the computer can understand and identify them. A very common standard table is the "ascii" table which is an acronym for American Standard Code for Information Interchange (developed in 1961 just after the dinosaurs roamed the Earth in computer years). It includes numbers 0 through 9 as text, upper and lowercase English letters, as well as some other characters. Unfortunately, the table is rather limited, and most characters are not defined in it or even in Word's extension of it. Many "extended" ascii tables exist which is part of the reason Mac and Windows internally represent "curly" (left or right oriented) double quotes differently.

Double quote character constants

We want left and right double quotes. In Word for Mac, a left curly double quote is Chr(210) and a right is Chr(211). In Word for Windows, a left curly double quote is Chr(147) and a right is Chr(148).

Huh?

What is Chr(...)?

We need to translate between the computer's numeric representation of characters to the text we humans want to see on the screen. VBA (and other languages) has a function called "Chr" which is short for "character." Plug a number into the function, and you'll get the corresponding text representation. The Chr function allows us to specify many non-keyboard characters using the corresponding numbers from a constant table, but the default character sets can vary especially between different operating systems like Mac or Windows.

If you want characters from other languages, you can also look at Unicode. VBA includes a separate function, ChrW(...), to handle the wide variety of other characters available with Unicode.

Straight double quote

If we want to be complete, we can also include Chr(34) which is a straight double quote your keyboard produces. This is probably a good idea because occasionally Word's smart quotes feature doesn’t catch and convert a straight double quote to the appropriate curly double quote.

Remove the left or right double quote

Now, we set up to remove a possible double quote from our range, but the tricky part is that we only want to remove it if it occurs on one side.

Some simplifying assignments

We define three plain text constants for the double quotes to make the macro easier to read for humans.

' Declare double quote characters for later
Dim StraightDQ As String, LeftDQ As String, RightDQ As String
StraightDQ = Chr(34)

' Curly double quotes on a Mac
LeftDQ = Chr(210)
RightDQ = Chr(211)

' Curly double quotes in Windows
LeftDQ = Chr(147)
RightDQ = Chr(148)

In standard VBA, we could just assign the strings to variables, but I said we were trying to be more careful now. Here we declare StraightDQ as a String using "As String". See how VBA reads nicely. As shown, we can combine several variable declarations on the same line if we separate them by commas, but every variable needs its own type even if it is the same as the previous or next. Otherwise, the variable missing a type would be a generic "Variant" type. Most of the time, that would still be okay, but we're trying to be clear and consistent.

If we really wanted to be specific, we could declare them as constants (using Const instead of Dim), but I'm neglecting that specificity. The assignment notation has to be all on one line which is nice if you're used to it but a little messy if you're new to it.

Use the curly double quotes set for Mac or Windows as needed. If you happen to work in Word for Mac or Windows at different times, it's convenient to instead create some simple functions to return the corresponding double quote character based on the current operating system, but the details stretch out too long to include here.

Get the first and last characters of the Selection

For comparison purposes, we need to identify the first and last characters of the range. Any valid Range variable includes a collection of Characters inside it.

rSentence.Characters

Some VBA collections include two convenient properties, First and Last, to refer to the indicated element.

rSentence.Characters.First
rSentence.Characters.Last

First and Last return a character range in the document. We need the actual plain text string, we refer to the range's Text property.

rSentence.Characters.First.Text
rSentence.Characters.Last.Text

As written, these are the first and last characters we need for later comparison. We could use these representations directly, but it is convenient to store the characters in two plain text string variables. In computer world, plain text is essentially a value, so just use an equals = sign like we would when assigning a value to a numerical variable like x = 1.

' Declare first and last characters for later
Dim FirstCharacter As String, LastCharacter As String
FirstCharacter = rSentence.Characters.First.Text
LastCharacter = rSentence.Characters.Last.Text

Pick variable names that clearly represent the respective characters.

Character and paragraph ranges comment

If you’re paying close attention, you might notice a confusing difference with the above use of First for a character and its use in a previous macro where we referred to the first paragraph of the Paragraphs collection based on the insertion point position.

' Previous macro use of Selection object Range for a VBA Paragraph
Selection.Paragraphs.First.Range

As shown, we further referred to an additional “Range” property for the referenced First Paragraph, but the Characters collection above omits the Range reference after First.

The difference is a Paragraph is an object in VBA with its own properties and methods whereas a character is just a character at a specific document position. We needed to refer to the Paragraph's Range (see our supplementary article for more explanation) to get the spanned document content. The Characters collection just stores the corresponding character ranges, so First already refers to a document range. The dissimilarity is a little awkward, but it occurs when the referred thing is an inherent VBA object type.

Difference between the character range and its text

The character range basically corresponds to its position in the document whereas the character Text property refers to the actual document plain text we see on the screen. In general, ranges can span any amount of document content, but of course, a character range has a length of a single character.

Detect a double quote

Now we need to detect whether the identified first and last characters are the respective left or right double quotes. This gets a little messy.

Making the individual character comparisons

We literally compare whether the character stored in the FirstCharacter variable is the same as a left double quote. A similar argument applies to the LastCharacter variable. The result will be a True or False (Boolean) value answering the respective question.

' Conditions checking whether each variable is the character
FirstCharacter = LeftDQ
LastCharacter = RightDQ

We should also include a straight double quote comparison for each character, so a tiny formatting mistake does not mess up our macro. This occurs sometimes when AutoCorrect does not trigger as expected (perhaps after an undo action). For some fonts, we might not even notice the straight double quote character did not convert to the appropriate left or right double quote.

' Conditions checking whether each variable is a straight double quote
FirstCharacter = StraightDQ
LastCharacter = StraightDQ

The fact that these comparisons look like variable assignments is an unfortunate aspect of VBA, but VBA will interpret them as conditions with True or False values when they are used inside a conditional statement (see our introduction to conditional statements in VBA for more explanation).

Using Or with compound conditions

We sometimes need to combine conditions using "Boolean operators." The two main operators are And or Or. We'll use Or below, but we'll also see Xor later.

An "operator" is just a mathematical or logical symbol that takes usually two values and returns a result. For example, a plus + sign is an operator that takes two numbers and combines them into another number as in 1 + 2 = 3.

Condition1 Or Condition2

The Or operator takes two conditions and gives a result of True if either or both conditions are True. Otherwise, it gives a False result. For example, if Condition1 is True but Condition2 is False, then the compound result, Condition1 Or Condition2, is True. In equation form it says, True Or False = True.

Making a compound condition to detect either quote type

Either of our character comparison conditions could work in a document. A given double quote could be a straight (keyboard) quote or a left or right double quote, so we need to put them together into a pair of compound conditions with Or operators.

FirstCharacter = LeftDQ Or FirstCharacter = StraightDQ
LastCharacter = RightDQ Or LastCharacter = StraightDQ

See how it gets messy quick.

Store the condition result in a variable

We could just use these compound conditions where needed, but they're ... long, so it's nice to store the results in separate variables.

' Declare first and last character match results for later
Dim IsFirstCharacterQuote As Boolean, IsLastCharacterQuote As Boolean
IsFirstCharacterQuote = FirstCharacter = LeftDQ Or FirstCharacter = StraightDQ
IsLastCharacterQuote = LastCharacter = RightDQ Or LastCharacter = StraightDQ

We literally use the same conditions from above but just assign the result to the corresponding variable. Try to pick variable names that make sense. I like short names when possible and clear, but sometimes a good descriptive name is long.

Unfortunately, the use of equals = sign three times in the same statement looks confusing, but VBA interprets each one based on its context. The first equals is an assignment to a variable whereas the second and third are part of two separate conditions.

Boolean variables in conditional statements

The variables have the type "As Boolean" which a standard name for this type of variable, so we're stuck with it until the apocalypse. Such variables store True or False values (although they are secretly numbers internally).

The advantage of this approach is we can then use these Boolean variables directly in conditional statements allowing us to make decisions in our macros depending on the current state of our document. The most important conditional statement is an “If … Then … Else” (see our introductory article), but we'll eventually see other uses for Boolean variables.

Sometimes, such assignments result in a miniscule efficiency boost because VBA doesn't have to repeatedly evaluate the compound condition, but usually they just make things easier for us humans to read if we come back to modify the macro at a later date.

Check for double quotes in the document

Our rough conditional statement to check for double quotes is something like:

If a double quote is only on one side Then
' Remove the double quote from the sentence range
End If

This is called "pseudo-code" which people sometimes use to think through their logic before actually writing the real code.

Hmmm.

So, we leave the double quotes if they are on both sides. That's easy, just don't remove them, but how do we do the test for them and then remove the respective character in VBA?

And and Not Boolean operators

How do we use the above compound conditions to test for double quotes in our dialog?

The And operator works on two conditions similar to what Or did above, but And only results in True if both conditions are True. Otherwise, it gives a False result.

For our double quotes test, we might start with something like:

' Not quite ... checks for double quotes on both sides of the range
IsFirstCharacterQuote And IsLastCharacterQuote

But this isn't quite right because it checks whether double quotes are on both sides of the range.

Conditions detecting double quotes on only one side

We need a way to flip the True or False result of one of the conditions. A Not operator only works on one condition where it changes a True value to False and a False value to True.

Why is it useful in this macro?

We need to know if only one side of our range has a double quote character not both, so we flip the condition for the other side using Not.

' Check for double quotes only on the left side of the range
IsFirstCharacterQuote And Not IsLastCharacterQuote
' Check for double quotes only on the right side of the range
Not IsFirstCharacterQuote And IsLastCharacterQuote

Conditional statements detecting double quotes on either side

Putting these into a conditional statement, we get two slightly different If statements:

If IsFirstCharacterQuote And Not IsLastCharacterQuote Then
' Remove the double quote from the left side of the sentence range
End If
If Not IsFirstCharacterQuote And IsLastCharacterQuote Then
' Remove the double quote from the right side of the sentence range
End If

I wrote my versions using a Boolean Xor "exclusive or" operator, but the above are more direct.

Removing a double quote

Several ways exist to modify the range, but we already introduced the MoveEndWhile command earlier. It's works just fine in this context.

To remove a right double quote from the end of the range, we would use a character set of RightDQ (our variable name for it above). The catch is it could also be a straight double quote which we called StraightDQ. We previously concatenated strings with a plus + sign, so putting the two possible quotes together, our character set is, Cset := RightDQ + StraightDQ. Inserting this into a command, we have:

rSentence.MoveEndWhile CSet:=RightDQ + StraightDQ ' Not done ...

Now, we need to move the End of the range backward in the document, but we also did that above for spaces using Count := wdBackward. Our command becomes:

rSentence.MoveEndWhile CSet:=RightDQ + StraightDQ, Count:=wdBackward

These methods are a little overkill, but they waste only milliseconds on an extra character comparison. One advantage of this approach is we can easily add in single quotes later, if desired, with a simple change to the character set.

We repeat the above for the Start of the range with a left or straight double quote, but we need to use the sibling command MoveStartWhile. We called LeftDQ, so the revised command is:

rSentence.MoveStartWhile CSet:=LeftDQ + StraightDQ

We're moving the Start position forward, so we can omit the Count option since that is the default.

Remove the detected double quote

Finally, use the respective command to remove the double quote if it only occurs on one side of the sentence.

If IsFirstCharacterQuote And Not IsLastCharacterQuote Then
' Remove the double quote from the left side of the sentence range
rSentence.MoveStartWhile CSet:=LeftDQ + StraightDQ
End If
If Not IsFirstCharacterQuote And IsLastCharacterQuote Then
' Remove the double quote from the right side of the sentence range
rSentence.MoveEndWhile CSet:=RightDQ + StraightDQ, Count:=wdBackward
End If

Remember, spaces and paragraph markers were removed as the first step when we started.

Reclaim any trailing spaces

If we want to be consistent with how Word works in manual editing, we could re-extend the end of the range to include any trailing spaces. We reuse the MoveEndWhile command from above specifically extending the end of the range forward over any spaces.

rSentence.MoveEndWhile CSet:=" " ' Optional

This command moves the End position forward in the document using the default direction. I do not include paragraph markers since that does not make sense for a sentence selection (not sure why Word includes them for automatic sentence selections). If the command finds a right (or straight) double quote on the end, nothing happens, which is fine; but if no right double quote was present, it restores the range to mimic the default-ish Word selection by including the trailing spaces on the end.

This step isn't strictly necessary for the macro to function as advertised, but it is a nice tweak since I prefer the macro behavior to match expected Word defaults as much as possible at least when it makes sense with the macro action.

Delete the selection

We finally use the Delete method on the resulting range whether or not any changes were made to it based on double quotes.

rSentence.Delete

As an aside, the Delete method has a Unit option, so in principle, we could specify a sentence unit using Unit := wdSentence. For our current macro, it does not seem to accept a sentence unit presumably because the action is not defined in standard Word when pressing the Delete key. We would not use it anyhow because it does not give us control over the details like omitting or including double quotes based on our document content.

Final macro allowing for double quotes

Putting it all together in order we get:

Sub DeleteSentenceEnhanced()
' Delete the current sentence in the document respecting double quotes
' on one side of a sentence

' Set a working range variable to the initial Selection range
Dim rSentence As Range
Set rSentence = Selection.Range

' Expand the working range over the current sentence in the document
rSentence.Expand Unit:=wdSentence
' Remove any trailing spaces from the range to simplify logic below
rSentence.MoveEndWhile CSet:=" " + vbCr, Count:=wdBackward

' Define left and right double quotes to use below
Dim StraightDQ As String, LeftDQ As String, RightDQ As String
' Change left and right double quotes to Chr(147) and Chr(148) on Windows
LeftDQ = Chr(210)
RightDQ = Chr(211)
StraightDQ = Chr(34)

' Detect the first and last characters of the range
Dim FirstCharacter As String, LastCharacter As String
FirstCharacter = rSentence.Characters.First.Text
LastCharacter = rSentence.Characters.Last.Text

' Detect first and last character match results for later
Dim IsFirstCharacterQuote As Boolean, IsLastCharacterQuote As Boolean
IsFirstCharacterQuote = FirstCharacter = LeftDQ Or FirstCharacter = StraightDQ
IsLastCharacterQuote = LastCharacter = RightDQ Or LastCharacter = StraightDQ

' Test whether a double quote exists on only one side of the range
If IsFirstCharacterQuote And Not IsLastCharacterQuote Then
' Remove the double quote from the left side of the sentence range
rSentence.MoveStartWhile CSet:=LeftDQ + StraightDQ
End If
If Not IsFirstCharacterQuote And IsLastCharacterQuote Then
' Remove the double quote from the right side of the sentence range
rSentence.MoveEndWhile CSet:=RightDQ + StraightDQ, Count:=wdBackward
End If

' Replace any trailing spaces for the range to mimic a Word selection
rSentence.MoveEndWhile CSet:=" "
' Finally delete the modified sentence range
rSentence.Delete
End Sub

I added a bunch of comments to make it clearer what is going on. It’s tempting to omit them when you're creating your own macros but including them is strongly recommended. You may forget what you were thinking later if you ever need to revise or tweak the macro.

Hopefully, the advantage of rolling our own delete sentence macro is apparent. It now conveniently accounts for dialog, so it works more intuitively as we edit our novels.

Improvements

Depending on how refined you want your macro to be, a few other tweaks might make it even nicer to use.

Spacing tweaks

In many of my macros, I like to add steps to handle little special cases. Word often does a good job of adjusting the spacing around sentences or paragraphs, but occasionally in macros, the default Word behavior will leave a trailing space at the end of a paragraph or a sentence after the delete action finishes. I find it annoying, so why not let the macro also handle that for me automatically?

This tweak is more of a perfectionist perk than being absolutely necessary. While not super difficult, it is trickier than it seems since Word fights us on the spacing. We worked out the details in a separate function, but they are not included in the current macro.

What about dialog tags?

The macro works well as advertised, but if a line of dialog ends with a dialog tag such as, "This character is saying something blah, blah," she said. The macro steps will select the entire sentence including the right double quote and dialog tag on the end, but it will exclude the left double quote at the beginning.

Huh? Why?

The current macro isn't smart enough to detect the right double quote inside the sentence before the dialog tag. As a result, it perceives the character statement as being just a sentence within a larger paragraph of dialog. The macro will delete the rest of the sentence and leave an isolated left double quote at the beginning of a now empty sentence. That's not what we want, but fixing this quirk is harder than it might seem at first glance.

I am usually a proponent of having the macro do everything I need but within reason. I use dialog tags sparingly, so it seems like too much effort for the payoff based on how I write most of my dialog. While I've implemented some macros that manipulate dialog tags, it is a much bigger job in this macro than it might seem, so the "within reason" factor kicks into my decision-making process. As such, it will be relegated to member plus content if there is enough interest.

Allow parentheses

This macro extends trivially to also work with parentheses which I find useful in some of my work documents. We could include the new character definitions.

' Not really necessary since a parenthesis is just one character
LeftParenthesis = "("
RightParenthesis = ")"

But these assignments are not really necessary since a parenthesis is just a plain text character, "(" or ")", respectively. We can skip the variable assignments since the character check is simpler now.

We should reset the stored first and last characters of the range since they could have changed in the previous steps when detecting double quotes.

' Reset the current first and last characters of the range to allow
' for parentheses on one side
FirstCharacter = rSentence.Characters.First.Text
LastCharacter = rSentence.Characters.Last.Text

We then need two additional conditional statements to detect whether the respective parenthesis exists on only one side of the range in the document. Rather than create additional Boolean variables like we did earlier, we just directly compare the first or last characters to the respective parenthesis because we only need to consider one possible character on either side.

' Test whether a parenthesis exists on only one side of the range
If FirstCharacter = "(" And Not LastCharacter = ")" Then
' Remove the open parenthesis from the left side of the sentence range
rSentence.MoveStartWhile CSet:="("
End If
If Not FirstCharacter = "(" And LastCharacter = ")" Then
' Remove the close parenthesis from the right side of the sentence range
rSentence.MoveEndWhile CSet:=")", Count:=wdBackward
End If

We adjusted the character sets for the move methods to the respective parentheses.

This is then added to the bottom of the above macro just after checking for double quotes thus accounting for both cases. Technically, the order matters since this placement will remove double quotes before parentheses, but the distinction will rarely, if ever, matter in a novel or even a work-related document.

Using MoveStartWhile and MoveEndWhile will handle nested parentheses also, which is a nice bonus feature.

Final more comprehensive macro

The final result allowing for either double quotes or parentheses is:

Sub DeleteSentenceEnhanced()
' Delete the current sentence in the document respecting double quotes or
' parentheses on one side of a sentence

' Set a working range variable to the initial Selection range
Dim rSentence As Range
Set rSentence = Selection.Range

' Expand the working range over the current sentence in the document
rSentence.Expand Unit:=wdSentence
' Remove any trailing spaces from the range to simplify logic below
rSentence.MoveEndWhile CSet:=" " + vbCr, Count:=wdBackward

' Define left and right double quotes to use below
Dim StraightDQ As String, LeftDQ As String, RightDQ As String
' Change left and right double quotes to Chr(147) and Chr(148) on Windows
LeftDQ = Chr(210)
RightDQ = Chr(211)
StraightDQ = Chr(34)

' Detect the first and last characters of the range
Dim FirstCharacter As String, LastCharacter As String
FirstCharacter = rSentence.Characters.First.Text
LastCharacter = rSentence.Characters.Last.Text

' Detect first and last character match results for later
Dim IsFirstCharacterQuote As Boolean, IsLastCharacterQuote As Boolean
IsFirstCharacterQuote = FirstCharacter = LeftDQ Or FirstCharacter = StraightDQ
IsLastCharacterQuote = LastCharacter = RightDQ Or LastCharacter = StraightDQ

' Test whether a double quote exists on only one side of the range
If IsFirstCharacterQuote And Not IsLastCharacterQuote Then
' Remove the double quote from the left side of the sentence range
rSentence.MoveStartWhile CSet:=LeftDQ + StraightDQ
End If
If Not IsFirstCharacterQuote And IsLastCharacterQuote Then
' Remove the double quote from the right side of the sentence range
rSentence.MoveEndWhile CSet:=RightDQ + StraightDQ, Count:=wdBackward
End If

' Reset the current first and last characters of the range to check
' for parentheses on one side
FirstCharacter = rSentence.Characters.First.Text
LastCharacter = rSentence.Characters.Last.Text

' Test whether a parenthesis exists on only one side of the range
If FirstCharacter = "(" And Not LastCharacter = ")" Then
' Remove the open parenthesis from the left side of the sentence range
rSentence.MoveStartWhile CSet:="("
End If
If Not FirstCharacter = "(" And LastCharacter = ")" Then
' Remove the close parenthesis from the right side of the sentence range
rSentence.MoveEndWhile CSet:=")", Count:=wdBackward
End If

' Replace any trailing spaces for the range to mimic a Word selection
rSentence.MoveEndWhile CSet:=" "
' Finally delete the modified sentence range
rSentence.Delete
End Sub

It's a nice enhancement to when working in a novel since almost all novels include lots of dialog. Handling parentheses is a bonus that benefits some work documents and only required a little extra work. If you work in Word for Window or Mac at different times, we defined two double quote utility functions to let Word pick the correct double quote characters depending on which system you are currently using.

Works with multiple sentences

We don't mention it throughout the above commentary and explanations, but due to the default behavior of the Expand command, this function also naturally handles consecutive selected sentences if a user extends the initial selection over a sentence boundary.

A few related macros

Another dialog related macro toggles double quotes around a paragraph. We've also created a variation that deletes partial sentences to the beginning or end and another that quickly moves sentences or words.

Macro length comment

Don’t cringe at the length of the macro any more than you cringe at a day’s work finished by typing one word at a time. We built the macro one step at a time, and there’s a certain satisfaction afterward when you’ve created a nice, functional macro to help you in your writing and editing.

Affiliate Links

If you're interested in using Word or another tool related to the article, check out these affiliate links. I may make a small commission if you purchase when using them, but there is no increase in cost for you, and it helps to support this site and associated content.

I've been using Microsoft for Business for commercial use (that's us writers) on one of the lower pricing tiers for years. I get to use my macros, have online storage, and don't have to worry about software updates.