More targeted navigation in your manuscripts reduces clicking around with the mouse making both writing and editing easier and faster.
One of the little tools toward that goal is jumping to an empty paragraph. I created it on a whim one day, but now I use it (actually its big brother) often when writing.
Thanks for your interest
This content is part of a paid plan.
Create the empty macro
A previous post covers creating an empty macro like the one shown below. When you’re done, you’ll have something like:
We'll need one for the next and another for the previous empty paragraph in the document.
The single quote tells VBA the rest of the text on that line is a comment meant for human readers. We start our macro steps on the empty line.
What about the “goto last edit” shortcut?
Yeah, that technically exists as Shift+F5 (cycle between last several edits), but it often counts individual characters as distinct “edits.”
While I find the idea intriguing, in practice Word’s implementation is only useful in isolated circumstances.
Basically, you can’t have made any significant changes, as in typing a single word, before trying to jump back to the previous edit location.
We can’t emulate this kind of behavior at the macro level (macros only know the state of the document while they are running), but we can create some targeted improvements to help us navigate our documents faster.
How can we jump to an empty paragraph?
This use case usually pops up for me when I’m working in a novel, and I move somewhere else to add a quick inline note. (Am I the only one that can’t stop myself from editing or adding notes as I write?)
This macro (or its big brother in the extended content below) is one of those that helps me quickly jump back to where I was working.
So how do we find the next empty paragraph?
Using Find (a simple introduction)
We need the Find method of the Selection (actually any Range object can use Find also).
There are a lot of parameters corresponding to all the options you see in the regular or advanced Find dialogs, but we’ll keep mostly to the simpler search options for now.
We access the Selection's Find method like so:
We do the actual find operation by telling it to “Execute”
What are we searching for?
We can set the search text using the FindText property.
Don’t forget we use := to assign arguments when necessary in VBA commands.
Most text is included in double quotes when you give them as arguments in VBA, but there are exceptions for some special characters. This happens to be our case in this macro.
How to find an empty paragraph?
Think about what marks an empty paragraph …
Specifically, we’ll look for two paragraph markers side by side.
On paper, we just skip to the next line and start writing, but a paragraph marker is a special character in Word. We can’t literally put it inside double quotes, so we have to use the Word constant vbCr which indicates a Visual Basic (the “vb” part of the name) constant for a carriage return.
Searching for two of them together would look like:
We just “add” (called concatenate) the characters together to search for two side by side in the document.
Collapsing the selection
If you recall, when we Execute a Find operation in Word using the regular dialogs, Word automatically selects the text when it is found.
In our use case today, we’re just positioning the insertion point at the empty paragraph, so we don’t want the empty paragraphs selected when the macro is done.
So in our macro, we need to collapse the Selection after the search.
Repositioning the cursor
Unfortunately, collapsing the Selection like this will leave us at the end of the previous paragraph relative to the empty paragraph we found. After the collapse, we also need to move down a line.
The default Unit for MoveDown is by line which is fine for us here.
If you remember our other macro examples, we can also collapse the Selection toward the End (using Direction:=wdCollapseEnd) instead of the beginning, but it doesn’t save any steps in this macro since the insertion point would finish on the next paragraph. We would then need to move up at this step instead.
What if it doesn’t find an empty paragraph?
Oh, we have to think about that?
Actually if it doesn’t find an empty paragraph, nothing happens with the find operation, but then we experience a side effect of the included included steps. The cursor would still move down one line.
Not really a problem, but it would look a little odd while you’re editing when you’re expecting to jump to an empty paragraph.
Was the search successful?
We really should have the macro only move down a line if an empty paragraph is found.
We can check for this using the Found property of Find.
This property has a true value if your search text was found but false if nothing was found.
Conditional check on Find Found
Sounds perfect for a conditional If Then check. We’ve introduced it a few times before this, so I’ll jump right to how we use it.
We now only collapse the selection and move down a line if the Find step actually finds the search text.
What about searching backward?
Of course, sometimes you’ll want to search backward in the document, and the Find method has a Forward parameter.
It defaults to True (search forward in the document, of course), but you can set it to False to search backward.
Any gotchas?
Actually if you search backward in the text and then try to use the forward version, the Find method remembers the Forward setting to be False, so it’s safer to just give the direction explicitly for both macros.
In fact, it’s probably safer to give most of the related arguments for Find operations each time, but we’ll save that for the extended content below since it involves talking about some other stuff.
Final macros
The final versions of the macros are relatively simple with one for each direction with steps almost identical to each other.
Searching forward in the document:
If you've come straight to the final macros, make sure you read above about why we specified Forward as True explicitly.
Searching backward in the document:
I assign these to keyboard shortcuts Command+Control+Space and Control+Option+Space, respectively, in Word for Mac.
While you might be skeptical of its use, in practice, I often ensure it’s utility by leaving an empty paragraph where I’m working, so I know I can always quickly jump back there almost immediately.
Personal variations
One of the cool things about macros is you can very much tailor them to your preferences, making Word work your way.
Here are some improvements I’ve made to my own variation of these macros.
Incomplete paragraphs
My personal version extends this idea to search for incomplete paragraphs (mostly those without ending punctuation). There are some caveats for styles like heading paragraphs, but I prefer this generalization of the idea.
A simplified version of this extension continues in the extended content below.
Excluding or targeting certain paragraph styles
A more thorough implementation might exclude certain paragraph styles like heading paragraphs which usually don’t have ending punctuation marks and would match the search text. (As I write, I usually insert many inline novel notes with specific paragraph styles which I want to skip when I’m working on the actual text.)
Alternatively, you might like to target certain paragraph styles, like Body Text in your novel, before committing to moving the insertion point.
There is an important gotcha to make it these restrictions work correctly since the obvious approach doesn’t work as expected in some cases.
Connected to this customization, I also have some logic to further detect whether I’m in a novel or a notes document and search differently in each case.
It’s a little more complicated than it may seem at first read, so I’ll share this stuff later in members’ content.
Limited search range
My version also limits the search range to a few pages since I tend not to like the idea of jumping to a random location in my novel where I forgot to finish the text line.
I suspect this behavior is a preference that is probably not shared by the majority of readers, so I won’t go through the details unless I get a lot of interest in it.
Improvements
I now introduce a simplified variant of my personal implementation of this macro concept.
How can we find an incomplete paragraph?
This may seem like a tall order. With the seemingly unlimited number of ways you can not finish a line, how do you detect any of them?
Setting more search parameters
We’ll need to specify more Find arguments to be safe which introduces the concept of With statements.
Essentially a With statement groups a set of related assignments or commands using the same object.
The .SomeProperty inside the With is equivalent to using
The With block just gives us a nice shorthand for repeated property or method references.
It’s technically ever so slightly faster, but in practice, you’d almost never notice the time difference.
The real advantages are just better organization and presentation of your steps and assignments, and you don’t have to repeat the SomeObject.SomeProperty reference over and over.
With blocks can include other commands, but generally it's probably better for your macro organization and clarity to limit any commands or assignments unrelated to the referenced object. It's your choice though.
Using With with Find
For today, we’re mostly setting search parameters for the Selection.Find method.
There’s a lot here, and I even left some options out for clarity. Several are intuitive doing what they say. I tend to include most of these just to be safe since Find remembers the previous search options like your regular Find dialog when you use it.
Each reference of a property must start with the . just as if you had typed it all together.
We don’t have time to talk about everything right now, but here are a few specific parameters relevant to today’s macro.
Most importantly, we need MatchWildCards to be True for our specific incomplete paragraph search.
One might think IgnoreSpace = True would be useful for finding incomplete paragraphs, but it is redundant with our fancier search argument below.
Indicating a target search style using .Style = “Some Style” doesn’t work in this macro for all cases since our search sometime spans an empty paragraph which may have a different paragraph style than the previous paragraph.
Finding incomplete paragraphs
Since we’ve set MatchWildCards, we can create a fancier search text. In fact, Word’s search text and search options are more robust than most people realize.
But the ending character could be anything?
How do we to reference any character?
For this macro, we want paragraphs that end with just letters, numbers, or a space but no punctuation marks.
Advanced search options
Typical, more commonly known, wildcards for searches include an asterisk “*” for any text after that point in the search string. “?” tells Word to allow any character for that specific character location in the search string. And more.
But we can get more specific than these allow alone. If you open the Word Advanced Find search dialog, you’ll see a whole list of more detailed search options.
We need a way to do this in VBA.
Finding any character
Specifically, we want any of several characters. For that, we use square brackets “[a-z]” in our search text string. This tells word to look for any of the characters in the range a-z which means any character of the English alphabet.
Since our search arguments above included MatchCase as False, the character range [a-z] also covers upper case English alphabet characters.
Now include numbers and a space to get a main part of the search string “[a-z0-9 ]”. (For any who find this notation familiar, it is similar to but not the same as search operations performed using RegEx.)
What’s not included are punctuation marks.
For clarity, the first character of the search text must include at least one of the characters in the brackets.
Including paragraph markers in the search text
Back in the GotoNextEmptyParagraph macro at the top, we searched for two paragraph markers using a search string vbCr + vbCr. That is, we set FindText to side by side paragraph markers as an indicator of an empty paragraph.
We still need the vbCr characters, but in this case the first one should be optional for incomplete paragraphs.
How do we combine this with the other optional characters above? We add the first one to the optional list and a second one after it like so:
Unfortunately, we need to add the first vbCr inside the square brackets to make it one of the optional set of first characters. This is why we have to add the right square bracket “]” after the first vbCr.
Then we add the second vbCr outside the brackets making it a required second character.
Paragraph marker side notes
There is another way to set the FindText search string using ^13 in place of vbCr for the paragraph marker:
It’s not horrible. Just a little messier. On the other hand, everything is in one set of double quotes, so maybe you prefer this version. It’s actually what I use.
Technically, Microsoft also allows a “^p” to indicate a paragraph marker in the FindText search string, but it doesn’t quite work as expected here since it can’t be used with MatchWildcards set to True.
I don’t know why Microsoft restricted its use like this, but in this macro, we have to use wildcards to match incomplete paragraphs, so we’re stuck with using one of the other constants.
Executing the new search
Now our search command would look like:
This is a little long and messy, so we can improve the presentation using a variable.
In general, messy code is hard to read, so you can often help yourself when you come back to it later by cleaning it up a little now. Word and VBA don’t care though. Your tolerance for what you consider “messy” will improve with experience.
Reviewing the search text
Let’s break this search text down again just to be as clear as possible.
This first part of the search text in square brackets “[a-z0-9 ” + vbCr + “]” tells Word to look for any character consisting of an alphabetic character, number, space, or a paragraph marker as the single first character match of the search.
This first character is required for a valid match.
Then the ending vbCr requires the last character of the two characters of matched search text to be a paragraph marker meaning we are always searching for the end of a paragraph.
Revised macro finish
If you test the macro, and you should, you'll notice that the finishing steps of collapsing the Selection and moving down don't work correctly for an incomplete paragraph.
What changed?
For an incomplete paragraph, the original MoveDown command now moves to the first line of the next paragraph. Why?
There is no empty paragraph to move into now.
The fix is simple: Since we only have two characters in any found text here, instead of moving down a line after the collapse, we just have to move to the right one character.
The default Unit for a MoveRight is by character.
This works for either case. For an empty paragraph, we're moving past the first paragraph marker and into the next paragraph since a paragraph marker counts as a character. It just happens to also divide paragraphs (and store formatting information in Word).
For an incomplete paragraph, we're moving past first character which happens to be a letter, number, or a space.
Don't over complicate things
It's worth a teaching moment to take an aside here. Don't pull a Rube Goldberg solution out of a hat to fix simple problems.
Sometimes the macro does have to be complicated, but only do that when necessary.
In the finishing steps correction above, I originally corrected it with nested conditional statements like so:
This does solve the problem, but it was at the moment I added the MoveRight step near the bottom when I realized it would solve both problems which is a good marker of a better solution.
Final macros
The final versions of the macros are relatively simple with one for each direction with steps almost identical to each other.
Searching forward in the document:
Notice we put also the Execute inside the With block of commands.
Searching backward in the document:
I assign these to keyboard shortcuts Command+Control+Space and Control+Option+Space, respectively, in Word for Mac.
Common steps comment
Notice all that changed from the Next to the Previous version was setting Forward to False to make it search backward in the document.
With all the common steps in these macros, it’s easy to see why programmers invented functions and subroutines, but that is a lesson for another day.