> ## 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.

# Every Function Has a Return Type
- URL: https://nolongerset.com/every-function-has-a-return-type/
- Published: 2023-02-10T02:54:31.000Z
- Updated: 2026-05-08T12:51:51.000Z
- Description: Every Function in VBA has a return type even if you don't explicitly define one. In fact, there are *FOUR* different ways to declare function return types.
- Author: Mike Wolfe
- Tags: Subs vs. Functions, #Import 2026-05-20 02:59

**This article is one in a [series on Subs vs. Functions](https://nolongerset.com/subs-vs-functions/) in VBA.*

---

One of the "additional facts" from my Subs vs. Functions article was this:

> A `Function` has a return **type* even if you don't declare one explicitly

As it turns out, there are four different ways to declare the return types of your functions:

- **GOOD**: Explicitly
- **LAZY-BAD**: Implicitly
- **CLEVER-BAD**: Via Type-Suffix
- **JUST PLAIN EVIL**: Implicitly via `Def` Types

## Explicitly Declared Return Types

Good programming practice is to *explicitly declare* the return types of your functions. What does this mean? It means including the `As <datatype>` clause at the end of your function declaration line.

For example:

```vba
Function GetCurrentYear() As Integer
    GetCurrentYear = Year(VBA.Date)
End Function
```

The GetCurrentYear function above has an **explicit return type** of `Integer`.

## Implicitly Declared Return Types

If you don't *explicitly* declare a return type for your function, VBA will do it for you. The default type in VBA is `Variant`. So, if you declare a function, but don't explicitly declare a return type using the `As <datatype>` clause, your function will have an *implicit* type of `Variant`.

These two function declarations are identical to the compiler:

```vba
'Explicit return type of Variant
Function MyFunction() As Variant
End Function

'Implicit return type of Variant
Function MyFunction()
End Function
```

Even though they are identical to the compiler, **they are not identical to someone reading your code**.

In the first case, someone reading your code **knows** that you **intend** to return a `Variant` value.

In the second case, an inexperienced person reading your code probably does not realize that it is returning a `Variant`. Even an experienced person is left wondering whether *you realized* that the function is returning a `Variant`.

Moral of the story: **it's always better to *explicitly* declare your data types.**

## Type-Suffix Declared Return Types

While I would not recommend it, the third option for declaring return types is to use a type suffix.

A type suffix is one of the following characters that can be used to set the type of a function, variable, or literal:

```
%   Integer
&   Long
^   LongLong
!   Single
#   Double
@   Currency
$   String
```

Here's how you would use the type suffixes to declare return types for your functions:

```vba
Function VariantFunction()
End Function

Function IntegerFunction%()
End Function

Function LongFunction&()
End Function

#If Win64 Then
Function LongLongFunction^()
End Function
#End If

Function SingleFunction!()
End Function

Function DoubleFunction#()
End Function

Function CurrencyFunction@()
End Function

Function StringFunction$()
End Function
```

And here's the proof that they actually work:

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

The type suffix is **optional** when you call the function. One thing you CANNOT do, though, is to use a *different* type suffix to coerce a function from one type to another. See below:

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

The `CStr()` works (in green above), but the String type suffix character (`$`) CANNOT be used to change the return type from Long to String.

## DefType + Naming Convention Return Types

I wrote above that "the default type in VBA is `Variant`." That is true. But you can override those defaults by using the arcane and ill-advised `Def`\-type syntax.

The basic idea is that you declare the type of all *implicitly* declared identifiers based on the first letter in their name. In the example below, every function and variable that begins with the letter "A" and does not have an explicit type will implicitly be declared as a Boolean, based on the statement: `DefBool A`.

If that sounds insane and convoluted and just asking for trouble...that's because it is. Don't do this. It's evil.

...

Unless you're messing with a colleague who's too lazy to explicitly type his functions and you want to teach him a lesson. In that case, by all means, have at it!

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

---

### \[MS-VBAL\]: The VBA Language Specification

The VBA Language Specification is the authoritative document that lays out how VBA works at a very technical level. Below are excerpts from a couple of relevant sections of the Spec.

---

**[5.3.1 Procedure Declarations](https://learn.microsoft.com/en-us/openspecs/microsoft%5Fgeneral%5Fpurpose%5Fprogramming%5Flanguages/ms-vbal/227005ad-78fb-479f-8145-fa3b8b610386)**

The declared type of a function declaration is defined as follows:

- If the <function-name> element of a function declaration is a <TYPED-NAME> then the declared type of the function declaration is the declared type corresponding to the <type-suffix> of the <TYPED-NAME> as specified in section [3.3.5.3](https://learn.microsoft.com/en-us/openspecs/microsoft%5Fgeneral%5Fpurpose%5Fprogramming%5Flanguages/ms-vbal/74e5bf34-2a30-420c-9d3b-9341fa4c4c09).
- If the <function-name> element of a function declaration is not a <TYPED-NAME> and the function declaration does not include a <function-type> element its declared type is its implicit type as specified in section [5.2.3.1.5](https://learn.microsoft.com/en-us/openspecs/microsoft%5Fgeneral%5Fpurpose%5Fprogramming%5Flanguages/ms-vbal/6df70c22-dc30-45d0-b8a7-9a0fb4f068b3).
- If a function declaration includes a <function-type> element then the declared type of the function declaration is the specified type of the <function-type> element.

---

**[3.3.5.3 Special Identifier Forms](https://learn.microsoft.com/en-us/openspecs/microsoft%5Fgeneral%5Fpurpose%5Fprogramming%5Flanguages/ms-vbal/74e5bf34-2a30-420c-9d3b-9341fa4c4c09)**

A <TYPED-NAME> is an <IDENTIFIER> that is immediately followed by a <type-suffix> with no intervening whitespace.

*Static Semantics*

- The *name value* of a <TYPED-NAME> is the *name value* of its <IDENTIFIER> elements.
- The *declared type* of a <TYPED-NAME> is defined by the following table:

| <type-suffix> | Declared Type |
| ------------- | ------------- |
| %             | **Integer**   |
| &             | **Long**      |
| ^             | **LongLong**  |
| !             | **Single**    |
| #             | **Double**    |
| @             | **Currency**  |
| $             | **String**    |

---

**[5.2.3.1.5 Implicit Type Determination](https://learn.microsoft.com/en-us/openspecs/microsoft%5Fgeneral%5Fpurpose%5Fprogramming%5Flanguages/ms-vbal/6df70c22-dc30-45d0-b8a7-9a0fb4f068b3)**

An <IDENTIFIER> that is not explicitly associated with a *declared type* via either a <type-spec> or a <type-suffix> might be implicitly associated with a *declared type*. The implicit *declared type* of such a name is defined as follows:

- If the first letter of the *name value* of the <IDENTIFIER> has is in the character span of a <letter-spec> that is part of a <def-directive> within the *module* containing the <IDENTIFIER> then its *declared type* is as specified in section [5.2.2](https://learn.microsoft.com/en-us/openspecs/microsoft%5Fgeneral%5Fpurpose%5Fprogramming%5Flanguages/ms-vbal/8865edf3-62ab-4eb7-aa13-c628aef9ccc2).
- Otherwise its implicit *declared type* is **Variant.**

---

**[5.2.2 Implicit Definition Directives](https://learn.microsoft.com/en-us/openspecs/microsoft%5Fgeneral%5Fpurpose%5Fprogramming%5Flanguages/ms-vbal/8865edf3-62ab-4eb7-aa13-c628aef9ccc2)**

Implicit Definition directives define the rules used within a *module (section [4.2](https://learn.microsoft.com/en-us/openspecs/microsoft%5Fgeneral%5Fpurpose%5Fprogramming%5Flanguages/ms-vbal/4599fae2-3f41-4e70-968e-2398741f446b))* for determining the *declared type (section [2.2](https://learn.microsoft.com/en-us/openspecs/microsoft%5Fgeneral%5Fpurpose%5Fprogramming%5Flanguages/ms-vbal/aaee9b48-168f-4cfe-95d1-14c5cc427b69))* of *implicitly typed* *entities (section 2.2)*. The *declared type* of such *entities* can be determined based upon the first character of its *name value (section [3.3.5.1](https://learn.microsoft.com/en-us/openspecs/microsoft%5Fgeneral%5Fpurpose%5Fprogramming%5Flanguages/ms-vbal/b1cbd42c-6caa-4510-8f28-b0eebabf1956))*. Implicit Definition directives define the mapping from such characters to *declared types*.

---