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

Delete sentence introductory phrase

Word • Macros • Editing • Functions
Peter Ronhovde
28
min read

As we utilize our editing tools, we’ll inevitably want a more comprehensive set. Toward that end, we generalize an earlier macro to quickly delete an introductory phrase or main clause of a sentence.

Thanks for your interest

This content is part of a paid plan.

Delete Sentence Introductory Phrase

We’re deleting the introductory phrase or main clause of a sentence with a keystroke. While we’re at it, our new macro might as well remove any conjunction and capitalize the new first word of the sentence. Macros excel at repetitive tasks. It’s why we use them, and today’s multi-step task is easy for a computer to accomplish without additional human input other than starting inside the intended sentence.

Why bother?

Sometimes it is handy to be able to tell Word to just do something simple. No fuss. Just get it done.

If you’ve been following along with our articles, we’ve implemented many macros to complete similar tasks. Sometimes, including this one today, the knee jerk reaction might be … but why?

After all, you have fingers, right? And you’ve been doing it “this way” for years, so why bother?

I hear you. Surely, we can leave some editing to the human, right?

Well, yes, but you’ve got plenty to do. Things that require a human brain, so why not let Word handle the tedious details.

Just try it.

You’ll be surprised at how often you’ll start wanting these quick and dirty macros to accomplish menial but necessary tasks.

A few notes

Believe it or not, the general term for either an introductory phrase or a main clause of a compound sentence is an “introducer.” Yeah, it sounds a little odd, but I’ll use that term because it’s accurate and shorter than repeating “introductory phrase or main clause.”

This macro also utilizes two previous simple functions that define single and double quotes because they are different characters between Word for Mac or Windows.

Function skeleton

We’ll initially implement a function to return the range of the introducer. We can then easily specialize it to deleting the identified text, but we’ll also extend it to related tasks when we’re done. The function skeleton is:

Function GetSentenceIntroducerRange(rTarget As Range) As Range
' Return introducer range for sentence at target range
' Omits initial double quote or open parenthesis
' Includes any conjunction if spanning a main clause

End Function

We're not creating a function to carry out the delete or select the text because we want to apply it to several different tasks each of which needs the introducer range as a starting point. I'm not saying ranges are a silver bullet but get used to thinking in terms of them, and it will often (not always) help frame up and even generalize the solution to apply to similar tasks.

The following naming stuff isn’t strictly necessary but notice the descriptive function name elements.

  • “Get” often means … well, get something. How is that for profound?
  • We then include the document element category of “Sentence”.
  • A “what” of “Introducer”
  • Finally, the word “Range” implies what the function returns to whoever uses it.

The idea is so using the function reads a little more like English, so we can understand how it’s being used in a macro. I don’t always follow the above pattern, but it also helps with organizing your macros and functions.

What parameters?

We accept a target range which should be positioned somewhere inside a sentence that contains the introducer. The target range does not have to start inside the introducer.

Return value

We return the identified sentence introducer range. For concreteness, we’ll exclude initial quotes, an open parenthesis, or a left square bracket. We’ll include a comma or semicolon in the returned range as well as any conjunction (see extended content) if we’re returning a main clause range.

The latter two details could be set up to depend on optional parameters, but I’ve found that I haven’t needed to reverse either assumption yet.

Create working range duplicate

We first create a working range r as a duplicate of the target range. It’s named r just to keep the name short.

Dim r As Range
Set r = rTarget.Duplicate

Now r is an independent range we can manipulate as desired.

Set r = rTarget ' Not an independent range (do not use in most cases)

If we were to set it equal to the target range instead, they would essentially be the same range. Any changes we would make to our working range r would immediately be reflected in the target range which is usually not the desired result.

Collapse the range

Since a given target range could span more than one sentence, it’s safest to collapse the initial range to avoid any unexpected issues with the upcoming steps.

r.Collapse ' avoid any problems

Collapsing the range ensures we have a well-defined starting point for the rest of the macro.

Get the beginning of the sentence

Since we want the sentence introducer range, we move the working range to the start of the current sentence.

r.StartOf Unit:=wdSentence

The advantage of using the StartOf method rather than a Move method is the range doesn’t move if we’re already at the beginning of the sentence. The Unit wdSentence is from a standard word units table.

Notice how we’re making choices that give us a clear state as we move forward.

Exclude initial sentence punctuation

We want to exclude single or double quotes, an open parenthesis, or a left square bracket from the range. Technically, our working range doesn’t span any text yet, but we’ll extend it toward a comma or semicolon in the next step, so we move past any initial punctuation marks before we do that.

Toward this end, we use the range’s MoveWhile method. This method keeps moving the collapsed range while it finds any of the indicated characters.

r.MoveWhile Cset:="[('" + Chr(34) + LeftDQ + LeftSQ

Cset is an option that stores a plain text string of characters to skip (different methods use Cset different ways). We include a left square bracket, an open parenthesis, and a straight single quote. Since these are already plain text, we can just include them in straight double quotes to define our character set. We then add other relevant characters using a literal plus + sign to mimic adding numbers (an ampersand & also works).

We include the two simple functions LeftDQ and LeftSQ that define single and double quotes since they are different characters in Word for Windows or Mac. Similarly, Chr(…) is a standard VBA character function. The number 34 corresponds to a straight double quote character. We use the Chr(…) function since we defined the initial Cset string using straight double quotes, so we need a way to specify it as a search character also.

Extend range over to a comma or semicolon

We’re positioned at the start of the sentence, possibly just to the right of some initial sentence punctuation marks. We now need to extend the range forward to the next comma.

r.MoveEndUntil Cset:=",;"

Since we’re also allowing a main clause, it takes almost no extra work to include a possible semicolon.

A range has Start and End positions (among other properties), so MoveEndUntil literally moves the End position of the range until it finds any character listed in the Cset option. The Start position of the range is unchanged, so any text in between the Start and End positions are now spanned by the range variable r.

In the extended content later, we’ll further verify whether a comma or semicolon exists before committing to this step.

Include the comma and trailing spaces

Now we need to include the comma or semicolon in the range. We use MoveEnd because we know we’re extending the End position of the range by one character.

r.MoveEnd Unit:=wdCharacter ' include comma or semicolon

We further include any trailing spaces to mimic how Word works when automatically selecting text. Using the MoveEndWhile method is appropriate because we want to keep extending the End of the range while the next character is a space.

r.MoveEndWhile Cset:=" "

The character set Cset is just a space. This step is probably redundant in most cases, but I like to be clear.

In the extended content, we’ll further include a possible conjunction if we happen to be spanning a main clause instead of an introductory phrase.

Final Macro

Putting the steps together, we have our function to get the range of the sentence introducer:

Function GetSentenceIntroducerRange(rTarget As Range) As Range
' Returns introducer range for sentence at target range
' Omits initial double quote, open parenthesis, or left square bracket

' Move to start of current sentence
r.Collapse ' avoid any problems
r.StartOf Unit:=wdSentence

' Omit any initial sentence punctuation
r.MoveWhile Cset:="[('" + Chr(34) + LeftDQ + LeftSQ

' Span text over to first comma or semicolon
r.MoveEndUntil Cset:=",;"

' Include punctuation mark and any trailing spaces
r.MoveEnd Unit:=wdCharacter ' Include comma or semicolon
r.MoveEndWhile Cset:=" "
End Function

We should add some checks to detect whether the target range exists or whether the sentence actually has an introductory phrase or main clause before continuing. Further checking for a possible coordinating conjunction joining two independent clauses is a convenient addition even if a tertiary effect. See the extended content below for both topics since the explanations stretch out a little.

Improved Function

Now we include two different validation checks, so we catch the problems before continuing (often resulting in our macro or function crashing). We also incorporate any coordinating conjunction between two independent clauses just to be complete.

Validation checks

We need to view any input from the user with suspicion. This is really “programming 101” (not that I call what we’re doing “programming” very often; just don’t tell anyone what we’re really doing).

Granted, in our current context we’re probably the ones both creating the macro and giving it any input, but we’re not perfect either (right?). In the interest of saving ourselves some trouble later, we should add some validation checks to our function.

First, what if the target range isn’t a valid document range? Second, what if the sentence doesn’t contain an introducer? After validating both, we'll feel more confident we’re working with a valid sentence range that includes an introducer.

Check if target range is valid

Is the given rTarget range assigned to a range in the document? It sounds like a non-sensical question at first. Of course, it refers to a document range—

Not always.

The rTarget argument given by the user could be Nothing. “Nothing” is a literal value assigned to an object when it is not yet assigned to anything in the document. We check this with the condition:

rTarget Is Nothing

“Is” is used to compare whether two objects in VBA (ranges are objects with properties and methods) refer to the same thing, but we usually use Is in this validation context. This condition is True if the target range is not yet assigned to something in the document. Our conditional statement for the range validation check is roughly:

' Check whether target range exists
If rTarget Is Nothing Then
' Target range is invalid, so let user know ...
End If
Invalidate return result if target range is invalid

If so, we need to tell the user that the target range was invalid. While we can’t return that specific information, we can at least set the return result to Nothing (using the function name).

Set GetSentenceIntroducerRange = Nothing

We must Set a range even when assigning Nothing since a range is not a plain value like a number or text. When the user notices the Nothing value of the returned range, they know something went wrong.

Exit if the target range is invalid

Since we know there is no valid result in this case, we immediately exit the function:

Exit Function

Putting it together, our fool proof check to exit if we’re not given a valid target range is:

' Check whether target range exists
If rTarget Is Nothing Then
Set GetSentenceIntroducerRange = Nothing
Exit Function
End If

Validate introductory phrase or main clause

If the target sentence has no comma or at least a semicolon, it cannot have an introducer. If one of these characters doesn’t exist in the sentence, we can immediately exit the function.

How do we check this?

We previously introduced the Like operator (in a different context) which takes search text and searches it using a provided search pattern. Both the search text and the search pattern can be defined explicitly with double quotes or refer to a string variable. The basic format of a search looks like:

SearchText Like SearchPattern

The result is a True or False (Boolean) value indicating whether the pattern was found in the searched text. We can then use this result in a conditional statement to decide whether we exit the function in our case.

What text do we want to search?

We need the full first sentence regardless of whether the initial target range spans all of it. To get it, we use the Sentences collection of the target range.

rTarget.Sentences.First

Sentences is a collection of sentence ranges in the rTarget range, and First references the first sentence range of that collection.

We need the text to search, so we use that range’s Text property. To make the following statements easier to read, we’ll declare a plain text variable and store the sentence text in it.

Dim sFirstSentence As String
sFirstSentence = rTarget.Sentences.First.Text

Strings are just values (mostly) in VBA, so we can just use an equals = sign to store it in the sFirstSentence variable.

What is our search pattern?

We want to know if a comma exists in the sentence. Obviously, our template search pattern is something like “,”, but we need to allow for any characters on either side (otherwise it looks for only a comma). A wildcard asterisk * character allows any or no characters in that search pattern position, so our search pattern becomes “*,*” since we want to allow any characters on either side of the sentence text.

Combining the pattern with our Like statement, we have:

sFirstSentence Like "*,*"
Exit if we do not find a comma

Our conditional statement is roughly:

If no comma is found Then
' Exit the function
End If

Like will tell us if a comma is found, but we only want to exit the function if a comma is Not found. Again, the Not operator reverses True or False values of the Like search result.

If Not sFirstSentence Like "*,*" Then
' Exit the function
End If

If no comma is detected, we need to tell the user no introducer was found. Since we haven’t checked anything yet, there is no introducer range to return. In VBA terms, this means the range is literally Nothing. As mentioned earlier, Nothing corresponds to an object not assigned to anything in the document yet.

Set GetSentenceIntroducerRange = Nothing

Returning this result is somewhat of a judgement call. You may prefer to return an empty range at the beginning of the sentence as your indicator of no introducer being found. In that case, the check would need to come after the sentence start is determined. We'll continue with returning Nothing in this function when no comma is found.

We then exit the function using:

Exit Function

Putting it together, our fool proof check to exit the function if no comma is found is:

' Check for a comma but exit if not found
If Not sFirstSentence Like "*,*" Then
Set GetSentenceIntroducerRange = Nothing
Exit Function
End If
Exit if we do not find a semicolon

If we’re allowing for main clauses as a special case, we should probably also check for a semicolon just to be complete. Like finding a comma, the search pattern for finding a semicolon anywhere in the search text is “*;*”.

Either case could be valid for us to proceed with the function. This condition corresponds to an Or statement. Putting it together with the comma check, we have:

sFirstSentence Like "*,*" Or sFirstSentence Like "*;*"

This compound condition tells us if either a comma or semicolon is found in the searched text. We only want to exit the function if one of them is not found, so we again need a Not operator to reverse the True or False result.

Not (sFirstSentence Like "*,*" Or sFirstSentence Like "*;*")

We included parentheses around the compound condition because we want to reverse the overall result. If we don’t like how that looks, use Not with each condition instead, but we must switch the Or to an And to make the new compound condition work out correctly.

' Alternative comma and semicolon check (just use one)
Not sFirstSentence Like "*,*" And Not sFirstSentence Like "*;*"

There is some general Boolean logic to explain this compound condition, but basically for our case, we only want to exit the function if both a comma and a semicolon are missing. That corresponds to an And operator.

Combine foolproof checks

It is convenient to combine the target range validation with the punctuation checks all into one conditional statement. After all, both sets of conditions give the same result of Nothing and then exit the function. Putting them together looks like:

' Does not work if target range is invalid ...
' Check for a valid target range and for a comma or semicolon being present
If rTarget Is Nothing Or Not sFirstSentence Like "*,*" Or Nothing Or _
Not sFirstSentence Like "*;*" Then
Set GetSentenceIntroducerRange = Nothing
Exit Function
End If

Remember an underscore _ continues a line, so the VBA editor looks at it as a single line as far as the command is concerned, but humans can read it more easily.

But be careful when using objects ...

We're okay here but be careful if the latter conditions also involve the target range variable. Unfortunately, VBA isn’t smart enough about how it checks the conditions to do this. All conditions are evaluated regardless, so if rTarget happened to be Nothing, another other tests referencing a property or method of rTarget would cause an error. For example, it would not be able to reference a Sentences collection of an invalid range. The collection would not exist since the range is not yet assigned to anything in the document yet, and the function would crash. Not nice.

Regular Visual Basic has some extra Boolean operators, specifically OrElse for our case here, to make this easier; but VBA does not inherit it which is a shame.

What's the solution?

If the following validation conditions depend on the target range, just do the other tests strictly after the target range is validated (we know it is assigned to some document range).

Including a conjunction in the range

Let’s account for a possible coordinating conjunction if we’re spanning a main clause. Of course, this is optional, but I prefer it, so we don't need to manually remove the conjunction if we delete the introducer.

Once the function has spanned text up to and including a comma, we can check whether the next word after that position is a coordinating conjunction.

Get the next word text

To make the following easier to read, we define a plain text variable sWord.

Dim sWord As String

We need the literal next word after the working range r. Ranges have a Next method that returns a range after it depending on whichever Unit we specify.

r.Next(Unit:=wdWord)

We needed to include the Unit inside parentheses, so we could reference the Text property of the next word range.

r.Next(Unit:=wdWord).Text ' Text of next word after r

Store the text in the sWord variable.

sWord = r.Next(Unit:=wdWord).Text
Trim any text spaces

The word Text will probably include a trailing space (it is the default action for Word) which will confound our checks for a conjunction below, so we should trim any spaces off the Text. VBA has a standard function called Trim(…) to do just this.

Trim(SomeText) ' Remove any spaces around SomeText

We can assign this trimmed text back to the same word variable sWord just to keep things simple.

' Trim any spaces off either side of the text
sWord = Trim(sWord)

Technically, two more standard VBA functions RTrim or LTrim exist to trim spaces off only the right or left sides, respectively, but I’m just using the regular function.

More concise trimmed word text

Alternatively, we could have skipped the intermediate assignment to sWord and saved a step.

sWord = Trim(r.Next(Unit:=wdWord).Text) ' Just use one version

I prefer this version, but it does look messier if you’re not used to looking at it.

Check for a coordinating conjunction

Check if the next word is a coordinating conjunction using a conditional statement something like:

If word is a coordinating conjunction Then
' Add word range to working range ...
End If

Basically, we check if sWord contains the text of any of the following: “but”, “and”, “yet”, “or”, “nor”, “so”. If so, we extend the End of the working range over the word.

Since we know exactly what the next word is and what the word should be, we can just compare our stored word to the conjunctions directly using an equals = sign. Remember in VBA, using an equal with strings requires an exact match—no missing or extra characters, and even the case of every letter must match.

Any of the conjunctions could match (result in a True condition for the search), so this corresponds to a series of Or statements all chained together.

If sWord = "but" Or sWord = "and" Or sWord = "yet" Or sWord = "or" Or _
sWord = "nor" Or sWord = "so" Then
' Add word range to working range ...
End If

Remember Or results in True if any of the conditions are True.

Extend the working range over a conjunction

After we detect a conjunction, we move the End position of the working range forward over that word.

r.MoveEnd Unit:=wdWord

The word Unit constant wdWord is from a table of standard Word Units. Combining this with our conditional statement, we have:

If sWord = "but" Or sWord = "and" Or sWord = "yet" Or sWord = "or" Or _
sWord = "nor" Or sWord = "so" Then
' Add word range to working range ...
r.MoveEnd Unit:=wdWord
End If

Revised introducer function

This version includes some validation checks as well as incorporating a trailing coordinating conjunction after an independent clause.

Function GetSentenceIntroducerRange(rTarget As Range) As Range
' Returns introducer range for sentence at target range
' Omits initial double quote, open parenthesis, or left square bracket
' Includes any conjunction if spanning a main clause

' Check for a valid target range or for a comma or semicolon being present
If rTarget Is Nothing Or Not sFirstSentence Like "*,*" Or Nothing Or _
Not sFirstSentence Like "*;*" Then
Set GetSentenceIntroducerRange = Nothing
Exit Function
End If

' Move to start of current sentence
r.Collapse ' avoid any problems
r.StartOf Unit:=wdSentence

' Omit any initial punctuation marks
r.MoveWhile Cset:="[('" + Chr(34) + LeftDQ + LeftSQ

' Span text up to first comma or semicolon
r.MoveEndUntil Cset:=",;"

' Include punctuation mark and trailing spaces
r.MoveEnd Unit:=wdCharacter ' include comma or semicolon

' Include coordinating conjunction for a main clause
Dim sWord As String
sWord = r.Next(Unit:=wdWord).Text ' Get next word text
sWord = Trim(sWord) ' Trim any spaces off ends

' Check whether next word is a conjunction
If sWord = "but" Or sWord = "and" Or sWord = "yet" Or sWord = "or" Or _
sWord = "nor" Or sWord = "so" Then
' Add word range to working range
r.MoveEnd Unit:=wdWord
End If

' Include trailing spaces (probably redundant)
r.MoveEndWhile Cset:=" "
End Function

For those newer to programming, the advantage of creating our working macros using this function is all four versions inherit our new improvements without any extra work.

Working macros using the function

We need a plain macro without any parameters if we plan to assign it to a keyboard shortcut, a custom ribbon button, or a quick launch button. This restriction does not apply to functions or macros called from a Dragon Professional script (which is a separate paid application).

Now that we have the base function, let’s apply it to several relevant macros. Specifically, we will select or delete the sentence introducer, or we will cut or copy it to the clipboard.

We probably won’t assign all these the keyboard shortcuts in Word since there are only so many key combinations available, but it’s nice to have them easily accessible for any simple voice commands we might set up in Dragon Professional scripting, but that is a different lesson.

Declare a working range

In each of the macros below, we define a working range.

Dim r As Range

Since r is declared in each macro separately from the above function, it is considered a completely separate variable by VBA despite the similarity in the variable names (in fancy terms, they have a different "scope"). VBA will not get them confused.

Get introducer range

In each of the macros below, we need the range of the introducer at the cursor location. We defined the previous GetSentenceIntroducerRange function to accept a target range to keep things general. Now we need to give the function the range of the current sentence. The user’s current selection or insertion point in the active document is literally called Selection (with a capital "S") in VBA, but it is not strictly a Range, so we need to reference its Range property.

Selection.Range

Then we “pass” this range to the GetSentenceIntroducerRange function and Set it equal to our above working range r.

Set r = GetSentenceIntroducerRange(Selection.Range)

The first steps above are the same for every macro below which is part of the reason for creating the workhorse of a function.

Run the appropriate method

Now that the working range corresponds to the sentence introducer, what we do now depends on the specific macro. Pick the corresponding method for the macro.

' Pick intended range method for the macro
r.Select
r.Delete
r.Cut
r.Copy

Validate the range (again?)

We should probably validate whether the returned range exists, so we like in the extended content above, we need to check whether we were given Nothing by the function.

If Not r Is Nothing Then
' Run the appropriate range method ...
End If

All the validations may seem annoying. You could take your chances and omit them, but it will probably pay off at some point in the future. (I used to skip style validations, for example, but those macros kept crashing in other documents until I got tired of it ... then I started validating the styles.)

In these macros, the chance of encountering a problem with Selection.Range being invalid is very small. If it is invalid, you have more serious problems with your document. However, since these macros deal with an introductory phrase, there is a very reasonable chance once does not exist in the current sentence.

Since the command is so short, we can use the more compact notation for two of the macros. We’ll use the Select version as an example.

If Not r Is Nothing Then r.Select

Capitalize first word of sentence

For the Cut and Delete versions of the macros, it is convenient to have the macro go ahead and capitalize the first word of the sentence for us. May as well let VBA save us the manual work.

Since we just removed the introducer, the range is now positioned precisely at the new first word of the sentence. We can control the case of the word using the Case property of the working range r.

' Capitalize new first word of sentence
r.Case = wdTitleWord

The wdTitleWord character case constant if from a standard word case table. Another other case constant wdTitleSentence also make sense, but wdTitleWord is quick and easy considering our range r is already at the beginning of the sentence. We do not need to extend the range over the word since where already positioned there.

Of course, we only capitalize the word if we have a valid range, so it would go inside the If statement.

If Not r Is Nothing Then
' Run the appropriate range method ...
' Capitalize new first word of sentence
r.Case = wdTitleWord
End If

Working macros

Putting it together, we get our initial two intended macros.

Sub SelectSentenceIntroducer()
' Select current sentence introducer range
Dim r As Range
Set r = GetSentenceIntroducerRange(Selection.Range)
If Not r Is Nothing Then r.Select
End Sub
Sub DeleteSentenceIntroducer()
' Delete current sentence introducer without using the clipboard
' Get and then delete sentence introducer
Dim r As Range
Set r = GetSentenceIntroducerRange(Selection.Range)
If Not r Is Nothing Then
r.Delete
' Capitalize new first word of sentence
r.Case = wdTitleWord
End If
End Sub
Sub CutSentenceIntroducer()
' Cut current sentence introducer to the clipboard
' Get and then cut sentence introducer
Dim r As Range
Set r = GetSentenceIntroducerRange(Selection.Range)
If Not r Is Nothing Then
r.Cut
' Capitalize new first word of sentence
r.Case = wdTitleWord
End If
End Sub
Sub CopySentenceIntroducer()
' Copy current sentence introducer to the clipboard
' Get and then copy sentence introducer
Dim r As Range
Set r = GetSentenceIntroducerRange(Selection.Range)
If Not r Is Nothing Then r.Copy
End Sub

All four macros can be useful at various times, and they take very little effort to implement after we’ve set up the workhorse function.

With the extra validation check, these macros look a little more like programming, but it’s safer to make sure the range exists before trying to use it.

Watch out for (figurative) shortcuts

If you’ve been paying close attention, you might be tempted to skip declaring the working range r. It does make the macro simple. The idea is the function already returns a range:

GetSentenceIntroducerRange(Selection.Range) ' Already a range

So why not just go ahead and select it here by referring to the Select method of the returned range.

GetSentenceIntroducerRange(Selection.Range).Select

Why bother with the extra step of storing the result in a range variable r only to use r.Select in the very next step?

Almost a gold star …

What could go wrong?

Honestly, this should work 87.238% of the time (ha, ha … math humor). If that’s good enough for you, then go for it. Here is the revised uber-simple macro:

Sub SelectSentenceIntroducer()
' Select current sentence introducer range
GetSentenceIntroducerRange(Selection.Range).Select
End Sub

Isn’t that beautiful simplicity?

Come on … admit it.

The problem is it crashes when the range isn’t valid. The way I coded the improved function, we get a result of Nothing if no sentence introducer is found. That makes sense, but it causes this simplistic version of our macro to crash. You could modify the function to return an empty range at the beginning of the sentence instead, so this simpler version of the macro doesn’t crash. However, this could cause side effects if you're not careful since methods like r.Delete would still do something, so you would need to account for the change in other places also. I'm not trying to scare you. Just trying to keep you safe.

It’s a judgment call. I just liked the clarity of the function returning a Nothing result to tell me it didn’t find anything.

Power of functions

Suppose you come back a week later and decide you also want to implement this introducer stuff for the Word spike (let me know if you use the spike). It’s almost trivial given our setup.

Sub CutSentenceIntroducerToSpike()
' Cut current sentence introducer to the spike
' Get and then cut sentence introducer
Dim r As Range
Set r = GetSentenceIntroducerRange(Selection.Range)
If Not r Is Nothing Then
NormalTemplate.AutoTextEntries.AppendToSpike Range:=r
' Capitalize new first word of sentence
r.Case = wdTitleWord
End If
End Sub

Remember Word's spike automatically cuts the text from the document, so I also included the extra step of capitalizing first word. I think the spike is more useful in VBA than in actual writing (at least for authors), but your mileage may vary.

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.