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 partial sentences

Word • Macros • Editing
Peter Ronhovde
7
min read

Trimming sentences faster in Word will obviously speed up the editing process for a manuscript. Toward this end, we'll create a pair of macros to delete to the beginning or ending of a sentence.

Thanks for your interest

This content is part of a paid plan.

Delete part of a sentence

Word includes various keyboard shortcuts for manipulating words or paragraphs. Sentences are a rather fundamental writing unit, and Word does include a few hidden commands for manipulating them, but the list is rather limited. Creating some extra macros to improve sentence editing is a worthy endeavor. We'll focus on a macro that deletes to the end of a sentence, but the counterpart to delete to the beginning of a sentence requires only a simple change.

Deleting to the end of a sentence with a macro
Example of deleting to the end of a sentence with a macro

While I don't like admitting it, this is probably one of my more used macros, so you should definitely try it out. The base macro is short, so we take a couple side trails to enhance our VBA prowess. We further enhance the macro to account for quotes and ending sentence punctuation in the member article.

Create the empty macro

A previous post covers creating an empty macro like the one shown below:

Sub DeleteSentenceToEnd()
' Delete to the end of the current sentence

End Sub
Sub DeleteSentenceToStart()
' Delete to the start of the current sentence

End Sub

As a quick reminder, the single quote on the second line tells the VBA editor that the rest of the text on that line is a only for human readers. We'll start our commands on the blank line.

The overall steps are similar, so after we've created the former macro, we'll modify it to delete to create the latter.

Delete to the end of a sentence

We previously used the Selection Expand method to prepare for deleting a full sentence from anywhere inside it.

' Not quite correct for a partial sentence ...
Selection.Expand Unit:=wdSentence

But we don't want to expand the selection over the entire sentence before deleting it, so we need another approach.

Hmmm …

Picking the correct method

Part of writing good Word macros is picking the correct command for the task. Early on, I floundered, but I eventually discovered Word VBA has some nicely targeted commands we can leverage for our specific needs. It's easy to overlook some of them, but if we'll just dig a little ... (sorry about the mixed metaphors but I'm trying to teach you how to fly not flounder).

Select to the end of a sentence

We need a way to just select part of a sentence. We could use standard move command that has an extend option, but we can do even better for this macro.

Use the EndOf command

We’ll leverage a lesser used move method of the Selection called EndOf to setup our delete step later.

Selection.EndOf Unit:=wdSentence ' Not done ...

Given the preposition ending the method name, we would expect a requirement to specify a relevant document unit. Word VBA understands several standard ones which are defined in the WdUnits constants table. We assign the desired constant using the Unit option name with a colon equals := symbol. Of course, in this macro, we'll use wdSentence, but the concept could easily be extended to other document unit types (most useful would be a paragraph using wdParagraph).

Selection.EndOf Unit:=wdSentence, Extend:=wdExtend

The Extend parameter requires a constant from the short WdMovementType constants table. It defaults to wdMove which collapses the Selection and just moves the insertion point, but we want wdExtend which extends the selection instead from the End position.

Contrast with the MoveRight method

Taking an announced (teaching) side trail, we could accomplish something similar using the regular MoveRight method instead. Without going into a lot of detail, the command would be:

' Not incorrect, but it misses a special case
Selection.MoveRight Unit:=wdSentence, Extend:=wdExtend

It looks very similar, and it even has an Extend option to extend the selection not just move the insertion point. Yay!

What's all the fuss?

The two approaches are not quite the same. The MoveRight command moves or extends to the next Unit regardless of the current position or context in the document, but the EndOf command doesn’t move the insertion point if it is already at the end of the current Unit specified. It also won't extend the Selection if the selection already ends at the correct location.

Using MoveRight this way would not be wrong per se, but we would need to add one or more extra steps or conditions to account for the special case. Why bother when EndOf does exactly what we need?

Delete the partial sentence

We've seen the Delete method before, but for completeness it is simply:

Selection.Delete

It's almost anticlimactic at times to finish the macro.

Delete with a sentence Unit?

If you've used Command+Delete (Mac) or Control+Delete (Windows) in Word to delete words, you might remember it also deletes partial words if the insertion point is already in the middle of a word.

Well … the Delete method actually has a Unit parameter also. Couldn't we just use a wdSentence Unit with it and mimic that delete behavior with words?

Uhhh … sounds good at first, but nope.

We can't actually use a sentence unit with the Delete method presumably because the standard delete action using when pressing the Delete key on a keyboard (or a related shortcut) does not understand what to do with a sentence like it does with a word. Apparently, that's our job.

Delete to start of sentence

The sibling command to delete to the start of a sentence is just:

Selection.StartOf Unit:=wdSentence, Extend:=wdExtend

It has the same behavior and options.

Finish the macros

Putting the commands together, the final simple version of the macro is:

Sub DeleteSentenceToEnd()
' Delete to the end of the current sentence
' EndOf will not extend the selection past the current sentence
Selection.EndOf Unit:=wdSentence, Extend:=wdExtend
Selection.Delete
End Sub

I assigned my version to Option+Control+Shift+Delete on a Mac or Alt+Shift+Delete on Windows. The Mac version needs to include the Control modifier key since the DeleteToSentenceStart macro more naturally uses Option+Shift+Delete to delete backward in the document in line with how Mac views the Delete key as a backward delete. MacOS has limited Backspace key support when using modifier keys.

The start version trivially swaps out StartOf for EndOf, but the differences are a little bigger in the extended version.

Sub DeleteSentenceToStart()
' Delete to the start of the current sentence
' StartOf will not extend the selection beginning the current sentence
Selection.StartOf Unit:=wdSentence, Extend:=wdExtend
Selection.Delete
End Sub

I assigned my version to Option+Shift+Delete on a Mac or Alt+Shift+Backspace on Windows.

On either macro, we could instead Cut the Selection to the clipboard using Selection.Cut or write a separate macro for that version if you like. I prefer to have both versions available, but I like my main version to not mess with the clipboard unless the user (me) intends it.

Improvements or extensions

What could we do to make these macros better? Do any trivial modifications exist that will enhance our editing capabilities?

Allow for punctuation marks

We did a similar delete full sentence macro, and we also created a separate version to accommodate dialog or parentheses. When deleting only part of a sentence, I prefer to delete just the text of a sentence not the beginning or ending punctuation. Removing the punctuation allows the macro to naturally handle dialog and parentheses. For the delete to sentence start version, we mostly only need to consider quotes and parentheses, so we'll work on the end of sentence case first.

After we’ve selected the text to the end of the sentence, we want to back up the End position of the Selection.

Character set

The character set is a little long, so it's convenient to store it in a separate variable first, so the upcoming move command is a little easier.

' Define possible end of sentence characters to exclude from the selection
Dim TrimCharacters As String

Now what characters?

Adding strings (of characters)

We add strings using the + sign which is called “concatenation.” For example, "a" + "b" = "ab", but everything has to be a string (of characters) for it to work. The ampersand & operator also concatenates strings (also like "a" & "b" = "ab") and is a little more forgiving in VBA, but it just looks messy.

Regular end of sentence punctuation

We'll start with closing parenthesis ")" or square brackets "]". Then we want to exclude typical end of sentence punctuation: period ".", exclamation point "!", or question mark "?".

We need to define a set of characters as a plain text string, so fortunately, we can just string all these together into one string since the move until command is looking for any of the characters in the string: "?.!)]"

TrimCharacters = ")].!?"
Paragraph markers

A paragraph marker is defined as vbCr (i.e., a return character) a in miscellaneous Word constants table. Including this character is necessary since by default the initial extension of the selection using EndOf will include any trailing paragraph marker(s).

Word includes a trailing paragraph marker in a selection for any sentences at the end of a paragraph. THis is counterintuitive to me, but at least Word is smart enough in this case not to delete the trailing paragraph marker (sometimes the default Word behavior feels like it works against use when writing macros). However, the paragraph marker still needs to be removed from the selection in this macro since we won’t be able to remove the other punctuation marks before it. The move until command would immediately stop when the vbCr character at the end was not in the Cset character list.

End of sentence spaces

Another necessary character is a space " ". Like the paragraph marker above, this is more functional since the move until command would immediately stop when the space was not in the Cset list of characters. This is important because Word considers the current sentence to extend all the way to the beginning of the next sentence which includes the space separating the sentences.

Now our TrimCharacters variable looks like:

TrimCharacters = "?.!)] " + vbCr
Double and single quotes

We want to naturally handle dialog quotes, but how do we tell VBA to include them? That is, we use double quotes to define a string of characters, so how do we specify a double quote character?

A straight single quote is easy. Just include it in double quotes like normal "'".

We can specify a straight double quote as two double quotes inside another pair of double quotes ““””. That’s not confusing at all, right? I suppose not once you get used to it, but I won't or haven't. It’s clearer (to me) to just refer to quote characters by number.

An older way (not better)

Many languages have a Chr(…) function to translate the numerical representation to the actual text characters we want to see on the screen. These can work for some of the necessary characters. For example, straight single and double quotes are Chr(39) and Chr(34), respectively, but the "curly" left and right quotes have different values between Windows and Mac systems. We created some double quote functions to make using them easier in VBA. Despite some information to the contrary, they are available when using Chr(…), but just not necessary when a more convenient function exists.

A more general way

It's actually easier to just use the more general ChrW(…) function since the respective numerical values for double quotes are the same between Word for Windows and Mac. They are summarized below:

  • Straight double quote " → ChrW(34)
  • Left double quote “ → ChrW(8220)
  • Right double quote ” → ChrW(8221)

The character numbers are similar for single quotes.

  • Straight single quote ' → ChrW(39)
  • Left single quote ‘ → ChrW(8216)
  • Right single quote ’ → ChrW(8217)
' Define quote characters by Windows or Mac
Dim LeftDQ As String, RightDQ As String, StraightDQ As String
Dim LeftSQ As String, RightSQ As String, StraightSQ As String
LeftDQ = ChrW(8220): RightDQ = ChrW(8221): StraightDQ = ChrW(34)
LeftSQ = ChrW(8216): RightSQ = ChrW(8217): StraightSQ = ChrW(39)

The ChrW(…) character values work on both Word for Mac and Windows.

Command notation shorthand

We defined the various quotes as variables. When using Dim, we can add more than one variable declaration on a line, but we need to separate them by commas and give a type "As String" (or whatever) for each variable. If we don't give a type, it will be a generic "Variant" type by default, which is usually okay, but it might cause a few small issues with functions.

We also took advantage of a special colon : command separation character. When it is used, VBA treats each part separately, but don't go crazy because overuse can make some dense, hard-to-read steps you may regret later. We used them here mostly because the assignments are so similar, and I didn't want to take up eight lines defining them.

The best way (not covered here)

Even better, the definitions above still take five lines in a macro, but they won't change (probably ever), so why not define them as constants not in the macro but for all macros at the same time. We can then use them in any macro in that module (a group of macros in the VBA editor) without having to redefine them.

Overall excluded characters

Putting all these characters together, out string of excluded punctuation and other marks is:

TrimCharacters = "?.!)] " + Chr(211) + Chr(34) + Chr(213) + Chr(39) + vbCr
Excluding the punctuation marks

After all that explanation, we finally back at the End of the Selection.

Selection.MoveEndWhile Cset:=TrimCharacters, Count:=wdBackward

MoveEndWhile does what the command name implies. It will keep moving the End as long as it keeps finding one of the characters specified in Cset.

Count:=wdBackward is a special case that tells the command to do just that. In general, you could specify a maximum number of characters to move past with a positive number moving forward in the document and a negative number moving backward.

We’ll put these extra commands together in the final macros below.

Reinclude spaces (optional)

We do not generally know whether trimming characters will remove anything other than a paragraph markers or spaces. We needed to trim spaces, so the other characters could be detected simply, but since Word includes ending spaces in a selection by default, it is consistent with that behavior.

Basically, we just need to extend the end forward again but only for spaces. We use the MoveEndUntil method again but just specify a character set of a space " ".

' Extend the selection back over any trailing spaces
Selection.MoveEndUntil Cset:=" "

We're moving forward by default, so we omit the Count option.

While this is optional, it is good to be consistent with how Word works for the most part because that is what people expect. Even when you're creating macros for yourself, there is an inherent expectation. Unless there is a solid reason, we should strive for that consistency.

I find that I do not agree with Word including paragraph markers in sentence selections, so I omit those. This is mostly consistent in that Word is often smart about not deleting the paragraph marker even if a sentence selection (part of the paragraph) is deleted.

Delete to Start of Sentence

The parallel macro to delete to the start of the sentence is nearly the same.

Revised trim characters

We don’t have ending punctuation marks, so we can reduce the number of trimmed characters.

TrimCharacters = "[(" + Chr(210) + Chr(34) + vbCr

As mentioned previously, the “curly” double quote characters are different on Windows and Mac systems. Specifically, the left double quote character in Word for Mac is given by Chr(210) but Chr(147) on Windows. The straight double quote is still Chr(34) everywhere (that uses the ASCII numbering scheme).

If you want to exclude single quote characters, the left single quote is Chr(210) in Word for Mac but Chr(147) on Windows. The straight single quote Chr(39) works on both systems.

Selection.MoveStartWhile Cset:=TrimCharacters

As with MoveEndWhile in the other version, MoveStartWhile keeps moving the Start of the Selection forward in the document as long as it keeps finding one of the characters specified in Cset.

If you want to limit how many characters you move past, give a Count parameter with a positive number (see above).

Capitalize the new sentence

After we’ve deleted to the beginning of a sentence, we’ll be manually capitalizing the new first word most of the time. It won't take long to get annoyed with this, so we should make VBA do it for us.

This is handled by the Case property of a Range (essentially a chunk of contiguous content in the document with a defined Start and End; more on them coming later).

Selection.Range.Case = wdTitleWord

Note how we specify the Range of the Selection before specifying the Case property. This must be done since the Selection doesn’t have its own Case property.

In common help-page fashion, the descriptions in the list of VBA case constants are terse (details matter when writing macros), but in short, the constant wdTitleSentence or wdTitleWord are probably best suited here, but it doesn’t quite act like we would expect in all cases.

As an aside, the wdTitleSentence Case property (almost more of a method or command) seems to understand when it’s inside a sentence if we use wdTitleSentence even when the entire sentence isn’t selected. This is okay in our current macro since we are confident our selection includes the beginning of the sentence (it won’t capitalize the first word otherwise), but in other macros, I will sometimes just collapse the Selection near the relevant word and use wdTitleWord instead just to be sure a word is capitalized as I intended.

Using the constant wdTitleWord makes the Case property/command capitalize the first letter of each word in a Range, but since we're only positioned at a single word at the beginning of a sentence, it only changes one. That's exactly what we want.

The disadvantage of including the automatic capitalization is Word does not understand other words like LastCharacter. It will convert the uppercase "C" in the middle of the word to a lowercase "c". That occurs much less often, so it's a reasonable compromise.

Check for a selection before deleting?

Some little gotchas can pop up. What if no sentence exists at the insertion point?

The initial steps will try to select to the end of the sentence but span nothing. Then the Delete method would still delete something. Mostly likely, it would delete a paragraph marker of an empty paragraph (the most logical reason for no sentence being present), but it would delete whatever was next to the insertion point.

We actually only want to delete the selected contents if a normal text selection exists. The Selection object has a Type property we can use to validate whether the selection contains any content.

Selection.Type ' Not done ...

We're focused on text, so we'll compare the Type to the wdSelectionNormal constant from the selection type constants table. The condition looks like:

Selection.Type = wdSelectionNormal

Both are numbers, so we're just checking whether the two values are equal. VBA treats this as a True or False (Boolean) condition when it's used within a conditional statement. Our conditional statement would look something like:

If selection is normal text Then
' Delete the selection
End the conditional statement

Nothing should be deleted if the selection is empty, so no otherwise (Else) part is included.

' Check whether a selection exists before deleting anything
If Selection.Type = wdSelectionNormal Then
Selection.Delete ' Delete the selection
End If

Since the conditional statement is so simple, we can actually condense it into one line:

' Check whether a selection exists before deleting anything
If Selection.Type = wdSelectionNormal Then Selection.Delete

Final macros

Now we get to the final macros. Hopefully, you didn’t skip all the way to here. There are several useful points above if you want to write other macros.

These macros also show how just getting the details right can sometimes make the steps stretch more than we might prefer; however, we just build it one step at a time.

Deleting to the end of a sentence

We focused on deleting to the end of a sentence. Putting all the steps together, we get:

Sub DeleteSentenceToEnd()
' Delete to the end of the current sentence

' EndOf will not extend the selection past the current sentence
Selection.EndOf Unit:=wdSentence, Extend:=wdExtend

' Trim most sentence ending punctuation marks
' Quote character constants are defined as global for all macros
Dim TrimCharacters As String
TrimCharacters = "?.!)] " + RightDQ + StraightDQ + RightSQ + StraightSQ + vbCr
Selection.MoveEndWhile Cset:=TrimCharacters, Count:=wdBackward
' Extend the selection back over any trailing spaces
Selection.MoveEndUntil Cset:=" "

' Only delete a non-empty selection
If Selection.Type = wdSelectionNormal Then Selection.Delete
End Sub

I assigned my implementation to Option+Delete on a Mac or Alt+Delete on Windows.

Deleting to the start of a sentence

The sibling macro to delete to the start of a sentence is:

Sub DeleteSentenceToStart()
' Delete to the start of the current sentence

' StartOf will not extend the selection before the current sentence
Selection.StartOf Unit:=wdSentence, Extend:=wdExtend

' Trim most sentence starting punctuation marks
' Quote character constants are defined as global for all macros
Dim TrimCharacters As String
TrimCharacters = "[( " + LeftDQ + StraightDQ + LeftSQ + StraightSQ
Selection.MoveStartWhile Cset:=TrimCharacters

' Only delete a non-empty selection
If Selection.Type = wdSelectionNormal Then
Selection.Delete
' Capitalize new first word of the sentence
Selection.Range.Case = wdTitleWord
End If
End Sub

For this version, we swapped out EndOf for StartOf at the beginning. In the middle, the trimmed characters and direction are different, and we removed the line that restores the trailing selection spaces. At the end, we added a step to capitalize the new first word of the sentence just after the Selection is deleted.

I assigned this macro to Control+Option+Delete in Word for Mac or Alt+Backspace on Windows.

Use global quote constants

The quotes are defined as global constants for all macros, but if you chose not to use them, just copy the below variable definitions before the line where the trimmed characters are assigned (or the top of the macro also works just as well).

' Define quote characters by Windows or Mac
Dim LeftDQ As String, RightDQ As String, StraightDQ As String
Dim LeftSQ As String, RightSQ As String, StraightSQ As String
LeftDQ = ChrW(8220): RightDQ = ChrW(8221): StraightDQ = ChrW(34)
LeftSQ = ChrW(8216): RightSQ = ChrW(8217): StraightSQ = ChrW(39)

These definitions were explained earlier. These are technically variables not constants, but the trim characters line just uses them as is.

Other improvements or extensions

What could we do to make these macros better? Do any trivial modifications exist that will enhance our editing capabilities?

Undo records

We could encapsulate the two changes into an undo record, so the undo shortcut can be used just once to reverse the changes. This is more of a user-friendly tweak for this macro since there are only two changes at most, but it's a nice touch. However, please read the tutorial carefully since undo records can also cause problems.

What about paragraphs?

Working through the macro, it's easy to change out the sentence manipulation for a paragraph. I don't need the paragraph version as often, but it has come in handy a few times. Given that it requires a tiny expenditure of effort, it's an excellent extension of the base macro.

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.