Working with Empty in VBA

A deep dive into the Empty keyword in VBA: why it exists, how to check for it, when it makes sense to check for it, and--most importantly--how NOT to check for it.

Working with Empty in VBA

Empty is one of many ways to express the concept of nothingness in VBA.  For the others, check out An Article About Nothing.


Empty

From the VBE glossary entry for Empty:

Indicates that no beginning value has been assigned to a Variant variable. An Empty variable is represented as 0 in a numeric context or a zero-length string ("") in a string context.

IsEmpty()

The proper way to check whether a variable is nothing in VBA is via the IsEmpty() function.

Returns a Boolean value indicating whether a variable has been initialized.

You should never use the equal sign with the Empty keyword to check if a variable or value is Empty (more on that below).

Sub TestEmpty(MyVar As Variant)

    'GOOD:
    Debug.Print "Is MyVar Empty? "; IsEmpty(MyVar)
    
    'BAD:
    Debug.Print "Is MyVar Empty? "; MyVar = Empty

End Sub

Practical Usage: Guard Clauses

I rarely use the IsEmpty() function to test the contents of a local Variant variable.

Generally speaking, I try to ensure that a local Variant variable gets initialized before I try to interact with it, regardless of which code path gets followed.  However, if I have a routine has a required Variant parameter, it might be wise to check to see whether the calling code passed me an Empty value, like so:

Sub MyRoutine(MyParam As Variant)
    If IsEmpty(MyParam) Then Throw "MyParam cannot be empty"
End Sub

For more information about Guard Clauses and Throwing Errors in VBA, see the related articles:

Guard Clauses
Guard clauses are one of my favorite low-friction defensive programming tools.
Throwing Errors in VBA
Introducing a frictionless alternative to Err.Raise.

Never Use = Empty to Check for Empty

Ben Clothier posted a great, succinct explanation in the comments section of An Article About Nothing:

IMO, I think Empty is the worst variant because if one doesn't understand how Variant and implicit conversion work, the following expression can appear downright bizarre:

?Empty = 0
True
?Empty = vbNullString
True
?Empty = #12:00 AM#
True
?Empty = vbNullChar
False
?Empty = Null
Null
?IsNull(Empty)
False
?IsMissing(Empty)
False
?IsEmpty(Empty)
True

All of those make logical sense though not necessarily intuitive and requires thinking about because VBA's implicit conversion of variants is really what distorts the evaluation.

Let's make sense of each of Ben's examples.

?Empty = 0 Returns True

From the VBE glossary entry for Empty:

An Empty variable is represented as 0 in a numeric context...

An explicit conversion of the value Empty to Integer produces a value of zero:

?CInt(Empty)
 0 

Thus, if we use the result of the explicit conversion, the result of the comparison makes perfect sense:

?CInt(Empty) = 0
True

However, VBA does not require explicit conversion among data types.  

If you directly compare two different data types in VBA, the language will attempt an implicit conversion of one of the values to a matching data type before performing the comparison.  When we compare the value Empty to 0, VBA first performs an implicit conversion of Empty to 0.  

In the end, VBA is reducing the expression ?Empty = 0 to ?0 = 0 via implicit conversion.

?Empty = vbNullString Returns True

From the VBE glossary entry for Empty:

An Empty variable is represented as ... a zero-length string ("") in a string context.

The more interesting portion of this expression is not Empty; it is vbNullString.  That's because vbNullString is not the same as "".  In fact, vbNullString does not exist as a string in memory at all.  Rather, it is a constant that represents a "null string pointer."  It has a memory address of 0:

?StrPtr(vbNullString)
0

Let's turn to the VBA Language Specification for some clarification.  From section 6.1.2.2, Constants Module:

vbNullString: An implementation-defined String value representing a null string pointer

I could not find any concrete documentation on how the Office VBA implementation represents a null string pointer, but from some cursory testing it appears that it treats it as a zero-length string for comparison purposes (see the expression ?vbNullString = "" in the screenshot below):

For practical purposes, then, we can assume VBA is reducing the expression as follows:

?Empty = vbNullString

?Empty = ""

?"" = ""

?Empty = #12:00 AM# Returns True

From the VBE glossary entry for Empty:

An Empty variable is represented as 0 in a numeric context...

Dates are considered numeric for the purpose of Empty comparisons.  The Date literal #12:00 AM# represents a numeric date value of 0 (zer0), which is why the ?Empty = #12:00 AM# expression returns True.

?Empty = vbNullChar Returns False

The vbNullChar constant represents a single Null character (i.e., ASCII code 0).

The easiest way to understand why this particular comparison returns False is to realize that Empty is represented by a zero-length string while vbNullChar is a string with a length of 1:

?Empty = Null Returns Null

Comparing any value to Null with the equals sign always returns Null.

This behavior is documented in section 5.6.9.5 of the VBA Language Specification, "Relational Operators."  The equals sign is tokenized as the "equality-operator-expression."  

As per the specification, "[t]he effective value type is determined as follows, based on the value types of the operands:"

Comparing any value to a Null always returns a Null.

?IsNull(Empty) Returns False

The IsNull() function is only used to check whether the passed value is Null or non-Null.  The IsNull() function tells us nothing about whether the passed value is Empty or not Empty, as this sample code shows:

For more information about Null values, check out this related article, Working with Null in Microsoft Access:

Working with Null in Microsoft Access
Let’s explore the many ways to check for, handle, and store Null values. Spoiler alert: the best way to do it varies between VBA and SQL.

?IsMissing(Empty) Returns False

The IsMissing() function is only used to check whether an optional variant parameter has been provided by the calling code.  See my article on The Missing Keyword in VBA for details:

The Missing Keyword in VBA
Wondering what the IsMissing() function is all about in VBA? We’ll explore that plus all the ins and outs of the VBA keyword that isn’t: Missing.

?IsEmpty(Empty) Returns True

As our alternative examples above prove, using the IsEmpty() function is the only proper way to check if a value contains Empty or not.

UPDATE [2023-09-06]: Added introductory paragraph with a link to An Article About Nothing.

All original code samples by Mike Wolfe are licensed under CC BY 4.0