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

Toggle scene heading style from content

Word • Macros • Editing
Peter Ronhovde
14
min read

We will create a VBA macro to toggle a scene or subscene heading style from within the scene text without needing to move to the heading paragraph to facilitate faster editing.

Thanks for your interest

This content is part of a paid plan.

Toggle Scene Heading Style

Editing our manuscripts is an essential but time consuming task. Aside from just training our figurative author muscles to get better at it, we can leverage other solutions to improve the process. On the technical side, we can make it faster and easier using a combination of techniques and tools, some bigger and some smaller. Some feel faster than others. Some you just like. Today’s macro fits more on the latter end of that spectrum.

Every author will have a different approach to editing. This macro may be targeted more at my particular editing method, but I think it’s general enough for others to benefit.

The final macro depends on functions defined in two member articles.

If you prefer, you can just skip ahead to the macro … otherwise, let me explain a little bit about the background and motivation.

Organizing a novel in progress

In my heart of hearts, I desperately want to outline my novels in almost every detail before I start writing … but I can’t. Just no.

Well … I can, but it just doesn’t work for me. Not even close.

I either choke on the detailed outline and stare for days at disorganized scribbles on paper or jumbled notes on a screen. If I press forward (set of the sail stuff, right?), my novel inevitably careens away from the outline as I write while mocking my futile efforts to control the shifting winds of inspiration.

I suppose I chose to pull the anchor and let the ship drive.

My evolving story

I usually keep a decent overview of the evolving story in my head, but sometimes the details get away from me, so I eventually started inserting chapter and scene headings as I write.

This isn’t about nurturing or even hammering a three-act story structure into being. It’s about tracking the literal development of the story as it grows and evolves, so I don’t get lost in my own story after it takes a few unexpected turns.

My (literal) novel structure

Toward that end, I include Acts, Chapters, Scenes, and down to Subscenes which are derived from the standard Word Heading 1 through 4 styles, respectively. I wanted to be able to efficiently manipulate my scenes and other subdivisions as the story and the editing progresses.

What’s this got to do with today’s macro?

Don’t report me to the novel police, but I don’t necessarily finish the whole rough draft before editing some scenes. Even after I finish the rough draft, I may not edit incrementally through the novel. There may be a particular sequence that bothers or perhaps even interests me more, and I want to tackle it first.

After editing a scene, I got tired of moving to the heading and marking it as edited (using a distinct paragraph style). I just wanted to mark it done for that draft and keep editing without having to bounce around the text. While this macro isn’t the largest productivity boost, I still like just being able to mark the scene as edited and move on.

Reordering text

I’m not a fan of writing chapters as separate documents since I like to move text around. Scenes are a more fundamental story unit, and I tend to decide chapter breaks later more than earlier. Using headings in the main text makes reordering content easier as the need arises. In Word for Windows, reordering can even be done by dragging headings in the Navigation Pane (although occasional formatting issues may occur).

Extracting a running outline is easier

I also have a separate macro to allow me to easily extract the above headings along with any important novel notes into a separate document, but that is a topic for another day.

Quickly applying a scene heading style

In addition to Scene and Subscene headings, I created more editing related styles including “Scene Edited” and “Subscene Edited”. These aren’t my exact names since it evolved over time but close enough. I want to quickly mark a scene as edited without having to move there and manually apply the edited paragraph style. That is today’s macro, but it relies on two previous functions given in member content to make things easier and more robust:

We’ll leverage both functions to create a short macro to quickly toggle the heading paragraph style of a scene.

A little heading terminology

We need some common terminology. When I refer to a “heading paragraph”, I mean the first paragraph of a heading. The “heading content” is everything below the heading paragraph that is part of the heading. Thus, “heading” by itself refers to all the above.

Macro skeleton

Since the intention is to assign this macro to a keyboard shortcut in Word (not on screen), we need to create a VBA subroutine not a function (functions return a value). Our macro skeleton is:

Sub ToggleSceneHeading()
' Toggle scene heading style from within the heading content

End Sub

The Subscene Edited macro will be a trivial modification, so we’ll just work with the Scene version.

Word macros and keyboard shortcuts

Any macros assigned to keyboard shortcuts or custom buttons in Word cannot have any parameters or even be a function. However, if you own Dragon Professional, which is a separate paid application with a hefty price tag, voice command scripts aren’t restricted in the same way (see separate introductory article if this sounds interesting).

Set a working range

A common initial step in a macro is to create a range variable to work with the document content. We’ll call our variable name r just to keep the name short.

Dim r As Range

A range variable is something like an invisible Selection or insertion point sharing many features with the Selection, but they’re not exactly the same.

Previous heading range function

We previously introduced a function that gets the heading range around a given location in the document (several function variations are presented in the article). The basic usage is something like:

Set rHeading = GetHeadingRange(TargetRange)

We “pass” it a previously defined range variable, which we’re calling TargetRange, around which we want the full heading range. We store the result in a range variable named rHeading here, but the names will vary.

Fortunately for our derived Scene and Scene Edited heading styles, this function works with standard or derived heading styles.

Get our current heading range

The heading range corresponding to the current user position or selection in the document is accessed using the Selection’s Range property.

Selection.Range

This works whether the initial Selection includes any spanned text or if it is just an insertion point (i.e., the blinking I-bar waiting for you to type).

We need to store the heading range somewhere, so we use the above working range r. We “call” the function to get the current heading range and store the result:

Set r = GetHeadingRange(Selection.Range)

Now our working range r is assigned to the entire heading range around the initial position in the document. We used Set because ranges are objects with more information than a typical value like a number.

Using this working range r, we can access heading paragraph without affecting the user’s current position or selection.

Was a heading range found?

What if no headings existed in the document? Is that a problem?

We need to verify that a heading range was found. If not, the function literally returns Nothing (meaning no range was assigned to r). Since a range is an object, we can check whether it is equal to Nothing using the “Is” operator.

r Is Nothing

Technically, Is compares whether two objects are the same thing, but Nothing is the value objects have when not assigned to anything in the document yet, so we also use it to compare an object variable to Nothing.

Conditional statement

Since this is a Boolean value, we can use it directly in a conditional statement:

' Check whether a heading range was found
If r Is Nothing Then
' No heading found, so exit the macro ...
End If

If you want more background on conditional statements in VBA, see this previous article for a quick review.

Exit the macro

As we’ve done before, we need to exit the macro if the target range is not yet assigned to anything in the document. Macros are technically called “subroutines” in VBA which are usually abbreviated as “Sub”. Since the command is so short, I used the more compact If statement notation on a single line.

' Exit if no heading range was found
If r Is Nothing Then Exit Sub

This is a subroutine, so there is no value to return for the macro like we’ve done in previous functions. We just exit if there is a problem with the heading range.

In my testing, this will likely not be a problem even if a document has no headings, but it is definitely safer to include it just in case something strange occurs.

Toggle heading paragraph style

We want to toggle the Scene style of the heading paragraph to indicate we just finished editing it (or vice versa). A previous set of macros toggled the current paragraph style, but we need to change the style of the heading paragraph of our range without moving there. That last part is half the point of this macro. We don’t want to require unnecessary manual steps for anyone using the macro.

Our function to toggle a given paragraph style is:

ToggleParagraphStyle(SomeParagraph, StyleA, StyleB)

It takes three arguments starting with the paragraph of interest which we call SomeParagraph here. Then we give the function two styles, StyleA and StyleB. The style names can be plain text names or names stored in String variables. The function alternates between them each time the macro is run.

First paragraph

We need the first paragraph of the heading which we’ll call Paragraph1.

Dim Paragraph1 As Paragraph

We declared it as a Paragraph since the function wants this specific data type (makes sense too since it works specifically with a paragraph).

The first paragraph is literally the first one contained within the heading range r. We’ve mentioned the Paragraphs collection of a range variable before which contains all paragraphs even partially within the range variable.

r.Paragraphs

We just need to reference the First paragraph of the collection using the First property.

r.Paragraphs.First

We finally store this paragraph in our Paragraph1 variable.

Set Paragraph1 = r.Paragraphs.First

We used Set because a Paragraph is an object much like a range.

Not using first paragraph’s range

Note we are not using the Range property of the first paragraph.

r.Paragraphs.First.Range ' Not using a range for above function

We’ve used ranges and range variables a lot, but our ToggleParagraphStyle function specifically wants a Paragraph variable not its range.

Style names

We need the two names of paragraph styles that exist in the document. For our case here, we’ll use the previously mentioned scene heading names “Scene” and “Scene Edited”. It’s not necessary to declare them as new string variables since we can just use them as plain text in double quotes.

No style validations here

We don’t need to validate whether the styles exist in this macro since the function does that for us, so there shouldn’t be a problem if we switch to another document where they don’t exist yet.

Function call

Given the function above, we pass the paragraph variable and the two style names.

Call ToggleParagraphStyle(Paragraph1, "Scene", "Scene Edited")

We need to use “Call” for the function because it has arguments. This is actually a function not a subroutine, so using Call essentially ignores the returned information from the function. We don’t need the returned value, so there is no need to declare a variable to store it and then not use it anywhere.

More concise alternative

We could skip the paragraph variable stuff, but the result is a little messier if you’re not used to looking at it.

Call ToggleParagraphStyle(r.Paragraphs.First, "Scene", "Scene Edited")

This works because r.Paragraphs.First is already a Paragraph object, so just skip assigning it to a middleman variable Paragraph1 and pass it directly to the function. Use whichever version you prefer. I like the conciseness of this version but the clarity of the previous, but we can only chase one rabbit.

Final Macro

Putting the steps together, our macro is:

Sub ToggleSceneHeading()
' Toggle scene heading style from within the heading content

' Declare working range to get heading paragraph
Dim r As Range
Set r = GetPreviousHeading(Selection.Range)

' Exit if no heading range was found
If r Is Nothing Then Exit Sub

' Toggle style for heading paragraph if one was found
Dim Paragraph1 As Paragraph ' Store first paragraph
Set Paragraph1 = r.Paragraphs.First
Call ToggleParagraphStyle(Paragraph1, "Scene", "Scene Edited")
End Sub

If you’ve followed along with some of the other member tier macros, you may notice a pattern. We create functions to do some (or most) of the hard work. Often this involves using a function to quickly and safely get a range of interest. In this macro, we utilize another function to toggle between known scene styles. Putting them together makes this macro “easy” to create.

But don’t “over function” macros

We don’t want to “over function” every macro since that can make them harder to update or troubleshoot later if there are dozens of micro-functions that are only used in one macro. That’s bad organization, but both functions above are general enough to be readily used in other macros.

What about three styles?

If you want to cycle between three styles, use the other function given in the same article. Almost everything would stay the same, but the function call at the end would become:

Call CycleParagraphStyle(Paragraph1, "Scene", "Scene Edited", "Scene Tentative")

This implies I also have a Scene heading style called “Scene Tentative” which I do. I use it to mark a possible route in my story as it develops. Again, this is just my approach that helps me organize my novel as I write and edit. Use what works for you.

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.