ThreeWave Enum Variable Type

This page describes the Enum data type.


An Enum (short for Enumerated) variable type is a special flavor of a Long type variable. With an Enum, you can specify a number of valid values for that variable and descriptive constant names for the values of the Enum. These values are used instead of constants. For example, without using an Enum, you might have code like the following:

    Const C_APPLE = 1
    Const C_ORANGE = 2
    Const C_PLUM = 3
    Dim Fruit As Long
    Fruit = C_APPLE

While this code is perfectly valid, it could be written better with an Enum type. When you are assigning a value to the Fruit variable, you have no indication of what the valid values are. You either must already know the valid values by name or you must flip around in the editor to the location(s) where the constants are defined.

An Enum allows you to specify valid values of a variable and the editor's Intellisense code will display a pop-up list of value name from which you can choose a value. The code above can be rewritten with an Enum as shown below:

    Enum FruitType
        Apple = 1
        Orange = 2
        Plum = 3
    End Enum

The Enum must be declared at the module-level; that is, before and outside of any procedure declaration. If you include an Enum in an an object module (a Class module, ThisWorkbook, the Sheet modules, and Userform code modules), it must be scoped as Private. As such, it cannot be accessed outside of the object module. Once, you have declared the Enum, you can declare a variable of that type:

    Dim Fruit As FruitType

Once the variable is declared as the Enum type, the Intellisense will display the values of the variable:



Validating An Enum Value

It is very important to remember that since under the hood an Enum is really a Long type variable, it is perfectly legal to assign any valid Long value to the variable, even if that value is not one of the values listed in the Enum declaration. In the code above, it is perfectly valid to assign the value 1234 to the variable Fruit even though the value 1234 is not listed in the Enum declaration. If the values declared within the Enum are sequential, as they are in the code above, you can declare hidden members of the Enum for the first and last elements, and then use a loop to iterate through the values to validate a variable's value. Expanding on the code above, the Enum can be declared as:

    Enum FruitType
        [_First] = 1
        Apple = 1
        Orange = 2
        Plum = 3
        [_Last] = 3
    End Enum

In the Enum above, the underscore makes the _First and _Last elements hidden (they will not be displayed by the editor's Intellisense feature) and the square brackets makes the underscore character valid. Now, we can loop through the valid values of then Enum FruitType to see if some value is valid:

    Dim N As Long
    Dim IsValid As Boolean
    Dim Fruit As FruitType
    Fruit = 1234
    For N = FruitType.[_First] To FruitType.[_Last]
        If Fruit = N Then
            IsValid = True
            Exit For
        End If
    Next N
    If IsValid = True Then
        Debug.Print Fruit & " is a valid value for a Fruit."
        Debug.Print Fruit & " is not a valid value for a Fruit."
    End If

One the nice improvements in the VB.NET language is the ability to test a value for validity and to get the enum element name corresponding to a value. Unfortunately, this is not possible in VBA.

For clarity and to avoid ambiguous names, you can prefix an enum value name with the name of the enum itself. For example,

Dim Fruit As FruitType
Fruit = FruitType.Plum ' Prefixed with FruitType Enum name

Automatic Values Of An Enum

While you can explicitly assign a value to an enum member, you can also allow the compiler to do this automatically. If you do not assign any values, the first enum member is equal to 0 and the remaining members are assigned sequentially ascending values. If you do assign a value, members following that member are numbered sequentially from the member to which you assigned a value. For example, the following enums are functionally identical:

Public Enum EnumOne
End Enum

Public Enum EnumTwo
    A = 0
    B = 1
    C = 2
End Enum

The followng shows how the compiler set values when a member is assigned a value:

Public Enum EnumThree
    A = 10
    B ' equals 11
    C ' equals 12
End Enum

You can also allow the compiler to assign values based on a member that is not the first member. For example,

Public Enum EnumFour
    A ' equals 0
    B ' equals 1
    C = 12
    D ' equals 13
    E ' equals 14
End Enum

You can assign a value to an enum member by using a previously defined enum member's value. For example,

Public Enum EnumFive
    A = 1
    B = A + 2 ' equals 3
    C = B + 2 ' equals 5
    D ' = 6
End Enum

Note that Enums cannot be declared within a procedure. They must be declared within the declarations part of a module, above and outside any procedure in the module. Class modules can declare Public Enum types but you cannot create a variable whose type is an Enum declared within a class module.

Composite Values

You can code your Enum types to allow more than one element of the Enum to be combined in order to allow the user to specify multiple options. For example, examine the following Enum:

Public Enum FontStyle
    Normal = 0
    Bold = 1
    Italics = 2
    Underline = 4
    Strikethrough = 8
End Enum

You can combine multiple values of the FontStyle enum to specify several Font options. The key here is that the values are powers of 2, which means that each one turns on a different bit of the Enum Long value. When you add multiple elements together, it indicates that those font elements are to be used. To determine what elements are turned on, you use VBA's bit-wise And operator. For example:

Dim FS As FontStyle
Dim R As Range

Set R = Range("A1")

FS = Bold + Strikethrough + Underline ' specify multiple font attributes

' Test FS against each FontStyle value
If FS And Bold Then
    R.Font.Bold = True
End If
If FS And Italics Then
    R.Font.Italic = True
End If
If FS And Strikethrough Then
    R.Font.Strikethrough = True
End If
If FS And Underline Then    R.Font.Underline = True
End IfIf

In this code, the FS variable, declared as a FontStyle, is tested with a bit-wise And against the various values of the FontStyle enum and then the font of the range object R is set accordingly.

Because an Enum is really a Long type variable, you can create a set up to 32 elements that can be combined. When creating many elements of a enum, it is useful to use exponential expressions to assign the values. For example,

Public Enum FontStyle
    Ex0 = 0
    Ex1 = 2 ^ 0
    Ex2 = 2 ^ 1
    Ex4 = 2 ^ 2
    '... as so on to
    Ex30 = 2 ^ 30
End Enum

Finally, you can turn all the bits on by setting the variable's value to -1, as in FS = -1. This works because in binary, -1 sets all the bits of the Long to 1s. Similarly, all bits can be turned off by setting the value to 0.


This page last updated: 12-March-2008