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

Insert new paragraph

Word • Macros • Editing
Peter Ronhovde
20
min read

We create another macro in the mold simple but useful editing tools. We will insert a new empty paragraph above or below the current paragraph with a keystroke.

Thanks for your interest

This content is part of a paid plan.

Insert a new empty paragraph

We create another macro in the mold of targeting simple but repetitive editing tasks. We'll insert a new empty paragraph above or below the current paragraph just waiting for your new text.

What?

Another one of these? Isn't that what the Return key is for?

Yeah, but I'm talking about doing it faster.

Example of quickly adding a new paragraph below the current one
Example of quickly adding a new paragraph below the current one

This stealth macro sneaks up on you with how useful it is. Tap. Done. Just type.

For two or three lines, these macros are subtler than they seem at first glance, so don't skip the details if you're reading along. In the improved version at the bottom, we also conveniently apply an anticipated paragraph style.

What are the manual steps?

If we add a new empty paragraph above the current one manually, what do we do?

  1. Move to the beginning of the paragraph (perhaps with Control+Up or Command+Up arrow or use the mouse which is slower)
  2. Tap Return to create the empty paragraph
  3. Press the up arrow to move to the empty paragraph
  4. Apply the correct paragraph style, if needed (optional)

That's three or four steps depending on the current document context which is why I keep mentioning simplifying repetitive tasks into a single shortcut. Instead, just tap Command+Control+Return (or whatever Word for Windows shortcut you wish) and start typing.

Create the empty macro

A previous article covers creating an empty macro using the ribbon or menu options. Create a pair of empty macros something like:

Sub NewParagraphAboveCurrent()
' Insert a new paragraph above the current paragraph

End Sub
Sub NewParagraphBelowCurrent()
' Insert a new paragraph below the current paragraph

End Sub

The single quote indicates to VBA that the rest of the text on that line is a comment meant for us humans. VBA ignores all text after a single quote unless it's inside double quotes. We begin our macro steps on the empty line below the comment.

Working with VBA object thingys?

Many practical document elements such as paragraphs, styles, or a selection have a corresponding "object" thingy for us to reference in VBA. Each has associated data (called "properties") and actions (called "methods") that allow us to track and manipulate them as well as any associated document content. Often, the VBA object goes by the same name only capitalized.

What is a Selection?

For us humans, the selection (lowercase s) is intuitively a span of document content in Word. Typically, we do not consider an insertion point (the location of the blinking I-bar) to be a selection, but in VBA, they are represented by the same thing since an insertion point is just an empty selection.

The Selection (with a capital S) is an object in Word VBA which represents a typical document selection as seen on screen; however, it is more general since it includes methods that allow us to control it in the document. A Selection roughly corresponds a range of document content, but only one Selection exists per document since it represents what we manipulate on the screen.

What is a Range?

A Range (capital R) is VBAs representation of a span of document content. They are invisible to the user unless we specifically select them in a macro (when it just becomes the document Selection) or use them to manipulate some document content. In essence, a Range is defined by Start and End positions in the document, but it also contains other properties and methods that allows us to manipulate it or the corresponding document content (see our introductory article for more information).

What is a Paragraph?

In VBA, a Paragraph (with a capital P) is VBAs representation of the same fundamental writing structure. It corresponds to a specific content range in the document literally ending with a paragraph marker. In order to properly track and manipulate them in Word, a VBA Paragraph also has other properties and methods.

Inserting a new empty paragraph before current

What do we need in VBA terms to automatically insert a new empty paragraph? We'll start by creating a paragraph above the current one.

Get current paragraph Range

We first access the current paragraph through the Selection as we've done before. We then refer to its Paragraphs collection.

Selection.Paragraphs ' Not done ...

We specifically want the first paragraph of the collection, so we refer to its First property.

Selection.Paragraphs.First ' Still not done ...

This is a Paragraph (with a capital P) meaning it is a VBA object, but we need the corresponding document content range (perhaps strangely, a Paragraph does not have the needed method to insert a paragraph), so we refer to the Paragraph's Range property.

Selection.Paragraphs.First.Range

We’ve used this before for things like deleting the first paragraph, but we're doing something different this time.

Using the first paragraph range for this macro only means we need to know where it begins. The macro works just as well even if the user runs it with an initial selection.

Insert the paragraph break

Insert the paragraph break before the current paragraph by referring to its Range InsertParagraphBefore method.

Selection.Paragraphs.First.Range.InsertParagraphBefore

Move to the new paragraph

We need to stop and fix a VBA pothole. We want to move up to the new paragraph, but if we tried the obvious MoveUp method:

Selection.MoveUp Unit:=wdParagraph ' Not used

We'll limit the command explanation since we're not using this approach. The default move Unit is a line, so we instead used the paragraph unit from a list of document Units with the Unit option.

It almost works … but it puts the insertion point in the wrong place in a special case.

Beginning of paragraph problem

Using the MoveUp method would work everywhere except for the special case of starting at the beginning of the paragraph. We end up on the previous line because the inserted paragraph will precede the insertion point. This behavior is standard for VBA ranges, but it causes a problem here because we get a different final position depending on where we start within the paragraph.

Cannot just collapse the Selection (aside)

If you're getting used to VBA, you might think something like collapsing the Selection would work. It's often an easy way to effectively "move" the insertion point.

Selection.Collapse ' Does not work in this case

With a range variable, the new paragraph would be at the beginning of the range (sounds good so far), but it does not work in this case because we're not working with an assigned range variable. We've accessed the paragraph range through the Paragraphs' collection of the Selection. We could create and assign a range variable, but an easier, and probably more elegant, method exists that works for all cases.

Starting position solution

One way to solve the inconsistent result based on the starting position is to just move to the start of the paragraph before doing anything else. We use the StartOf method which is designed exactly for such a task.

Selection.StartOf ' Not done ...

StartOf ensures we have a consistent starting position because it will not move any farther back in the document even if we begin the macro with the insertion point at the start of the paragraph. This move also automatically collapses the Selection by default, so we're also sure about the spanned content range (none).

The default move Unit is a line, but this command works with a list of document Units, so we need to tell it to move by a paragraph instead using the Unit option.

Selection.StartOf Unit:=wdParagraph

This looks like we're mimicking a manual approach by beginning with a jump to the start of the paragraph, but it's solving a small logical problem instead.

Insert a new empty paragraph after current

We need to make a few tweaks to modify the above macro to insert a new paragraph below the current one.

Last paragraph tweak

Instead of using the First paragraph of the Paragraphs collection as we did above, we can identify the last paragraph using the Last property of the collection.

Selection.Paragraphs.Last ' Not done ...

The we get the range of the paragraph as before.

Selection.Paragraphs.Last.Range ' Still not done ...

Referencing the last paragraph is not strictly necessary, but it's a nice tweak that makes it a tiny bit more intuitive. It also does not affect the result of the macro regardless of whether we start with just an insertion point or a selection of any size.

Insert the new paragraph

Add the paragraph using the InsertParagraphAfter method.

Selection.Paragraphs.Last.Range.InsertParagraphAfter

Move to the new paragraph

We want to move down to the new paragraph, so we're ready to start typing on the empty paragraph. The MoveDown method does exactly this.

Selection.MoveDown ' Not done ...

But the default move Unit is a line, but this command also uses a list of document Units, so we need to tell it to move by a paragraph.

Selection.MoveDown Unit:=wdParagraph

This move automatically collapses the Selection after the paragraph was inserted. It also works correctly no matter what our starting position is in the initial paragraph because the new paragraph is always one paragraph below it. Even if an initial selection exists, the new paragraph is one below the last paragraph.

EndOf (apparent) idiosyncrasy

If you're getting a little used to VBA and have been following other articles, it might be tempting to use the EndOf method in this case instead of MoveDown:

Selection.EndOf Unit:=wdParagraph ' Does not work for all cases (not used)

Strangely (at first), the EndOf method does not work if we begin this macro with the insertion point at the start of the current paragraph. The new paragraph will be inserted at the proper position, but the EndOf method will not move to it.

Why?

Because EndOf detects that it is already positioned at the end of the previous paragraph, so it will not move.

Ughhh.

Makes sense when you think about it, but it's a little off putting at first. We must resort to the MoveDown method instead.

Any gotchas?

What could go wrong?

It's common to work through the main logic based on the normal case, but we need to consider the edge cases also. For a macro like this one working with paragraphs, we're concerned with the initial insertion point position or selection. The basic case for the initial status when the macro is run includes:

  • Insertion point in the middle of paragraph (most common case)

Special cases for manipulating paragraphs include.

  • Is any text selected?
  • Beginning of paragraph
  • End of paragraph

The main problem is working around a slight asymmetry in how content (a single paragraph marker in this macro) is inserted differently at the beginning or the end of a range (also the Selection since it's like a range). This problem occurs even when working with distinct range variables. The way VBA does it is not wrong, per se, but it does cause some small logical issues we must understand and work around them. The quirk will return to bother us again in other macros.

What about a starting selection?

This is a common special case to think about, but the StartOf method both automatically collapses the Selection and intuitively positions the final insertion point at the respective new empty paragraph. In the second macro, we actually use the ending paragraph range of the selection to properly insert the new empty paragraph, so there is still no problem. The MoveDown method then collapses the Selection, so we're safe in either macro.

What about the beginning of the paragraph?

The StartOf command was specifically included to solve the final position discrepancy with the beginning or middle of paragraph (see above comments).

What about the ending of the paragraph?

Neither macro has problems when the insertion point is initially positioned at the end of a paragraph because we are always clearly to the left of the paragraph marker and "inside" the paragraph. For practical purposes, the end position is effectively the same case as starting anywhere inside the paragraph text.

Finish the macro

Now we just put the two commands together for each version. For a new paragraph above the current one:

Sub NewParagraphAboveCurrent()
' Insert a new empty paragraph above the current one
' StartOf avoids a final position ambiguity based on the starting position
Selection.StartOf Unit:=wdParagraph
Selection.Paragraphs.First.Range.InsertParagraphBefore
End Sub

I assigned this one to Command+Control+Return in Word for Mac. Using the PowerToys app, I also tweaked the shortcuts to assign this macro to Alt+Win+Return in Word for Windows. VBA macros in Word cannot normally be assigned using the Win key.

For a new paragraph below the current one:

Sub NewParagraphBelowCurrent()
' Insert a new empty paragraph below the current one
Selection.Paragraphs.First.Range.InsertParagraphAfter
Selection.MoveDown Unit:=wdParagraph
End Sub

I assigned this macro to Control+Option+Return in Word for Mac and Control+Win+Return in Windows (see comment above about how this is accomplished).

If you want to further apply the paragraph style, keep reading below. It only takes an extra (long) line.

Lessons from the macros

Both macros have position subtleties that are not obvious at first. We could have implemented a more complicated scheme where we use a conditional statement to check the beginning of the paragraph compared to the current insertion point position and make a decision based on what we find, but both macros are simple and elegant.

Implementing these macros are an example of how we cannot naively adapt previous macros and assume everything will always work out exactly the same.

Adding an intuitive paragraph style

The simplicity of the above macros compared to how convenient they are in practice is wonderful, but I further tweaked my own versions to assign the new paragraph style based on expected style from the prior paragraph. This adds some extra intuitive behavior saving an extra step where we can, and it doesn’t take much work to implement.

Change the style of the new paragraph

Why worry about it?

It’s definitely not essential since the new paragraph will inherit the style of the current one, and that works fine about 98.214% of the time. However, it’s handy to control the exact style since you might run the macro while in a heading paragraph, but we don't want the new paragraph to also be a heading.

As scene in the modify style dialog, we want to lean into the "Style for following paragraph" setting every Style has.

Modify Style dialog showing the Style for following paragraph setting
Modify Style dialog showing the Style for following paragraph setting. We wish to apply this style using VBA.

Each style can set this the same as or different from the current paragraph style. The issue is VBA will not automatically apply this "next paragraph style" like Word does when we manually tap Return at the end of a paragraph. We need to detect and apply the desired style within the macro.

Setting a paragraph style

Similar to what we did with the Selection earlier, we'll reference the First paragraph of the Paragraphs collection.

Selection.Paragraphs.First ' Not done ...

This works for our current macro because we are sure its finishing with the insertion point positioned on the new empty paragraph. We can then set the style of a paragraph by referencing its Style property.

Selection.Paragraphs.First.Style = "Style Name"

As we've done here, the most common approach is to just provide any valid style name in double quotes using an equals = sign. We would normally validate the style since they are finicky at times in VBA, but we're getting it from an existing valid style (see below), so we should be safe.

Since we just have an insertion point at the end of both of the previous macros, it’s easier to just set the Style property of the Selection as shorthand.

Selection.Style = "Style Name"

We could also assign a valid Style variable or even a value from a table of built-in style constants. Now we just need the style.

Setting the expected style

Both earlier macros end on the new paragraph, so we can refer to the previous paragraph the same way. Hold on because this one gets a little complicated.

Which style do we use?

The macro should respect the Next Paragraph Style property from the respective Style definition.

Selection.Style.NextParagraphStyle ' Something like this

When inserting a new paragraph before the current one, we will use the previous paragraph’s next paragraph style. Say that three times real fast.

However, before we can do that, we actually need to reference the previous paragraph to get the correct style.

Get the previous paragraph

We get the previous paragraph based on the current Selection position using its Previous method.

Selection.Previous Unit:=wdParagraph ' Not quite ...

The Previous method takes a Unit like several of the other commands we’ve used earlier. The default Unit is a character, so we need to specify a paragraph by assigning wdParagraph to the Unit option.

Getting the style property

We must include the Unit option assignment in parentheses because we need to reference (with a dot .) the Style property after we've identified the previous paragraph.

Selection.Previous(Unit:=wdParagraph) ' Not done ...

Now we can refer to the Style property.

Selection.Previous(Unit:=wdParagraph).Style ' Still not done ...

I'm not a fan of how this makes our macro look more like real programming, but it saves us from having to define an extra variable. It's a preference, but the more concise (even if long) command seems easier in this command.

Get the next paragraph style

We can finally refer to the desired next paragraph style which we'll apply to our current paragraph.

Selection.Previous(Unit:=wdParagraph).Style.NextParagraphStyle
Assign the next paragraph style to the current paragraph

We can now (finally) assign the desired paragraph style to the current paragraph using the Selection's Style property.

Selection.Style = Selection.Previous(Unit:=wdParagraph).Style.NextParagraphStyle

This is extended content, so I think it is useful to see an example of how we can chain the references to do more complex things with fewer steps. If you don't like how long the command is, see the following alternative version which adds an extra two steps to accomplish the same task.

Alternative paragraph style assignment (not used)

For those that don't like the snaky style assignment, we could instead define an extra variable and add a couple lines to get the job done in a more steppy fashion. I will not explain every line.

Dim PreviousParagraph As Paragraph ' Not required but clearer
Set PreviousParagraph = Selection.Previous Unit:=wdParagraph
Selection.Style = PreviousParagraph.Style.NextParagraphStyle

I felt like the extra two steps did not make enough difference in clarity. These lines weren't as nice as the more concise command, but if you like this longer version, replace the style assignment with these lines.

Finish the macros

Now we just put the commands together for each version. For a new paragraph above the current one, we have:

Sub NewParagraphAboveCurrent()
' Insert a new empty paragraph above the current one
' StartOf avoids a final position ambiguity based on the starting position
Selection.StartOf Unit:=wdParagraph
Selection.Paragraphs.First.Range.InsertParagraphBefore

' Finally set the style of the new paragraph
Selection.Style = Selection.Previous(Unit:=wdParagraph).Style.NextParagraphStyle
End Sub

I assigned this macro to Control+Option+Return in Word for Mac. VBA macros in Word cannot normally be assigned using the Win key, so I used the PowerToys app to tweak the shortcuts and effectively assign this macro to Alt+Win+Return in Word for Windows.

If you really want to be super-duper careful, see the new baby bug we squash below.

For a new paragraph below the current one, we get:

Sub NewParagraphBelowCurrent()
' Insert a new empty paragraph below the current one
Selection.Paragraphs.First.Range.InsertParagraphAfter
Selection.MoveDown Unit:=wdParagraph

' Finally set the style of the new paragraph
Selection.Style = Selection.Previous(Unit:=wdParagraph).Style.NextParagraphStyle
End Sub

I assigned this macro to Command+Control+Return in Word for Mac or Control+Win+Return in Windows (see above comments on using the Win key for Word macros).

Further improvements

Both macros make three changes to the document: add a new paragraph, reposition the insertion point, and change the new paragraph style. Adding an undo record would be convenient, so the changes may be reversed as a single step when needed. However, tread with care since undo records can cause genuine problems with content if they are not properly implemented.

A sibling variation adds a new paragraph at the end of the current heading. I use it to quickly append novel notes as I’m developing ideas, but it also works to quickly jump to the end of the current scene or subscene heading to just start typing.

Squash a new baby bug

Referring to the previous paragraph to get the desired paragraph style adds a subtle bug for the NewParagraphAboveCurrent macro.

Ughhh. What's wrong?

If the macro is run when the insertion point happens be located in the first paragraph of a document, no previous paragraph exists.

In the interest of simplicity, we ignored this rare occurrence earlier; but if you insist, as I usually do with my own macros, we can add a check for a valid style before making the style assignment. I will not explain it much for brevity, but the crux of the problem is the previous paragraph reference will result in Nothing (an invalid or otherwise unassigned object) if the paragraph does not exist.

For completeness, we copy the initial steps for this revised macro.

Sub NewParagraphAboveCurrent()
' Insert a new empty paragraph above the current one
' StartOf avoids a final position ambiguity based on the starting position
Selection.StartOf Unit:=wdParagraph
Selection.Paragraphs.First.Range.InsertParagraphBefore

' Catch and correct first paragraph of the document case
Dim NewParagraphStyle As Style ' Not required but clearer
' Attempt to get the next paragraph style of the previous paragraph
NewParagraphStyle = Selection.Previous(Unit:=wdParagraph).Style.NextParagraphStyle
If Not NewParagraphStyle Is Nothing Then
' Style is valid, so set the new paragraph style to it
Selection.Style = NewParagraphStyle
End If
End Sub

Basically, we only set the new paragraph style if it is valid. The revised macro to catch this rare special case is bloated. It took more lines to catch and correct the special case than the rest of the macro required. For presentation purposes, the earlier macro is nicer. I would use this version but pick the simpler one if you're willing to take the tiny risk.

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.