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

Navigate or select by punctuation more

Word • Macros • Editing
Peter Ronhovde
16
min read

I like to move around my document faster using targeted navigation, and navigating by common punctuation marks is one way to accomplish this.

Thanks for your interest

This content is part of a paid plan.

Simple Versions

If you didn’t see the earlier article covering Word VBA macros for jumping to punctuation marks in your documents, the results are below. Also refer to the first article for setup and explanation of the basic steps.

Moving

Moving forward to the next comma in the document:

Sub GotoNextComma()
  ' Jump to the next comma in the document
  Selection.MoveUntil Cset:=","
End Sub

Moving backward in the document:

Sub GotoPreviousComma()
  ' Jump to the previous comma in the document
  Selection.MoveUntil Cset:=",", Count:=wdBackward
  Selection.MoveLeft  ' End on left side of comma
End Sub

Selection

The movement macros are easily modified to allow us to select all text up to the punctuation mark by modifying the Start of End of the Selection rather than just the insertion point location.

Selecting forward in the document is done by:

Sub SelectToNextComma()
  ' Select text forward to the next comma in the document
  Selection.MoveEndUntil Cset:=","
End Sub

Select backward in the document:

Sub SelectToPreviousComma()
  ' Select text backward to the previous comma in the document
  Selection.MoveStartUntil Cset:=",", Count:=wdBackward
End Sub

You can modify the Cset character strings (characters at which the command stops the search) in each case to search for other punctuation marks or even include multiple search characters.

I’ve created variants for several common punctuation marks like periods and parentheses. Additional enhancements are covered in this article.

To be more concrete, we’ll refer to commas for the majority of the text below.

Iterating through the document

Suppose you select all text from the current edit location up to the next comma in the document.

If you tap the keyboard shortcut again. The basic macros above won’t select any additional text since the macro immediately “finds” the comma and stops the character search.

This doesn’t feel intuitive to me.

I personally like my macros in this context to jump to successive punctuation marks if I repeatedly press the keyboard shortcut like the following selection example.

Select by comma with iteration enabled

While the above macros are simple and a great place to get started, only GotoPreviousComma allows me to iterate the process as desired. That one works only because I prefer to end the macro on the left side of the comma regardless of which direction I'm moving through the document. For the others, you have to manually move past the comma before jumping or selecting to the next one.

So I want to add steps to my macros to make them behave the way I want. That’s one of the macro super powers if you’re willing to do some work up front.

The changes are mostly easy to implement. Unfortunately, there are a couple gotchas, but that’s why I’m here to help.

How do we iterate to the next comma?

The basic steps are straight forward. When the user runs the macro:

  • Detect whether there is a comma next to the current insertion point (i.e., the edit location)
  • If there is a comma immediately next to the current location, move past it by one character (or extend the selection past it for the selection macros).
  • Jump to the next comma (works whether or not a comma was detected first)

Seems simple enough …

You don’t have to write everything out like this (I’m writing an article after all), but thinking through specific steps like this might helps ensure you aren’t missing any obvious or less-than-obvious steps or other issues.

As advertised, the steps aren’t difficult, but the specifics get a little tricky when moving or selecting forward based on how Word views the text contents of empty versus non-empty selections.

That’s just how these particular commands work, so we’ll have to dig through the details a little moving forward.

Next character problem

A small issue with the steps above is determining the next character. It doesn’t seem like it should be an issue, but it doesn’t work the same way every time.

Doing some testing, we might notice the difference occurs depending on whether there is a starting selection or not.

We get different “next” characters in each case which is a problem if we want our macro to work correctly every time.

Next character method

The most intuitive method for getting the next character is probably the Selection.Next method. Let’s cover it briefly since this may be new to some readers.    

  Selection.Next(Unit:=wdCharacter).Text

This command tells VBA to “return” the next chunk of text after the Selection in whatever unit I specify. It defaults to a character, so I can leave out the Unit for our macros today.

  Selection.Next.Text

These can't be used all on their lonesome like this. We need to store them somewhere (see below).

Next Unit and Count

Along with a Unit, we could also give a Count, like Count:=3, argument perhaps if we wanted to know the third character after the Selection rather than the first, but this apply to our current macros.

One difference between this Next command and several we’ve covered previously is we wrapped the Unit argument in parentheses because we need to follow the Next method with the Text property.

Otherwise, the Next method returns a Range in the document not the text. The distinction is subtle, but we’ll cover Ranges later (they’re often a better way to solve problems in VBA macros compared to using the Selection object directly).

Storing values in variables

Back to our macro solution. Once I have the Next character, I want to store it in a clearly named variable for later reference:

  NextCharacter = Selection.Next.Text

For whatever reason, VBA uses an equals = when we are storing a value in a variable, but it uses a := symbol when we assign values to parameters for commands (like with Unit:=wdCharacter above). I would have liked more consistency, but that’s how VBA works.

Using the next character

Now that we supposedly have the correct next character after the Selection. We want the macro to skip a comma if it is at the edit location:

  ' This doesn’t work as expected if it runs when there is an empty selection
  NextCharacter = Selection.Next.Text
  If NextCharacter = "," Then
    Selection.MoveRight  ' Move just past the comma
  End If
  Selection.MoveUntil Cset:=","

We’ll cover conditions using If statements in another article, so I can’t discuss it in detail now without bogging down the (already long) solution here. Suffice it to say that it allows to to make a decision in the macro on whether to run some steps based on a condition we choose.

The above macro steps work if at least one character of text is selected (where Selection.Start is less than Selection.End in the document).

The problem ... empty selections

But it doesn't work when there is no selection (Selection.Start is the same as Selection.End).

Why?

When there is no selected text, the Next command will return the second character after the cursor location.

What?!

We get two different characters depending on whether a selection exists or not. This inconsistent behavior makes creating a reliable macro more troublesome.

Apparently, Word considers even an empty selection to contain at least one character. I’m sure they have a reason, but I find this behavior a little confusing. In my opinion, it’s more intuitive to think of an empty selection as containing no characters.

Even if it's inconsistent, it’s how VBA works, so we have to accommodate it. The solution isn’t too bad though.

Next character solution

As with many problems, there are at least two ways to solve it, and the choice is often a matter of preference. I’ll pick the method that works most consistently for the macros above. If you’re interested in other methods, let me know.

Now that we know the problem, how do we get the character immediately to the right of an empty selection?

Simple actually. Word VBA apparently assumes the first character after an empty selection is nevertheless part of the Selection text.

  Selection.Text

Note Selection.Text normally returns the entire selected text, but importantly for our purposes here, it returns the character at the cursor location when there is no selection.

Getting the next character every time

What are some fool-proof steps to get the next character in the intuitive sense regardless of whether there is a selection or not?

  • Check whether there is a selection
  • If there is a selection, get the next character with the Next method
  • Otherwise get the next character using the Selection Text
  • Store the character in either case

Now continue with the other steps mentioned earlier.

  • If the next character is a comma, move past it (or extend the selection past it for the selection variant).
  • Jump or select to the next comma as normal

What kind of selection?

To check whether there is any selected text, we have to check the "Type" of Selection.

  Selection.Type

There are several types of selections (block, shapes, tables, etc.), but we'll cover the topic in more detail later. Here we basically want to know whether or not there is a "normal" selection.

The Word constant that indicates just that is wdSelectionNormal, so we just check the Selection Type against it:

  ' Check the selection type
  If Selection.Type = wdSelectionNormal Then
    ' Do something ...
  Else
    ' Otherwise do something else ...
  End If

Sometimes it is more convenient to check if there is not a selection. Without any explanation here, the constant for that is wdSelectionIP.

There are some gotchas to watch out for, but we'll have to relegate those to a separate article.

Macro steps

In VBA, these steps look like:

  ' Get the next character regardless of whether there is a normal
  ' selection but ignore any other selection types

  If Selection.Type = wdSelectionNormal Then
    ' There is a regular selection, so use the Next method
    NextCharacter = Selection.Next.Text
  Else
    ' Assume no selection, so get the next character text directly
    NextCharacter = Selection.Text
  End If

  ' Now check whether the next character is a comma
  If NextCharacter = "," Then
    Selection.MoveRight  ' Move past the comma
  End If
  Selection.MoveUntil Cset:=","

This method of getting the next character begs for a function, but that is a lesson for another day.

For the SelectToNextComma variation the last steps instead use:

  ' Now check whether the next character is a comma
  If NextCharacter = "," Then
    Selection.MoveEnd  ' Extend End of Selection past the comma
  End If
  Selection.MoveEndUntil Cset:=","

Previous comma version?

What changes when jumping to the previous comma?

We don’t have to worry about the next character issue since the previous character is consistent regardless of whether there is a selection or not.

With that in mind, we get the previous character using:

  Selection.Previous(Unit:=wdCharacter).Text

Again, we omit the Unit within parentheses since it defaults to returning the next character.

  Selection.Previous.Text

Final Macros

Move variations

Putting the above steps together, our macro to jump to the next (or successive) comma in the document is:

Sub GotoNextComma()
  ' Jump to the next comma in the document. If the cursor is at a comma,
  ' jump to the following one (allows the user to naturally iterate through
  ' successive commas in the document).


  ' Get the next character regardless of whether there is a selection
  If Selection.Type = wdSelectionNormal Then
    ' There is a regular selection, so use the Next method
    NextCharacter = Selection.Next.Text
  Else
    ' Assume no selection, so get the next character text directly
    NextCharacter = Selection.Text
  End If

  ' Check whether the next character is a comma
  If NextCharacter = "," Then
    Selection.MoveRight  ' Move past the comma
  End If

  ' Finally move to the next comma
  Selection.MoveUntil Cset:=","
End Sub

The variant to go to the previous (or successive) comma in the document is:

Sub GotoPreviousComma()
  ' Jump the previous comma in the document. If the cursor is at a comma,
  ' jump to the previous one (allows the user to naturally iterate through
  ' prior commas in the document).


  ' Get the previous character regardless of whether there is a selection
  PreviousCharacter = Selection.Previous.Text

  ' Check whether the previous character is a comma and step past it if so
  If PreviousCharacter = "," Then
    Selection.MoveLeft  ' Move past the comma
  End If

  ' Finally move to the previous comma
  Selection.MoveUntil Cset:=",", Count:=wdBackward
End Sub

Selection variations

For the selection variations, the basic steps of the macros are the same, but we replace the move commands with MoveStart or MoveEnd variations as follows:

Sub SelectToNextComma()
  ' Select forward to the next comma in the document. If the cursor is at a comma,
  ' extend the selection to the next one (allows the user to naturally iterate
  ' through successive commas in the document).


  ' Select forward to the next comma in the document
  If Selection.Type = wdSelectionNormal Then
    ' There is a regular selection, so use the Next method
    NextCharacter = Selection.Next.Text
  Else
    ' Assume no selection, so get the next character text directly
    NextCharacter = Selection.Text
  End If

  ' Check whether the next character is a comma
  If NextCharacter = "," Then
    ' Extend End of Selection past the comma
    Selection.MoveEnd
  End If

  ' Finally select forward to the next comma
  Selection.MoveEndUntil Cset:=","
End Sub

Selecting backward through the document:

Sub SelectToPreviousComma()
  ' Select backward to the previous comma in the document. Allows the user
  ' to naturally iterate through the prior commas in the document.


  ' Get the previous character regardless of whether there is a selection
  PreviousCharacter = Selection.Previous.Text

  ' Check whether the previous character is a comma and step past it if so
  If PreviousCharacter = "," Then
  ' Move Start of Selection backward past the comma
    Selection.MoveStart Unit:=wdCharacter, Count:=-1
  End If

  ' Finally select backward to the previous comma
  Selection.MoveStartUntil Cset:=",", Count:=wdBackward
End Sub

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.