> ## Content Index
> Fetch the complete content index at: https://nolongerset.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Working with Empty in VBA
- URL: https://nolongerset.com/empty-in-vba/
- Published: 2023-08-30T03:56:35.000Z
- Updated: 2026-05-08T12:35:19.000Z
- Description: 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.
- Author: Mike Wolfe
- Tags: VBA, Intermediate, #Import 2026-05-20 02:59

*Empty is one of many ways to express the concept of nothingness in VBA. For the others, check out [An Article About Nothing](https://nolongerset.com/an-article-about-nothing/).*

---

## Empty

From the [VBE glossary entry for **Empty**](https://learn.microsoft.com/en-us/office/vba/language/glossary/vbe-glossary#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](https://learn.microsoft.com/en-us/office/vba/language/reference/user-interface-help/isempty-function).

> Returns a **Boolean** value indicating whether a [variable](https://learn.microsoft.com/en-us/office/vba/language/glossary/vbe-glossary#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).

```vba
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:

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

For more information about [Guard Clauses](https://nolongerset.com/guard-clauses/) and [Throwing Errors in VBA](https://nolongerset.com/throwing-errors-in-vba/), see the related articles:

[Guard ClausesGuard clauses are one of my favorite low-friction defensive programming tools.![](https://nolongerset.com/favicon.png)No Longer SetMike Wolfe![](https://storage.ghost.io/c/eb/d7/ebd732c1-5f03-4f07-b386-5d08557e15c9/content/images/2023/01/Guard-Clauses-1.jpeg)](https://nolongerset.com/guard-clauses/)

[Throwing Errors in VBAIntroducing a frictionless alternative to Err.Raise.![](https://nolongerset.com/favicon.png)No Longer SetMike Wolfe![](https://storage.ghost.io/c/eb/d7/ebd732c1-5f03-4f07-b386-5d08557e15c9/content/images/2020/10/juggler-2329843_1920.jpg)](https://nolongerset.com/throwing-errors-in-vba/)

## Never Use `= Empty` to Check for Empty

Ben Clothier posted a great, succinct explanation in the comments section of *[An Article About Nothing](https://nolongerset.com/an-article-about-nothing/#commento-comment-card-b7011011d685ee8c4883bced68db9b42e68c6bc4dd3033842fc8816ce637f7b5)*:

> 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**](https://learn.microsoft.com/en-us/office/vba/language/glossary/vbe-glossary#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: 

```vba
?CInt(Empty)
 0 
```

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

```vba
?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**](https://learn.microsoft.com/en-us/office/vba/language/glossary/vbe-glossary#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`:

```vba
?StrPtr(vbNullString)
0
```

Let's turn to the VBA Language Specification for some clarification. From section [6.1.2.2, Constants Module](https://learn.microsoft.com/en-us/openspecs/microsoft%5Fgeneral%5Fpurpose%5Fprogramming%5Flanguages/ms-vbal/52c853c1-fda2-4853-8069-172e515310f9):

> 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):

![](https://storage.ghost.io/c/eb/d7/ebd732c1-5f03-4f07-b386-5d08557e15c9/content/images/2023/08/image-25.png)

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

```vba
?Empty = vbNullString

?Empty = ""

?"" = ""
```

### `?Empty = #12:00 AM#` Returns `True`

From the [VBE glossary entry for **Empty**](https://learn.microsoft.com/en-us/office/vba/language/glossary/vbe-glossary#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:

![](https://storage.ghost.io/c/eb/d7/ebd732c1-5f03-4f07-b386-5d08557e15c9/content/images/2023/08/image-27.png)

### `?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](https://learn.microsoft.com/en-us/openspecs/microsoft%5Fgeneral%5Fpurpose%5Fprogramming%5Flanguages/ms-vbal/f8acd631-55c1-4199-bc1e-022aaab6d9c8)." 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:"

![](https://storage.ghost.io/c/eb/d7/ebd732c1-5f03-4f07-b386-5d08557e15c9/content/images/2023/08/image-24.png)

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:

![](https://storage.ghost.io/c/eb/d7/ebd732c1-5f03-4f07-b386-5d08557e15c9/content/images/2023/08/image-26.png)

For more information about Null values, check out this related article, [Working with Null in Microsoft Access](https://nolongerset.com/null-in-ms-access/):

[Working with Null in Microsoft AccessLet’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.![](https://nolongerset.com/favicon.png)No Longer SetMike Wolfe![](https://storage.ghost.io/c/eb/d7/ebd732c1-5f03-4f07-b386-5d08557e15c9/content/images/2023/08/Working-with-Null.jpeg)](https://nolongerset.com/null-in-ms-access/)

### `?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](https://nolongerset.com/the-missing-keyword/) for details:

[The Missing Keyword in VBAWondering 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.![](https://nolongerset.com/favicon.png)No Longer SetMike Wolfe![](https://storage.ghost.io/c/eb/d7/ebd732c1-5f03-4f07-b386-5d08557e15c9/content/images/2023/08/Missing-Keyword.png)](https://nolongerset.com/the-missing-keyword/)

### `?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](https://nolongerset.com/an-article-about-nothing/).*