In some macros, it’s useful to know the overlap, or lack thereof, of two distinct document ranges in Word.
Thanks for your interest
This content is part of a paid plan.
Range Intersection Function
A function finding the intersection of two Word ranges would be more natural as a native Range method, but that does not exist in Word VBA, so we need a separate function.
What does an intersection mean in Word?
A mathematical intersection includes all shared elements between two sets. The equivalent for Word ranges is finding the overlapping document positions of two ranges.
Of course, two sets might have no elements in common, so the intersection would be the empty set. We’ll also need an equivalent for Word range intersections (see below).
Brief review of positions and ranges
Remember document positions are the number of characters counted from the beginning of the document. Ranges in Word are essentially stored as Start and End positions in the document.
Why should I care?
As an author, I try to play safe with my macros, particularly if there is a function that has the potential to affect a large portion of my document. In such cases, I’ll restrict the working range to limit any ill effects if something goes wrong.
For example, an upcoming macro adds all unknown words in the selection to a custom dictionary, but have you ever accidentally selected a larger region of the document than you originally thought? I don’t want to accidentally add all misspelled words to my custom dictionary, so constraining the initially selected range to within the current page helps prevent any mishaps. Of course, I also give a user the option to force any changes, if desired, so it’s a precaution not an essential feature.
Different from InRange method
If you just want to know whether one range is fully inside the other, then the existing range method InRange returns a True or False value.
This is True if range r1 is inside r2 and False if not. I’ve used this method to restrict Find operations to within a target range.
Create the function skeleton
We start by creating the function skeleton.
What parameters to use?
The function accepts two ranges, which we’ll call r1 and r2, to check for any overlap between them.
Return type
We return the overlapping document range, if any.
We can further indicate an empty set equivalent with no overlapping document range using a “Nothing” value, so return Nothing if either given range is Nothing or if there is no intersection.
Special cases
We first need to handle a couple special cases.
What about an empty range argument?
This is an extra foolproof check, but it must be done since we can’t guarantee a macro won’t give us an invalid range variable.
In Word VBA, an unassigned range variable has a “value” of Nothing meaning it hasn’t yet been assigned a proper document range. If either range r1 or r2 is Nothing, there is no possibility for an intersection between the ranges, so we assign Nothing as the function’s return value and immediately exit the function.
Since it's a range, we need to use Set to assign it, but we literally assign Nothing to it.
Nothing has other uses in Word VBA like effectively deleting an object. Today we’re using it to indicate the equivalent of an empty set result for our intersection.
Detecting Nothing
How do we detect Nothing?
The condition to detect an unassigned object has a special syntax.
Notice the “Is” statement instead of a more typical equals = sign in regular value conditions. This condition is True if the variable SomeRange is not yet assigned to a valid document range. This example refers to a Range variable, but the idea also applies to other object types.
We need to two of these for the given ranges r1 or r2 since either of them being Nothing is enough to invalidate a possible intersection between them.
In order to make it past this If statement, both conditions must be False meaning both ranges must exist in the document.
What if there is no overlap?
Technically we don’t need to check for no overlap this early in the macro, but it makes the later logic a little simpler since we can assume at least some overlap exists even if only at one document position.
We take advantage of the fact that ranges in Word are essentially a span of contiguous character positions in a document.
What is the condition for no overlap?
Due to the ordered nature of Word range positions, there is no overlap if range 1 ends before range 2 starts. More specifically for VBA ranges, the End position of range r1 is before the Start of range r2.
Since we don’t know which range is earlier in the document, we also need to check the reverse condition where r2 is before r1.
If either condition is True, the result is an empty set. This sounds like another Boolean Or operator is needed.
Overlap result
If there is no overlap, we return Nothing and exit the function immediately since we already know the result. Combining the steps, we have:
Define a working range
We don’t want to modify either range argument r1 or r2 (see range article for why this matters), so we create a separate range for the work below. We initially assign it to be the first range r1 for simplicity.
The Duplicate method creates an independent range to modify. Otherwise, the two range variables would literally refer to the same range. We know any possible overlap will include part of r1, so this is a good starting point.
Detecting overlapping range
We’ve already handled the case of no intersection above, so let’s find the overlap between the two ranges.
Left side
The working range r is currently equal to the given range r1. If anything changes, the intersection shrinks the range. Specifically, if the Start of the second range r2 is bigger (later or to the right) in the document than the current Start position, then move the Start position of our working range r.
Right side
Repeat that idea on the right side. If the End position of r2 is smaller (earlier or to the left) in the document than the current End position, then move the End position of our working range.
Shorter versions
Since both of these commands are super short, we can use a shorthand notation where we don’t require an End If statement. As long as it fits on a single command line, we can instead write the following:
This is a matter of preference, but I like to condense them onto one line when the commands are clear.
Return working range result
At this point, the working range r holds our valid overlapping result, so just return it.
No gotchas
The main gotcha of being given an invalid range for r1 or r2 was handled in the foolproof condition at the top of the macro, so I think we’re okay now.
Final Function
Putting everything together, the range intersection function is:
I mainly used this function to restrict a document range for any action I am a little nervous about. For example, I might restrict a range to be within the screen, so I can visually validate whether the macro, whatever it does, worked correctly.