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

Capitalize sentence allowing dialog

Word • Macros • Editing
Peter Ronhovde
15
min read

Capitalizing the first word of a sentence is a trivial but necessary task, so we create a macro to do so from anywhere within the sentence while also accounting for double quotes or parentheses.

Thanks for your interest

This content is part of a paid plan.

Capitalize the current sentence

We create another macro in a series aimed at tackling menial editing tasks. The goal is to keep our fingers working on the human part of the editing process and let the computer do what it does best. This macro is simple and yet practical. While it may not be the most productive macro in the automated editing world, it’s nice to capitalize the first word of the sentence from wherever and just continue working.

What are the manual steps?

If we manually capitalize the first word of the current sentence, what steps are required?

  1. Use the mouse (slow) or keyboard to move to the beginning of the sentence
  2. Delete the first character
  3. Type the new capitalized first character

We've done this probably thousands of times, but let's trim them down to one shortcut tap.

We can cycle the capitalization of a Word (or text in a selection) using a standard keyboard shortcut Shift+F3, but we still need to move to the beginning of the sentence (or otherwise select it) before we can  change its capitalization. A previous article covered assigning shortcuts to some hidden Word commands to help with sentence navigation (sadly omitted) in Word, but some tasks occur often enough, it is more efficient to create a specific macro to handle it.

Mimicking the above manual steps in VBA is clumsy and unnecessary, so we'll focus on solving the problem a little more like VBA intended.

Talk about VBA thingies

VBA represents various document elements as virtual "objects" which encapsulate data (called "properties) and actions (called "methods") related to its structure and function in the document. These properties and methods allow us to manipulate the associated document content, and we can further declare variables to represent specific elements in the document.

What is the Selection?

The Selection (with a capital "S") is VBAs representation of the visible selection or insertion point on the screen. We can move it around, collapse it, delete the text, etc. Since it controls the actual selection on screen, any changes are immediately visible, but only one Selection exists per document. The Selection is like a specialized Range with some extra properties and methods. See our brief introduction to the Selection for more information.

Related to the current macro, the Selection contains several collections (essentially fancy VBA lists) of perhaps partially or fully spanned document elements. The content could include Words, Sentences, Paragraphs, Bookmarks, etc. We will use the Sentences collection of the Selection for this macro.

What is a Range?

Conceptually a range corresponds to a contiguous region of document content. VBA includes a generalization of this concept called a Range (with a capital "R"). It is tracked literally using Start and End character positions in the document, but it also includes other properties and methods that allow us to control its extent, modify any related document content, change capitalization, and more. See our brief introduction to Ranges in Word VBA if you would like more information about them.

Many document elements are treated as ranges such as sentences, words, characters, headings and their content, etc. Like the Selection, a valid range contains collections with essentially the same kinds of (perhaps partially) spanned document elements as above. We will use the Words collection of a sentence range for this macro.

Create the empty macro

Open the VBA editor and create the following macro skeleton. If you prefer, a previous post covers creating an empty macro using the application interface.

Sub CapitalizeCurrentSentence()
' Capitalize the first word of the current sentence

End Sub

The single quote tells VBA the rest of the text on that line is a comment meant for human readers. Most macros include a description at the top that explains the function of the macro as well as any special considerations. We start our macro steps on the empty line.

Capitalize the first word of the sentence

Then to carry out the capitalization, we will need the Case property of a valid VBA Range which means we need to identify the range of the first word of the current sentence.

What are the macro steps?

The manual steps above serve more as a guideline of important elements than as a sequence of steps for a macro. Until we get used to various VBA concepts, the differences between VBA and the manual approach can be a brain teaser. VBA sees the document internals, so it works differently. In practice, we often identify the associated document elements we want to modify and then identify them using the related VBA objects. If you plan to write more than a few macros, the benefits of thinking more like VBA is worth the effort since it sees the document internals, and it can do things we can’t quite replicate directly.

What steps are good for a VBA solution to our capitalization task?

  1. Get the first sentence range
  2. Identify the first word range of that sentence range
  3. Set the Case property of the word's range to capitalize it

As a bonus, these steps do not modify the extent of the current Selection, so they leave the insertion point in place or initial selection intact. We can just keep working.

Identify the first word range

The task is easy, but it takes several references to get the first word of the current sentence.

Declare a working range variable

It is convenient to declare a working range variable, so we can tweak the range of the first word based on the nearby punctuation.

Dim rWord As Range

We declare most variables in VBA with the Dim keyword, and "As Range" tells VBA what type of data the variable will store. I usually precede range variables with a lowercase "r" to remind myself what type of variable it is. If only one working range exists in my own macros, I'll often just call it "r" for brevity, but this variable is called rWord for a bit of extra article clarity.

VBA doesn't require variables to be declared by default, but it's a good habit as your macros become more complex. Being more specific with any variables is clearer, and it helps prevent unintended consequences. If you want to force yourself to do so (which I do), add a line with Option Explicit at the top of the macro file.

Get the first sentence Range

We start by identifying the current sentence using the Sentences collection of the Selection.

Selection.Sentences ' Not done ...

We need the range of the first sentence, so we use the collection's First property.

Selection.Sentences.First ' Still not done ...

The Sentences collection stores the ranges of the sentences (unlike Paragraphs or some other collections which store objects of that specific type), so the First property refers to the actual sentence range. If the initial Selection spans multiple sentences, this identifies just the first one. Even partial sentences are included in the collection, so this reference works even if the macro starts with an insertion point or if only part of the first sentence is selected.

Get the first word range

In order to avoid a mid-sentence capitalization issue (see the gotcha below), we can narrow our range to just the first word of the sentence. We've already identified the first sentence range, so we need its Words collection.

Selection.Sentences.First.Words ' Almost there ...

The Words collection contains all words in the sentence, but just want first word which we get using the First property of the Words collection.

Selection.Sentences.First.Words.First

Like a sentence, a word reference is just a document range, so this refers to the range of the first word of the first sentence.

Do we need both collection references?

We cannot just refer to the Words collection of the Selection directly.

Selection.Words.First ' Does not work for this macro

Referring only to the Words collection does not work for this macro because it would return the first word of the Selection not the first word of the first sentence.

Example document text

In this text, the insertion point precedes the word "document". We want a range reference to "This" for the first word of the sentence, but directly referring to Selection.Words.First would return the range for the word "document" instead since it is the first word at the current Selection position.

Not what we want.

This fits in the mold of better understanding how VBA works. By referring to the Sentences collection first, we ensure we're getting the first word of that sentence range regardless of where the Selection is located in the sentence. A similar argument applies if the macro is run with an initial selection.

Assign the first word range

Now we assign the first word range to our working range variable.

' Store the range of the first word of the sentence
Set rWord = Selection.Sentences.First.Words.First

We need Set because a range is a VBA object not just a value. Otherwise, we use an equals = sign like other assignments. This works because the First on the end returns a word range (not its document text), so we can assign it to a range variable. Both types agree.

Allow double quotes and parentheses

As a writer, I prefer that my macros work as naturally with double quotes in dialog as regular text. In fact, the case property assignment (see below) will not work (as in nothing will happen) if the "first word" begins with a double quote since upper and lowercase have no meaning for punctuation marks.

If we're already excluding a double quote, it's a simple task include a left parenthesis or a left square bracket. The latter are sometimes convenient in other documents.

Trim the starting punctuation marks

We essentially need to trim the desired punctuation marks from the start of the word range. The most general method to trim characters from the Start of a Range uses the MoveStartWhile method of a range.

rWord.MoveStartWhile ' Not done ...

MoveStartWhile requires a character set defined as plain text which are characters to be removed from the Start range.

Trim grouping symbols

The left parenthesis and left square bracket would be "([" as plain text, so we assign this to the Cset option using a colon equals := symbol.

rWord.MoveStartWhile Cset:="[(" ' Still not done ...

This command keeps moving the Start position while any of the characters in the Cset option are found. As soon as it finds any character not in the set, it stops. The default direction is forward by any number of matched characters which is what we need for this macro, so we can omit the Count option.

Trim double quotes

Similarly we need to remove a left double quote or a straight double quote. Unfortunately for our macros, a left double quote character is also used to define plain text strings like "abc" on Mac and Windows systems.

The easiest way to handle this is to refer to the character number through a special function ChrW(…). Each character has a special number from a particular Unicode character table. We "pass" this number to the function to get the equivalent text character.

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

We include both left and straight double quotes since Word sometimes does not catch and convert the keyboard straight double quote to a "curly" left double quote.

Adding these to Cset looks like:

rWord.MoveStartWhile Cset:="[(" + ChrW(8220) + Chr(34)

We used a plus + sign to add the plain text together (called concatenation). This just smooshes them together into one string which is what the Cset option needs. An ampersand & also works (slightly differently) for concatenation, but I prefer the plus notation since it resembles regular numeric addition.

Change the case

Every valid range has a Case property that controls the case of the word(s) in the range (more like a method than a property), so we now refer to the Case property of the first word range.

rWord.Case ' Almost there ...

Assign the word title case wdTitleWord, from the case constants table, to the range to capitalize the word.

rWord.Case = wdTitleWord

We assigned the Case property using an equals "=" sign since it is stored as a numerical value. The word title would work the same as the sentence title value wdTitleSentence in this macro since the range only spans a single word.

Cycle capitalization?

We could cycle the capitalization of the first word of the sentence similar to how the standard Word keyboard shortcut Shift+F3 acts for individual words, but I almost never want to do that. If that sounds interesting to you though, change the Case constant assignment to wdNextCase.

MyRange.Case = wdNextCase

The case constants have some additional features, but we will move on with the current macro.

Are we done?

We referred to the first sentence and first word ranges rather than directly manipulating the Selection, so no changes were made the Selection. Thus, we do not need to take any other action after the capitalization to adjust the Selection position. The rWord range variable disappears when the macro ends which doesn’t matter because we don’t need it any more.

Any gotchas?

What could go wrong in the macro?

Starting selections?

Many text-oriented macros assume the macros begins with an insertion point in the document, but we should always consider what happens if a selection exists when the user runs the macro. Does it matter here?

We’re not deleting any text or reorganizing content. We specifically refer to the first sentence of the Selection. We're also not changing the Selection other than capitalizing a single word, so an initial selection should not cause any problems.

Mid-word capitalization issues

We're using wdTitleWord to correct the case of the first word of the sentence range. This usually works as expected, but a small problem exists. Some words have a different capitalization like USA or a possible variable name FirstCharacter. Word understands USA and will not change the abbreviation, but it does not know the FirstSentence name. Its capitalization will be changed to a regular-ish word firstsentence.

Ughhh.

It's not a huge problem, since most novels will not contain many such words, if any. Moreover, our finished macro only adjusts the capitalization of the first word, so we only encounter a problem then. If the unintended mid-word case change occurs for those words, it is annoying and even counterproductive, but given the constraints, it should be a rare occurrence. Updating the proper capitalization information seems to require more than just adding the word to an accessible Word dictionary. Given the relative rarity of the problem, we will let it be.

Final sentence capitalization macro

Putting the steps together, our finished macro is:

Sub CapitalizeCurrentSentence()
' Capitalize the first word of the current sentence
Set rWord = Selection.Sentences.First.Words.First
' Remove double quotes or parentheses from beginning of the sentence
rWord.MoveStartWhile Cset:="[(" + ChrW(8220) + Chr(34)
rWord.Case = wdTitleWord ' Just the first word
End Sub

I assigned my variant to Option+F3 in Word for Mac or Alt+F3 on Windows mostly because the standard Word keyboard shortcut to change the case of the current word (or words in a selection) is Shift+F3. I actually don't like this shortcut since it is a little awkward to tap quickly, but it is consistent and easy to remember, and I haven't found a better one yet.

This macro is only saving two steps, but those little steps add up over time, and it’s just nice not to have to do them manually. The first word could still experience mid-word capitalization issues if it is a special word that Word does not recognize, but this version of the macro avoids any mid-sentence capitalization issues.

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.