top of page
John

VBA Attributes

Updated: Aug 14

What is an Attribute?


A name/value pair that specifies some characteristic of a Module or Module-member. All Attributes are hidden when editing VBA code directly in the VBE.


What can I do with Attributes?


All sorts of things. They define the names of Modules. They define the descriptions, seen in the Object Browser, of Modules and Module members. They define whether a class Module has a default instance, is iterable, has a default member and whether objects created from a Class Module are public or not. And more … read on.


The following is a summary of the Attributes that actually perform a function in VBA:


Module Attributes


Module Attributes are located at the top of a Module.


For more on Module Attributes, see The details – Module Attributes

Attribute VB_Name = "SomeName"

Module name

Attribute VB_PredeclaredId = False

True to create a default instance

Attribute VB_Exposed = False

True to allow other VBA Projects to access (but not create) Class instances

Attribute VB_Description = "Some text"

Module description, visible in Object Browser

Procedure and Property Attributes


Procedure and Property Attributes are located immediately following the Procedure / Property declaration line. They include the name of the Procedure / Property they apply to (shown as [ProcOrPropName], below) in the Attribute name.


For more on Procedure and Property Attributes, see The details – Procedure / Property Attributes

Attribute [ProcOrPropName].VB_UserMemId = 0

Procedure / Property is the default member of the Class

Attribute [ProcOrPropName].VB_UserMemId = -4

Function / Property Get returns an enumerator to iterate over a Collection

Attribute [ProcOrPropName].VB_ProcData.VB_Invoke_Func = "J\n14"

Procedure has a keyboard shortcut (Excel only)

Attribute [ProcOrPropName].VB_Description = "Some text"

Procedure / Property description, visible in Object Browser

Variable and Constant Attributes


Variable and Constant Attributes are located immediately following the Variable / Constant declaration line. They include the name of the Variable / Constant they apply to (shown as [VarOrConstName], below) in the Attribute name.


For more on Variable and Constant Attributes, see The details – Variable / Constant Attributes

Attribute [VarOrConstName].VB_VarUserMemId = 0

Variable / Constant is the default member of the Class

Attribute [VarOrConstName].VB_VarDescription = "Some text"

Variable / Constant description, visible in Object Browser

How do I see and adjust the values of Attributes?


Depends which Attribute.


Some you can access directly from the standard VBE UI eg

  • The name of a Module … obviously

  • Whether new instances of Class Modules are public or not

  • The description of a Module

And some you cannot access directly from the standard VBE UI but you can by using the built-in export/import functions or by using VBE_Extras eg

  • Whether a Class Module has a default instance

  • Whether a Class Module is iterable

  • Whether a Class Module or UserForm Module has a default member

  • The description of Module members (Procedures, Properties, Variables and Constants)

And note that some Attributes, in VBA, do nothing at all – MultiUse, VB_GlobalNameSpace and VB_Creatable are legacy Attributes carried over from VB6 and serve no purpose in VBA. In fact, if you change their values from anything other than the default, the VBE will reset their values back to the default when you re-import the Module.


How to add or adjust Attributes that aren't accessible using the VBE UI


You have two ways to view or adjust the values of Attributes that you cannot access directly from the default VBE UI (but see note for Attributes in Document Modules).


The complicated way - use the built-in export/import functions.


In the VBE, right click on the relevant Module in the Project Explorer window, select 'Export File' and choose a suitable location. Open that file (a Standard Module will be saved with a .bas extension; a Class or Document Module will be saved with a .cls extension; a UserForm will generate two files … one with a .frm extension and one with a .frx extension … for Attributes, you want the .frm file) in a text editor (Notepad or similar).


You can now view the Attributes and their values. Module Attributes at the top of the file. Attributes for Module members (Procedures, Properties, Variables and Constants) immediately follow the member declaration.


To adjust the value for an existing Attribute, you just replace the Attribute's value, so for example you can replace a False value for the VB_PredeclaredId Attribute with True (ensure to keep the space characters before and after the '=' sign and to keep each Attribute on its own line).


To add a new Attribute, add a line (for Module Attributes, either immediately before, in the middle of, or immediately after the existing list of Attributes; for Module members, immediately following the declaration of the member) and type 'Attribute', a space, if the Attribute is for a Module member then the name of the Module member followed by a '.', the Attribute name, an '=' (surrounded by spaces) and then the Attribute value. If the value is text then it must be surrounded by speech marks and any speech marks within the text must be escaped (with another speech mark). So, for example, to add a description to a Module, you would add a line as follows:

Note that the length of the description is limited by the number of characters allowed in a single line of VBA, that is 1024 characters less the Attribute name, equals sign, spaces, speech marks and characters used for escaping other speech marks and less the terminating carriage return for the line.


You then need to import the Module back into the VBE. First save the file that you just modified. If you want to replace the old version of the Module with the new version with the modified Attribute then first delete the old Module from the VBA Project… right-click it in in the Project Explorer window then select 'Remove'. Then in the VBE, again in the Project Explorer window, right-click the Project (or any Module of the Project) and select 'Import File', select the file with the modified Attribute. Done.


Note also that:

  • There must be a space before and after the '='

  • If Attributes have white space (on the same line) before the word 'Attribute' they will be removed when you import the module

  • Attributes are not case sensitive (either the name of the Attribute or, for Attributes applied to Procedures, Properties, Variables and Constants) the name of the Procedure, Property, Variable or Constant (the VBE fixes the casing when you import the Module)

And when adding new Attributes:

  • Module Attributes must not have a blank line between the new Attribute line and the existing Attribute line(s)

  • Procedure, Property, Variable or Constant Attributes must be on a line immediately following the line that declares the Procedure, Property, Variable or Constant


The simple way – using VBE_Extras


For a Module Attribute, in the Project Explorer window, right-click the Module then select: Extras, then Attributes, then select the desired option to either view or set the value for the Attribute. VBE_Extras does the rest ensuring that you only select appropriate values for appropriate Attributes.


For a Module member Attribute, in the Code Window, right-click the name of the member in its declaration line then select: Extras, then Attributes, then select the desired option to either view or set the value for the Attribute. VBE_Extras does the rest ensuring that you only select appropriate values for appropriate Attributes.


Other reasons to use VBE_Extras:

  • Manually exporting, editing and importing Modules is highly error prone … VBE_Extras will handle all of this for you

  • It will ensure you only add Attribute types that are relevant to the Module / Procedure / Property / Variable / Constant

  • It will ensure that the Attribute name is correct and it's value is appropriate

  • It will ensure that when you add an Attribute that should be unique in a Module, eg VB_UserMemId = 0 / VB_VarUserMemId = 0, then it will warn you if that Attribute is already present and will remove it for you where appropriate.

  • It will prevent you from adding Attributes within Module types that the Attribute cannot be used within eg VB_UserMemId = -4 can only be added in a Class Module


VBE_Extras displaying Class Module Attributes
VBE_Extras displaying Class Module Attributes

Adding a description to a Procedure using VBE_Extras
Adding a description to a Procedure using VBE_Extras

Note for Document Modules


Neither of these ways will allow you to update any Attribute in a Document Module. The reason for this is that you cannot remove an existing Document Module and when you import a Document Module into the VBE, it is imported as a Class Module, not as a Document Module. Only the VBE itself can update an Attribute in a Document Modules and it will only allow you to set its name (VB_Name) and description (VB_Description) Attributes.


For clarity, Document Modules are:

  • In Excel, ThisWorkbook and the Sheet Modules

  • In Word, ThisDocument

  • In Outlook, ThisOutlookSession

  • In PowerPoint, VBA Projects do not have Document Modules


The details – Module Attributes


Which Module Attributes are present and/or can be added depends on the type of Module:

  • Standard Modules – only VB_Name is present by default and can be updated; VB_Description can be added

  • Class Modules – all of the following Attributes other than VB_Description are present by default and can be updated; VB_Description can be added

  • UserForm Modules - same as for a Class Modules but note that a UserForm Module header also has a GUID and other UserForm-specific data added - these are not 'Attributes' and so are not covered in this post

  • Document Modules - all of the following Attributes other than VB_Description are present by default and can be viewed but only VB_Name and VB_Description can be updated / added (using the VBE UI)

Here is an example of the Attributes in a Class Module (with the VB_Description Attribute added). The VBA code itself will start on the line immediately follows the last Attribute.


VB_Name


Defines the name of the Module. Is adjustable from the VBE UI and so isn't very thrilling to discuss here. Just use the VBE's built-in rename capability to adjust the value of this Attribute.


VB_GlobalNameSpace


Serves no purpose in VBA. Always defaults to False.


VB_Creatable


Serves no purpose in VBA. Always defaults to False.


VB_PredeclaredId


This Attribute defines whether a Module has a default instance - that is you can access the members of the Class without first creating a new instance of it.


For a UserForm Module, this is True by default (if you export a UserForm Module, set it to False, then import the UserForm, the VBE will revert it back to True ... hence, a UserForm always has a default instance). For a Class Module, this is False by default but you can set it to True. You cannot do this using the VBE UI, instead see How to add or adjust Attributes that aren't accessible using the VBE UI


Setting VB_PredeclaredId to True allows you to convert code that creates a class instance like this

to this

The Create method does not appear magically though. The class itself needs to define it … where the original class was, for example

The new class also has

This is a 'factory' which creates a Class instance (for those reading this who are familiar with other object-oriented languages, this is the nearest VBA can get to have a constructor), assigns values to the members and passes the fully formed instance back to the calling code (more on factories and VBE_Extras' ability to auto-generate them in a subsequent blog post!).


VB_Exposed


This Attribute defines whether objects created from a Class or UserForm Module are Public (can be accessed from another VBA Project) or not.


This is False by default but can be set to True. For a Class Module, you can do this using the VBE UI (select the Class in the Project Explorer window menu then adjust the value of 'Instancing' in the Properties window where '1 – Private' is equivalent to False and '2 – PublicNotCreatable' is equivalent to True). For a UserForm Module, you cannot do this using the VBE UI, instead see How to add or adjust Attributes that aren't accessible using the VBE UI

Setting the VB_Exposed Attribute using the VBE UI
Setting the VB_Exposed Attribute using the VBE UI

Note, though, that even with VB_Exposed being set to True, other Projects still cannot create new instances of the Class or UserForm, they can only access existing instances that have been created by the Project that the Class or UserForm is in … so that Project (that the Class or UserForm is in) will need to include a Public Function or Property Get in a Standard Module to create instances for the 'other Project' such as

VB_Description


This Attribute defines whether a Module has a description … the description being visible in the Object Browser. This Attribute is not present by default (and so there is no description in the Object Browser by default).


You can set the value of this Attribute using the VBE UI for all types of Module (go to the Object Browser, select your VBA Project as the 'library', right-click the relevant Module under 'Classes' then select Properties and you will see the 'Description' box to enter text).

Displaying the VB_Description Attribute using the Object Browser
Displaying the VB_Description Attribute using the Object Browser





The details – Procedure / Property Attributes


As with Module Attributes, which Procedure and Property Attributes can be added depends on the type of Module:

  • Standard Modules – the VB_Description Attribute and, in Excel, the VB_ProcData.VB_Invoke_Func Attribute can be added

  • Class Modules – the VB_UserMemId and the VB_Description Attribute can be added

  • UserForm Modules – only the VB_Description Attribute can be added

  • Document Modules – no Attributes can be added (see Note for Document Modules)

The format of Procedure / Property Attributes differs from the Module Attributes in that the name of the Procedure / Property and a '.' must be included … examples below.


VB_UserMemId


This Attribute defines whether a particular Procedure or Property:

  • Is the default member of the Class … only one Procedure or Property (or Variable or Constant) can be the default member

  • Returns an enumerator such that a Collection can be enumerated using a 'For Each' loop … this can only be applied to a Function or Property Get and can only be applied to one such member

Note that you can only apply one VB_UserMemId value to any one Procedure or Property … that is, any one Procedure or Property cannot be both the default member and an enumerator. Only the values 0 (for the default member) and -4 (for the enumerator) perform any function in VBA.


You cannot set this Attribute using the VBE UI, instead see How to add or adjust Attributes that aren't accessible using the VBE UI


Default member


The Procedure or Property must either have Public or 'default' access (not Private or Friend). For a Property with a Get and Let/Set pair, you can apply it to either member.


Before I go further on this Attribute, my advice is not to use it … I never do. Default members are a disaster-in-waiting and can result in hard-to-discover bugs through their accidental use. Avoid default members, don't create your own and don't use the default members of built-in objects. Having said that …


Here is an example of this Attribute applied to a Property Let. Note the Property name is used before the '.' and Attribute name.

Having done this, you can then use code like this (where c1 is an instance of the Class)

Instead of the much better (as the intention of the code is explicit)

You can validate which member is the default member using the Object Browser as the default member has a 'blue dot' icon instead of the usual Procedure or Property icon (the word 'Default' is also included in the Object Browser description).


Enumerator


Here is an example of this Attribute applied to a Function in a Class Module.

The Function (or Property Get) must return an IUknown (or a Variant containing an IUnknown) and must have either Public or 'default' access. It does not have to be called NewEnum (but is called that by convention). mColl is a Collection defined and instantiated in the same Class, for example

You will also need a Procedure to add items to the Collection (and obviously you can add other Procedures or Properties to remove items and perform other actions on the Collection), for example

In another Module, having created a new instance of the Class and then added some Strings to it using the AddItem Procedure, you can then iterate over them, for example (where c1 is an instance of the Class a v is a Variant)

VB_Description


This Attribute defines whether a Procedure or Property has a description … the description being visible in the Object Browser. If you apply a different description to the Let/Set vs Get for the same Property, the uppermost in the Module will be the visible description.


You cannot set this Attribute using the VBE UI, instead see How to add or adjust Attributes that aren't accessible using the VBE UI


Here is an example of this Attribute applied to a Sub. Note that the speech marks in the description are escaped (with another speech mark).

VB_ProcData.VB_Invoke_Func


This Attribute is an oddity in that it is host-specific – that is, it only works in Excel. Modules containing this Attribute that are imported into a VBE being hosted by other applications appear to ignore this Attribute (ie it isn't automatically removed but it serves no purpose).


The Attribute serves two purposes and its value is made up of 3 parts:

  • The first character governs the first purpose of this Attribute: it is a single character defining the keyboard shortcut key used to run the procedure, or is a space character meaning 'no shortcut'. Any such shortcut always uses the Ctrl key and also uses the Shift key if the character requires it (so in the example below, the character is an uppercase letter 'Q' which does require the Shift key and therefore the keyboard shortcut is Ctrl+Shift+q; if the character were a lowercase letter 'q' which does not require the Shift key then the keyboard shortcut would be Ctrl+q).

  • Following the first character is "\n" - this appears to be a delimiter only.

  • Following that is a number governing the second purpose of this Attribute: it defines the Excel function category that a user-defined Functions is shown in within the Excel UI - 14 means "User Defined" (see the Remarks section at Application.MacroOptions for a full list).

Other than adding this Attribute manually, there are 3 ways (that I know of) that you can use to add this Attribute:

  • When using the macro recorder in the Excel UI (e.g. Developer > Record Macro) and you set a value for the 'Shortcut key' field (the Excel function category ... i.e. the part of the Attribute following "\n" ... will default to "User Defined). The macro recorder can also add a description (using the VB_Description Attribute) … see the example code below).

  • When using the 'Macro Options' dialog (e.g. Developer > Macros, select a macro then Options) and you set a value for the 'Shortcut key' field for a Sub in a Standard or Document Module. As with the macro recorder, the Excel function category will default to "User Defined" and this can also add a description.

  • Using the Application.MacroOptions method (see the MS docs for Application.MacroOptions) with: for the shortcut key - True for the HasShortcutKey parameter and with an uppercase or lowercase letter for the ShortcutKey parameter; for the Excel function category - an integer for the Category parameter


The details – Variable / Constant Attributes


Again, as with the Procedure and Property Attributes, which Variable and Constant Attributes can be added depends on the type of Module:

  • Standard and UserForm Modules – only the VB_VarDescription Attribute can be added

  • Class Modules – the VB_VarUserMemId and the VB_VarDescription Attribute can be added

  • Document Modules – no Attributes can be added (see Note for Document Modules)

As with Procedure / Property Attributes, the name of the Variable / Constant and a '.' must be included. Note that the names of the Attributes for Variables and Constants are different to those for Procedures and Properties, they include 'Var' in the Attribute name … examples below.


VB_VarUserMemId


This Attribute defines whether a particular Variable or Constant is the default member of the Class … only one Variable or Constant (or Procedure or Property) can be the default member (when applied to a Variable or Constant, the VB_VarUserMemId Attribute cannot be used to define an enumerator).


The Variable or Constant can have any access modifier (including default) though typically will be Public. You cannot make a WithEvents Variable the default member (the Attribute will be removed by the VBE when you import the Module).


You cannot set this Attribute using the VBE UI, instead see How to add or adjust Attributes that aren't accessible using the VBE UI


As with a Procedure or Property, before I go further on this Attribute, my advice is not to use it … I never do. Default members are a disaster-in-waiting and can result in hard-to-discover bugs through their accidental use. Avoid default members, don't create your own and don't use the default members of built-in objects. Having said that …


Here is an example of this Attribute applied to a Variable.

Having done this, you can then use code like this (where c1 is an instance of the Class)

Instead of the better (as the intention of the code is explicit)

As with a default member that is a Procedure or Property, you can validate which member is the default member using the Object Browser as the default member has a 'blue dot' icon instead of the usual Variable or Constant icon (the word 'Default' is also included in the Object Browser description).


VB_VarDescription


This Attribute defines whether a Variable or Constant has a description … the description being visible in the Object Browser. You cannot add a description for a WithEvents Variable (the Attribute will be removed by the VBE when you import the Module).


You cannot set this Attribute using the VBE UI, instead see How to add or adjust Attributes that aren't accessible using the VBE UI


Here is an example of this Attribute applied to a Constant. Note that the speech marks in the description are escaped (with another speech mark).


Examples


If you want examples for some of the Attributes (descriptions, enumerators, defaults instances and default members are all covered) then please download the below Zip file which contains files for one Standard and two Class Modules. You can just review the code or load them into the VBE and run the Procedures in the Standard Module for a demo.


Limitations


As with all information on my website, this blog post applies to Excel, Word, PowerPoint and Outlook running on Windows devices. Other applications hosting the VBE may use additional Attributes. They are intentionally not covered here.


2 comments

2 Comments


J. Woolley
J. Woolley
Aug 13, 2022

Great article. I hope you don't mind if I reference it in My Excel Toolbox.

Re. Procedure/Property Attributes, VB_Description: "You cannot set this Attribute using the VBE UI...." Perhaps you can.

  1. Open the Object Browser in VBE

  2. Select the appropriate Library or search for the Procedure

  3. Under Members..., right-click the Procedure and pick Properties

  4. In the Member Options dialog, enter Description

You can also describe a macro (Public Sub w/o parameters) in Excel's UI:

Developer > Macros, pick the macro and click Options.

J. Woolley

Like
John
John
Aug 14, 2022
Replying to

Hi J, happy for you to reference the article.


Thanks for the correction re Procedure/Property Attributes.

Like
bottom of page