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

Trim blank space from range

Word • Macros • Functions
Peter Ronhovde
9
min read

When writing Word macros, it’s relatively common need a working text range spanning regular text but with no blank space (spaces, paragraph marks, or tabs) included on either side.

Thanks for your interest

This content is part of a paid plan.

Trim Blank Space from a Range

Trimming any blank space makes the macro easier to create since we don’t need to think about as many exceptions for our macros. To simplify the explanation, we’ll focus on trimming blank space from the right side of a range, but a very similar argument applies to trimming them from the left side.

What’s the plan?

We want to remove all spaces, paragraph marks, and optionally tabs off one end of a range—

"Oh that’s easy …"

Just hold on a second. This one seems immediately obvious if you’ve been tinkering around with VBA in Word (or following this blog) for a while. Just use a quick command like so.

r.MoveEndWhile Cset:=" " + vbCr, Count:=wdBackward

The command removes any spaces or paragraph marks from the End of a range.

And … we’re done, right?

Well …

It works fine as long as at least some regular (non-blank) text is spanned by the range.

What’s the problem?

The problem occurs when an empty range or one that contains only spaces or tabs is passed to the function. The above command will just keep moving the range position until it finds some regular text.

Doesn’t quite work …

More obvious solutions leave something to be desired.

Detect empty range?

We need a step to catch and correct blank ranges. We could just be direct and test whether the range is empty with something like this.

' Not the best way to handle the special cases here ...
If rStart = r.End Then
' Do empty range case steps ...
Else
' Do regular trimming stuff ...
End If

But this doesn’t catch when only spaces are in the range.

Detect space-filled paragraph?

Detecting an empty range directly doesn’t catch a blank paragraph (as opposed to an empty paragraph), so do we add yet another test for this?

That version would be a little more complicated. For example, we could iterate through each spanned character and check whether it’s a space, tab, or paragraph mark?

' An awkward solution to the problem ... (do not use)
For Each MyCharacter In MyRange.Characters
If MyCharacter = " " Or MyCharacter = vbTab Then
' Track any spaces, tabs, or regular characters?
End If
Next

For now, ignore the loop stuff since I haven’t properly introduced them. The main point here is somehow tracking whether we ever encounter a regular character in the range and then make a decision on what to do.

I suppose that would work, but it’s just clumsy and clunky and quite a few more steps than initially expected to complete such a simple task.

Better solution?

Sometimes we just need to sit on our hands and not implement the first idea that comes to mind because we can catch both cases with a much simpler test. That’s why you have me along for the ride, right?

Create the function skeleton

Start by creating the function skeleton.

Function TrimRangeRight(rTarget As Range) As Range
' Include function steps ...

' Return modified range
Set TrimRangeRight = rTarget ' Temporary
End Function

What parameters to use?

We accept the target range rTarget to trim. This variable is not changed during the function (normal range variables could be changed; see the article on ranges for a brief explanation).

Return type

We return the trimmed range.

Create duplicate working range

We want to avoid unintended changes to the rTarget range, so we immediately create a duplicate of it which we call r just to keep the name short.

Set r = rTarget.Duplicate

Now our working range r is independent of the given range rTarget. That way a user is not unpleasantly surprised if the given range is changed during the macro.

Trim the blank space

As previously mentioned, we move the End of the range backward across any blank space using a quick MoveEndWhile command.

r.MoveEndWhile Cset:=" " + vbCr, Count:=wdBackward

We specified the character set as a space plus a paragraph mark special character. I left off vbTab since I rarely use them in my novels, but you could just literally add it with + vbTab to the Cset characters if you prefer.

Since we specified the wdBackward option for Count, the command removes blank space from the End of the working range.

This would work fine by itself as long as at least some non-blank text is spanned. If not, the command can overshoot the starting range and end up on a previous paragraph.

Catching the overshoot

An easy method to catch when the MoveEndWhile command overshoots the beginning of the range is to check the resulting range position against the initial range. Fortunately, we created a duplicate of the initial target range, so rTarget still spans the original text range.

Recall the Start and End positions of a range are literally character positions (as Long values which allow bigger numbers than Integers) as counted from the beginning of the document.

If we moved too far, the End position of the working range will have moved before the Start position of the initial target range.

Why?

We removed all blank space from the initial range until no characters were left, so the MoveEndWhile command kept looking backward in the document as commanded. It just went too far, so the comparison check is:

If r.End < rTarget.Start Then
' Moved too far, so correct ...
End If

What is a collapsed range?

We need a slight detour for a moment.

The Start and End positions of a collapsed range are the same, so no text (or any document content) is spanned by the range. We can achieve this manually by assigning the same document position to both Start and End positions of a range.

Correcting the overshoot

If we moved too far, the result should be a collapsed range at the beginning of the initial target range.

Why?

The “trimmed” range cannot logically occur before the Start position of the given target range, so we don’t let it.

How do we correct the working range position?

We just need to set the working range to the starting position of the initial target range.

r.SetRange Start:=rTarget.Start, End:=rTarget.Start

More specifically for this version trimming on the right side of the range, we assign the Start position of the initial range to both the Start and End positions of the working range r.

The SetRange command is just a shorthand method to reassign the range with two parameters Start and End. It just saves a single step since we could also just assign the two values manually.

Corrected trimmed range

Insert this command into the above If statement to make the range correction.

If r.End < rTarget.Start Then
r.SetRange Start:=rTarget.Start, End:=rTarget.Start
End If

Gotchas

What could go wrong?

This function is safe by itself since we’re not actually deleting or changing anything in the document just removing any blank space from the given range.

Final Functions

We have three variants of the functions: trimming from the right side, left side, or both. None of these functions check any text outside the given range.

Trim range right

Trim the blank space from the end of a given target range.

Function TrimRangeRight(rTarget As Range) As Range
' Trim blank space from right side of rTarget
Set r = rTarget.Duplicate

' Move backward past blank space on end
r.MoveEndWhile Cset:=" " + vbCr, Count:=wdBackward

' Correct if moved too far
If r.End < rTarget.Start Then
r.SetRange Start:=rTarget.Start, End:=rTarget.Start
End If

' Return the trimmed range
Set TrimRangeRight = r
End Function

If you want to include tab characters, just add + vbTab to the Cset character list.

Trim range left

The trim left side version requires only minor adjustments. We change the initial trimming command to MoveStartWhile and drop the backward option since we’re now moving forward in the document. Then we check the result against the End position of the initial target range instead of the Start.

Function TrimRangeLeft(rTarget As Range) As Range
' Trim blank space from left side of rTarget
Set r = rTarget.Duplicate

' Move forward past blank space at start
r.MoveStartWhile Cset:=" " + vbCr

' Correct if moved too far
If r.Start > rTarget.End Then
r.SetRange Start:=rTarget.End, End:=rTarget.End
End If

' Return the trimmed range
Set TrimRangeLeft = r
End Function

Trim range either side

Putting the two together, this function trims both sides with one function call.

Function TrimRange(rTarget As Range) As Range
' Trim blank space from both side of rTarget
Set TrimRange = TrimRangeRight(rTarget)
Set TrimRange = TrimRangeLeft(TrimRange)
End Function

This one isn’t hyper-efficient since we’re passing a range back and forth, but it is simple. Most of the time, Word macros for writers are so fast that we will never notice minor inefficiencies. In this case, the clarity of the macro is more important. Plus if we make any changes to either trimming function, this function will inherit them automatically.

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.