By: Stan Leszynski
Developers by nature have this love/hate thing about naming conventions. Such standards are often seen as slowing the development process, increasing the size of object names and files, and stifling true programming creativity. And yet, without order,
the laws of entropy invariably draw every project toward incoherent "spaghetti code" and/or "spaghetti objects." Thus, few developers would argue against the need for an ordered approach to development, but they want the system that is
least intrusive.
Sorry, but you can't have it both ways! A system that is comprehensive and applied consistently will also by nature be mildly intrusive. If you want to apply a naming convention to your objects, you will incur a penalty of a few keystrokes every
time you type an object name. However, the small pain of extra keystrokes certainly produces a large gain.
Creating your own naming conventions takes research, group effort, and testing. To complicate matters, there are several different approaches you can take when naming objects. For a complete discourse on designing your own naming conventions, see the
book Access Expert Solutions by Stan Leszynski, published by Que Corporation.
In this appendixdocument, I detail for you the Leszynski Naming Conventions ("LNC"), a set of standardized approaches to naming objects during Visual Basic ("VB") development. These naming conventions were born
of necessity, since some members of my staff spend all day in VB development, year after year. They were also born of a different needa void that existed in the marketplace due to a lack of consensus about development styles among leading VB
application developers.
Our Visual Basic conventions are tightly linked with our conventionsnow also called LNC, formerly called L/Rfor Microsoft Access for Windows 95 and the Microsoft Jet database engine. The L/R conventions for Access were
distributed broadly, with over 500,000 copies in print, and became the most widely accepted conventions in the Access user community. Over the last few years, we have received feedback about L/R from hundreds of developers and companies, and have
tried to accommodate some of their input, as well as our ongoing experiences, into LNC documents for both Access and Visual Basic.
LNC assumes that most VB developers also work with other Microsoft development tools: Access, Excel, SQL Server, and others. Microsoft's development products have more in common in their '95 versions than in any previous iterations.
Consequently, this VB style dovetails with the LNC development style detailed in the Leszynski Naming Conventions for Microsoft Solution Developers, a separate document which covers all of Microsoft's application development products.
This document includes Jet conventions and examples in recognition of the fact the Jet has become the default database engine for many VB developers. More detailed style information for working with Access and Jet is found in the Leszynski Naming
Conventions for Microsoft Access document.
I use the terms naming conventions, style, and LNC interchangeably throughout this document.
Naming conventions are one of the foundation elements of your overall development style. We developed our naming conventions primarily to achieve four objectives:
To meet these objectives, we create and apply consistent naming conventions to these application objects:
The term database in the preceding listthis table refers to using VB against Jet and SQL Server data. While Jet is discussed in this document, naming conventions for NT SQL Server are documented in the Leszynski Naming Conventions for Microsoft Solution Developers paper.
Object names are the foundation on which your entire application is built, so they are almost impossible to change once development has begun in earnest. Therefore, you probably won't find it cost or time-efficient to retrofit these conventions into
your existing applications. For new applications, however, you should apply these naming conventions consistently from the moment you create your first object in a new project file.
LNC relies primarily on leading tagsseveral characters placed before an object's name (for example, frmCust). This approach is sometimes referred to as Hungarian notation. (The term Hungarian refers to the nationality of
Charles Simonyi, a programmer at Microsoft who wrote a doctoral thesis in the 1980's called "Program Identifier Naming Conventions"). Leading tags provide several benefits:
If you are averse to Hungarian notation for some reason and prefer trailing tags, LNC will still work for you. However, LNC prescribes no standard for locating and punctuating trailing tags. You will have to decide if they are offset with
an underscore (Order_fmdi), or by capitalization (OrderFMdi), or by some other technique. Remember also that you should be consistent throughout your style, so if you use trailing tags for objects, you will need to use them when writing VB code as
well.
For purposes of this document, we have created the standardized terminology in Table B.1 for grouping objects. We will use these group names when discussion naming conventions.
VB Objects | VBA Objects | Database Objects |
Class modules | Procedures | Tables |
Forms | Variables | Table fields |
Form controls | Constants | Queries |
Modules | User-defined types |
In LNC, object names are constructed using this syntax:
[prefix(es)] tag [BaseName] [Qualifier] [Suffix]
The brackets indicate optional syntax elementsdo not include them in your actual object names. Notice that the tag element is required even though the BaseName is not in some cases. These options will be explained later in this
document. Note in the syntax diagram that the case of each element reflects its case in actual use. The element tag is in lower case since the tags themselves are always lower case. Table B.2 shows sample object names using these constructions.
Object Name | Prefix(es) | Tag | BaseName | Qualifier | Suffix |
frmCust | frm | Cust | |||
qsumSalesPerfBest_WA | qsum | SalesPerf | Best | _WA | |
plngRecNumMax | p | lng | RecNum | Max | |
ialngPartNum | ia | lng | PartNum |
A prefix is an identifier that precedes a tag and clarifies it narrowly. Prefixes describe one or more important properties of an object. For example, a Long variable that is public in scope (declared Public) has a prefix p, as in
plngRecNumMax. Prefixes are one or two characters long and in lower case. Multiple prefixes can be used together on one object, as in ialngPartNum, where i and a are both prefixes.
A tag is a multi-character string placed against an object base name to characterize it. In object-oriented programming terms, the tag is basically an identifier for the class. Note that the word class here refers to a naming
convention construction, not an exact object model construction. For example, there is only one Query (or QueryDef) class object in Jet, and the data action (delete, update, and so on.) is determined by its SQL statement, not its class. Nevertheless,
LNC prescribes several tags for this one Jet class.
Tags are three or four characters long for readability and to allow for the hundreds of combinations necessary as the Microsoft Office object model grows over time. They are always to the left of the base name and in lower case, so that your eye reads
past them to the beginning of the base name.
A tag is created to mnemonically represent the word it abbreviates, such as "frm" for "form". However, some tags may not seem fully mnemonic for three reasons. First, the perfect (or obvious) tag for a particular new object may
already be assigned to another object in a product that existed previously. Secondly, where common objects (objects with similar properties and usage) exist in multiple Microsoft applications, the tag for one may be used to represent similar objects in
other products, even if the names are different. For example, Visual Basic Shape objects and Access Rectangle objects share the tag shp in LNC, since they are very similar objects structurally. Finally, there may not be such a thing as an
"obvious" tag, so a suitable one may be chosen from a body of several reasonable candidates.
The base name is the starting point when you name a particular objectthe name you would use anyway if you had no naming conventions. The LNC guidelines for creating base names are driven by a set of rules stated later in this
document.
A qualifier is an extension following the base name that provides context to the specific use of an object. Unlike prefixes, which detail properties of the object (for example, that the variable has public scope), qualifiers describe how the
object is being used in a context. For example, plngRecNumMax is obviously the maximum record number, in an application that could also have variables for the minimum (plngRecNumMin) and current (plngRecNumCur) record numbers. Qualifiers are short and
written with mixed upper and lower case, as in the examples in Table B.3.
Qualifier | Usage |
Curr | Current element of a set |
Dest | Destination |
First | First element of a set |
Hold | Hold a value for later re-use |
Last | Last element of a set |
Max | Maximum item in a set |
Min | Minimum item in a set |
Next | Next element of a set |
New | New instance or value |
Old | Prior instance or value |
Prev | Previous element of a set |
Src | Source |
Temp | Temporary value |
Suffix elements provide specific information about the object and are used only as "tie-breakers" when more detail is required to differentiate object names that could otherwise legitimately be identical. Suffixes are the only element
in the syntax diagram where LNC does not suggest standardized values. You will create suffix items as needed by your company, development team, or application. For example, a series of queries that summarized the best sales performance by state
would need the state name in each object name to properly qualify it, as in qsumSalesPerfBest_AK. Placing the state name at the very end of the name as a suffix item allows the entire collection of related queries to sort together, like this:
qsumSalesPerfBest_AK qsumSalesPerfBest_AL ... qsumSalesPerfBest_WY
Since the suffix is the last piece of information on a name, it can be easier for the eye to find if delimited from the rest of the object name with an underscore, as shown, but this convention is optional.
The building blocks of your application are its objects. When creating base names for VB objects, you should give careful consideration to the purpose of the object, the approaches used to name associated objects, and the rules of thumb that follow for
naming objects.
Your Visual Basic project can consist of many files, and good development style often dictates that you keep all files for a project in the same directory. However, with the advent of long file names, I have found it helpful to give each project a
unique abbreviation and apply the characters as a tag for files in the project. This helps me to:
Table B.4 lists the tags for Visual Basic module objects.
Object | Tag |
Class module | cls |
Standard module | bas |
VB applications usually consist of many forms. While it is acceptable to tag every form with frm, LNC provides the opportunity to be more specific about the nature of each form, as seen in Table 5. While object name sort order is not enforced in
the Project window (Dear Microsoft, I wish you treated object names with greater importance than file names in the Project window...), viewing forms through the Object Browser is easier with
meaningful object tags.
Object | Tag |
Form | frm |
Form (dialog) | fdlg |
Form (lookup table) | flkp |
Form (menu/switchboard) | fmnu |
Form (message/alert) | fmsg |
Form (wizard main) | fwzm |
Form (wizard subform) | fwzs |
MDI form | fmdi |
MDI child form | fmdc |
Table B.6 lists the tags for control objects on forms, and Table B.7 provides tags for critical OLE control types. VBA code written behind forms using this convention will reflect a control's type in its event procedure names (for
example cboState_AfterUpdate). The automatic sorting provided by this notation in the VB IDE can be very helpful during development. All control tags are three characters long.
Control | Tag | Constant Prefix | VB 4 Docs | Class |
AniButton | ani | ani | none | AniButton |
CheckBox/3D | chk/chk3 | none/ss | chk | CheckBox |
ComboBox | cbo | none | cbo | ComboBox |
CommandButton/3D | cmd/cmd3 | none/ss | cmd | CommandButton |
CommonDialog | cdlg | cdl | none | CommonDialog |
Communications | com | com | none | Communications |
Control (generic) | ctl | none | none | n/a |
Data | dat | vb | dat | Data |
DBCombo | dcbo | dbl | dbc | DBCombo |
DBGrid | dgrd | dbg | dbg | DBGrid |
DBList | dlst | dbl | dbl | DBList |
DirListBox | dir | none | dir | DirListBox |
DriveListBox | drv | none | drv | DriveListBox |
FileListBox | fil | none | fil | FileListBox |
Frame/3D | fra/fra3 | none/ss | fra | Frame |
Gauge | gau | gau | none | Gauge |
Graph | gph | gph | none | Graph |
Grid | grd | none | grd | Grid |
GroupPushButton | gpb3 | ss | none | GroupPushButton |
HScrollBar | hsb | vb | hsb | HScrollBar |
Image | img | none | img | Image |
KeyStatus | key | key | none | KeyStatus |
Label | lbl | none | lbl | Label |
Line | lin | none | lin | Line |
ListBox | lst | none | lst | ListBox |
MAPIMessage | mpm | map | none | MAPIMessage |
MAPISession | mps | map | none | MAPISession |
MaskedEdit | msk | msk | none | MaskedEdit |
MCI | mci | mci | none | MCI |
Menu | mnu | vb | mnu | Menu |
Menu (shortcut) | mct | n/a | none | Menu |
OLEContainer | ole | vb | ole | OLEContainer |
OptionButton/3D | opt/opt3 | none/ss | opt | OptionButton |
Outline | out | out | none | Outline |
Panel | pnl3 | ss | none | Panel |
PictureBox | pic | vb | pic | PictureBox |
PicClip | clp | none | none | PicClip |
RemoteDataControl | rdc | rd | none | RemoteDataControl |
Report | rpt | none | none | Report |
Shape | shp | vb | shp | Shape |
SpinButton | spn | spn | none | SpinButton |
Tab | tab | ss | none | Tab |
TextBox | txt | none | txt | TextBox |
Timer | tmr | none | tmr | Timer |
VScrollBar | vsb | vb | vsb | VScrollBar |
The trailing 3 on the tags for 3D controls is included for backward compatibility with VB3 projects using THREED.VBX, but is not required by LNC for controls in new VB4 projects.
Some conventions attempt to catalog or create tags for third-party VBX and OLE controls. Such an effort is beyond the scope of this documentI take responsibility here only for helping you use controls that are part of a VB developer's standard
tool set or are created by my company. A starting point if you are interested in tags for third-party controls is the document "Microsoft Consulting Services Naming Conventions for VB" on the Microsoft Developer Network CD subscription.
Control | Tag | Source | File Name | Class Name |
Calendar | cal | Access | MSACAL70.OCX | MSACal70 |
Kwery Calendar | kcal | Kwery | KCCAL32.OCX | KCCalendar |
Kwery Clock | kclk | Kwery | KCCLOK32.OCX | KCClock |
Data Outline | dout | ADT | DBOUTL32.OCX | DataOutline |
Kwery Gauge | kgau | Kwery | KCGAGE32.OCX | KCGauge |
Image List | ilst | VB | COMCTL32.OCX | ImageList |
List View | lvw | VB | COMCTL32.OCX | ListView |
Kwery Preview | kpvw | Kwery | KCPRVW32.OCX | KCPreview |
Progress Bar | pbr | VB | COMCTL32.OCX | ProgressBar |
Rich Text Box | rtf | VB | RICHTX32.OCX | RichTextBox |
Slider | sld | VB | COMCTL32.OCX | Slider |
Status Bar | sbr | VB | COMCTL32.OCX | StatusBar |
Tab Strip | tabs | VB | COMCTL32.OCX | TabStrip |
Toolbar | tbr | VB | COMCTL32.OCX | Toolbar |
Tree View | tvw | VB | COMCTL32.OCX | TreeView |
Kwery Wheel | kwhl | Kwery | KCWHL32.OCX | KCWheel |
Most VB coders use a standard menu naming convention already, which consists of the tag mnu before a menu control base name built of the menu's options, as in mnuFileExit. This technique will cause menu options to sort in a very distinct order in the
property dialog, and is acceptible for LNC.
In addition to standard bar and drop-down menu combinations, you can create pop-up or "shortcut" menus in VB 4. LNC suggests that you prefix these objects with the mct tag to keep the menu items grouped together when sorted.
"Shortcut" is the term used by Windows 95 for context menus, so I prefer using it over the terms "pop-up menu" and "context menu" used in the VB documentation.)
When creating base names for VBA objects, remember that the base name must be descriptive even in the absence of its tag. For some programmers, the syntax Dim I As Integer for a loop variable is quite acceptable. Within LNC,
however, the variable named I would become iintLoopan index integer variable to control a loop. Single-character variable names, especially without tags, are not allowed. Instead, create a list of short and standardized work variables to
handle common daily needs (see tTable B.11 later in this document).
Crafting VBA object base names involves creating and following simple rules such as these:
Note that Rule 6 requires a reference in variable names to objects of any type that they relate to. For example, a Recordset variable created on tblCust should be named rstCust. Also, if a string array variable of part numbers astrPartNum had an
Integer index variable, it should include the array's base name in its own sans tagging: iaintPartNum.
There is no LNC guideline limiting variable name length, but common sense dictates that variable names longer than 15 or 20 characters waste a lot of keystrokes at each use. For procedure names, the VBA module editor by default show the first 30
characters of a procedure name, so this number is suggested as the target maximum procedure name length.
Abbreviate VBA object base name elements wherever possible using a standardized abbreviation table such as the one in the section "Standardized Abbreviations." You can extend LNC by creating your own standard abbreviations. You should
also create and use standardized terminology in your applications wherever possible, for examples see the section "Standardized Terminology."
Procedure base names should follow the construction ObjectVerb, where the Object portion describes the primary object type affected (often the same as the primary argument), and Verb describes the action. This style sorts functions
and subs by their target object when shown in ordered lists:
FormCtlHide FormCtlShow FormPropAdd FormPropGet FormPropSet
We find this sort order much more appealing than the more common alternative with VerbObject construction:
AddFormProp GetFormProp HideFormCtl SetFormProp ShowFormCtl
In LNC, tags are required for the following VBA objects:
Optional tags also are available for some types of procedures.
In the syntax diagram earlier we noted that base names are optional in some constructions. When you are programming in VBA, the tag element is always required, but the base name is optional for variables local to a procedure. For example,
a procedure that declares only one form object variable can legitimately use the variable name frm, which is a tag without a base name. Normally, however, I prefer more detail. Type structures, constants, and variables that have module-level or public
scope must have both a tag and base name.
VBA variable tags are noted in Tables B.8 through B.10 below, grouped by type of variable.
Variable Type | Tag |
Boolean | bln |
Byte | byt |
Conditional Compilation Constant | ccc |
Currency | cur |
Date | dtm |
Double | dbl |
Error | err |
Integer | int |
Long | lng |
Object | obj |
Single | sng |
String | str |
User-Defined Type | typ |
Variant | var |
In Table B.8, the Conditional Compilation Constant, Error, and User-Defined Type items are not true data types (created with Dim name As datatype), but rather are programming concepts. A Conditional Compilation Constant variable is a flag of type Boolean, an Error variable is a Variant created with the CVErr() function, and Types are unique user-defined constructs.
Object | Tag | Object | Tag |
AddInManager | add | ListImages | lsis |
App | n/a | Menu | mnu |
Application | app | MenuItem | mni |
Button | btn | MenuItems | mnis |
Buttons | btns | MenuLine | mnl |
Clipboard | n/a | Node | nod |
Collection | col | Nodes | nods |
Column | clm | Panel | pnl |
Columns | clms | Panels | pnls |
ColumnHeader | chd | Picture | pic |
ColumnHeaders | chds | Pictures | pics |
Component | cmp | Printer | prn |
Components | cmps | Printers | prns |
Control | ctl | ProjectTemplate | tpl |
Controls | ctls | Property | prp |
ControlTemplate | ctp | Properties | prps |
ControlTemplates | ctps | RowBuffer | row |
Debug | n/a | Screen | n/a |
Err | n/a | SelBookmark | sbk |
FileControl | flc | SelBookmarks | sbks |
Font | fnt | SelectedComponents | scms |
Form | frm | SelectedControlTemplates | scts |
Forms | frms | SubMenu | msub |
FormTemplate | ftpl | Tab | tab |
ListImage | lsi | Tabs | tabs |
Object | Tag | ||
Container | con | QueryDef (Paradox) | qpdx |
Containers | cons | QueryDef (SQL Server) | qsql |
DBEngine | dbe | QueryDef (Text) | qtxt |
Database (any type) | dbs | QueryDefs | qdfs |
Database (Btrieve) | dbtv | Recordset (any type) | rst |
Database (dBASE) | ddbf | Recordset (Btrieve) | rbtv |
Database (Excel) | dxls | Recordset (dBASE) | rdbf |
Database (FoxPro) | dfox | Recordset (dynaset) | rdyn |
Database (Jet) | djet | Recordset (Excel) | rxls |
Database (Lotus 1-2-3) | dwks | Recordset (FoxPro) | rfox |
Database (ODBC) | dodb | Recordset (Lotus 1-2-3) | rwks |
Database (Paradox) | dpdx | Recordset (ODBC) | rodb |
Database (SQL Server) | dsql | Recordset (Paradox) | rpdx |
Database (Text) | dtxt | Recordset (snapshot) | rsnp |
Databases | dbss | Recordset (SQL Server) | rsql |
Document | doc | Recordset (table) | rtbl |
Documents | docs | Recordset (Text) | rtxt |
Dynaset | dyn | Recordsets | rsts |
Error | err | Relation | rel |
Errors | errs | Relations | rels |
Field | fld | Snapshot | snp |
Fields | flds | Table | tbl |
Group | gru | TableDef (any type) | tdf |
Groups | grus | TableDef (Btrieve) | tbtv |
Index | idx | TableDef (dBASE) | tdbf |
Indexes | idxs | TableDef (Excel) | txls |
Parameter | prm | TableDef (FoxPro) | tfox |
Parameters | prms | TableDef (Jet) | tjet |
Property | prp | TableDef (Lotus 1-2-3) | twks |
Properties | prps | TableDef (ODBC) | todb |
QueryDef (any type) | qdf | TableDef (Paradox) | tpdx |
QueryDef (Btrieve) | qbtv | TableDef (SQL Server) | tsql |
QueryDef (dBASE) | qdbf | TableDef (Text) | ttxt |
QueryDef (Excel) | qxls | TableDefs | tdfs |
QueryDef (FoxPro) | qfox | User | usr |
QueryDef (Jet) | qjet | Users | usrs |
QueryDef (Lotus 1-2-3) | qwks | Workspace | wsp |
QueryDef (ODBC) | qodb | Workspaces | wsps |
In Tables B.9 and B.10, tags for collection variables are made by adding s after the tag for the object type stored in the collection, as in usr for User and usrs for Users. The tags dyn, snp, and tbl for Dynaset, Snapshot, and
Table objects are directly relevant to users of Jet 1 and Jet 2. Starting with Jet 3, these object types are allowed only as a subtype of Recordset variables, thus the Recordset tags rdyn, rsnp, and rtbl.
Even though we noted previously that a tag by itself is a legitimate variable name, a few variable tags shown (such as int) are VBA reserved words and will not compile in your procedures. Such tags require a base name.
Instead of using I and J as work variable names, use names that are still short but meaningful. For example, even iintI and iintJ are more descriptive than I and J, although I'd never use them. Instead, I try to keep a short list of
handy work variables and reuse these variables where practical. Table B.11 suggests the LNC approach to commonly-used variables.
Variable | Description |
blnRet | Captures a True/False return value from a function call |
cccDebug | Creates a conditional compilation constant for toggling conditional debugging |
intErr | Preserves the value of Err |
iintLoop | Provides a counter for For. . .Next loops |
intMsg | Captures a return value from a MsgBox() function call |
intResult | Holds the result of math operations (also dblResult, lngResult, and so on.) |
intRet | Captures a numeric return value from a function call (also dblRet, lngRet, and so on.) |
intWork | Used for any temporary work (also dblWork, lngWork, and so on.) |
strMsg | Used to build long message box strings |
strOrder | Used to build long SQL ORDER BY strings |
strSQL | Used to build long SQL strings |
strWhere | Used to build long SQL WHERE clauses |
Table B.12 lists entry points for common OLE server applications.
Object | Tag |
Access.Application | accapp |
DAO.DBEngine | daodbe |
Excel.Application | xlsapp |
Excel.Chart | xlscht |
Excel.Sheet | xlssht |
Graph.Application | gphapp |
MAPI.Session | mpsmps |
MSProject.Application | prjapp |
MSProject.Project | prjprj |
OfficeBinder.Binder | bndbnd |
PowerPoint.Application | pptapp |
SchedulePlus.Application | scdapp |
SQLOLE.SQLServer | sqlsvr |
Word.Basic | wrdbas |
Note that variables for objects in the object hierarchy of a referenced type library can be dimensioned directly by class, as in this line:
Dim xlsapp As Excel.Application
Alternately, if the variable is created with late binding (that is as a generic object) rather than early binding, the prefix o is added to denote an object variable:
Dim oxlsapp As Object Set oxlsapp = CreateObject("Excel.Application")
The naming convention for entry points into OLE server applications follows this syntax:
applicationtag [entrypointtag] primaryobjecttag BaseName
The item applicationtag is a three-character notation for the server application, and entrypointtag is three characters denoting the entry point used. The entrypointtag is optional and should be used when clarification is necessary
(when variables for several entry points are declared in the same procedure), or when the entry point is not the standard Application object. The primaryobjecttag describes the ultimate class of the object (the one you intend to address with the
variable). The BaseName is optional and clarifies the use of the variable, as with other VBA variables.
For example, the following code creates an Excel Range object and manipulates it.
Sub SalesCheck() Dim xlswksSales As Excel.Worksheet Dim xlsrngYTD As Excel.Range Set xlswksSales = GetObject("C:\Data\Sales.Xls", "Excel.Sheet") Set xlsrngYTD = xlswksSales.Range("YTDSales") If xlsrngYTD.Value < 100000 Then MsgBox "Sales are lame.", vbOKOnly, "Get to Work!" End If Set xlswksSales = Nothing End Sub
In this example, the Range object is technically several layers deep in the application hierarchy, and a purely accurate combination of tags and code structure would yield this line of code, which actually runs:
Set xlsappwkbwksrngYTD = _ xlsapp.ActiveWorkbook.Worksheets("Sales").Range("YTDSales")
In practice, of course, such nomenclature is unwieldy, and the shorter style is accurate but more friendly.
I prefer to show the server name in the variable declaration for clarity of code. While both lines below will run, the second is less ambiguous:
Dim xlsrng As Range Dim xlsrng As Excel.Range
See the section "Creating Your Own Tags" for more discussion of OLE syntax. See the Leszynski Naming Conventions for Microsoft Solution Developers document for
a complete listing of tags for Microsoft OLE servers and objects.
The capabilities of the Remote Data Objects and the RemoteData control in VB 4 to work with ODBC data sources, and the structure of the objects themselves, makes it tempting to compare RDO and Jet objects. While there are many commonalities, there are
also enough differences that we opted to create separate tags for use with RDO, as shown in Table B.13.
Object | Tag |
rdoColumn | rdclm |
rdoColumns | rdclms |
rdoConnection | rdcnn |
rdoConnections | rdcnns |
rdoEngine | rdeng |
rdoEnvironment | rdenv |
rdoEnvironments | rdenvs |
rdoError | rderr |
rdoErrors | rderrs |
rdoParameter | rdprm |
rdoParameters | rdprms |
rdoPreparedStatement | rdprs |
rdoPreparedStatements | rdprss |
rdoResultset | rdrsl |
rdoResultsets | rdrsls |
rdoTable | rdtbl |
rdoTables | rdtbls |
The prefixes for VBA variables can be categorized into two groups: prefixes for scope, and all other prefixes. Since the model for variable scope has changed somewhat in VB 4, I will discuss scope prefixes first. The following prefixes are ordered by
increasing (broader) scope.
Use no prefix for variables that are local to a procedure. | |
s | Place this prefix before variables that are declared locally to a procedure with a Static statement. |
m | Use this prefix for module-level variables that are declared with Dim or Private statements in the Declarations section of a module. |
p | Use this prefix to denote variables declared as Public in the Declarations section of a module. This prefix is new to the '95 conventions and supplements the g prefix. |
g | Use this prefix to denote variables declared as Public or Global in the Declarations section of a standard module. Such variables are truly global and may be referenced from procedures in the current project or other projects. |
When used, scope prefixes always begin a variable name and precede any other prefixes.
In addition to scope, other characteristics of variables can be identified by prefixes:
a | Use this prefix to denote a variable that is declared as an array, including a ParamArray argument to a function. |
c | This prefix is placed before constants defined with the Const statement. |
e | Use this prefix for a variable that is an element of a collection. Such variables are usually part of a For Each . . . Next loop structure. |
i | Use this prefix to denote a variable (usually of type Integer) that serves as an index into an array or an index counter in a For . . . Next loop. |
n | Use this prefix for variables that are Optional arguments (named parameters) passed in to a procedure. |
o | This prefix is placed before object variables that reference OLE Automation servers through late binding (an Object variable), where the tag denotes the type of server. |
r | Use this prefix for variables that are arguments (parameters) passed in to a procedure and declared as ByRef, or not declared as either ByRef or ByVal (including a ParamArray), which implies ByRef. |
t | Use this prefix to describe a variable that is declared as a user-defined Type structure. The variable should inherit the base name from the original declaration for the type. |
v | Use this prefix for variables that are arguments (parameters) passed in to a procedure and declared as ByVal. |
A prefix provides a very detailed description of a variable. The number of allowable prefix combinations is limited, as shown in Table B.14.
Any One of These. . . | . . .Can Come Before This |
s, m, p, g, r, v | a |
m, p, g | c |
s, m, p, g, r, v | e |
s, m, p, g, r, v | i |
s, m, p, g, r, v | ia |
s, m, p, g, r, v | o |
n | r |
m, p, g | t |
n | v |
Variables require a unique prefix when declared Public in a widely-distributed application to prevent name contentions. See the "Tags and Prefixes for Procedures" section for more information.
VB 4 introduced some changes in the area of constants. The changes most relevant to naming conventions include these:
When creating constants, use a scope prefix (if appropriate), the prefix c, and the suitable tag for the constant's data type. To properly synchronize the tag, the data type, and the value, do not let VB assign the type; always use the full
"Const name As datatype" syntax.
Constants require a unique prefix when declared Public in a widely-distributed application to prevent name contentions. See the following section for more information.
Whether and how to prefix and tag procedure names is a debatable subject. In general, this style neither requires nor encourages placing characters before a procedure name except, in the following situations.
Procedures can have scope similar to that of variabless (Static), m (Private), p (Public), or g (global Public). LNC allows, but does not encourage, the use of these scope prefixes on function names if they
solve a particular need, and are used consistently throughout an application.
If you are creating code libraries for retail sale, for inclusion in the public domain, or for broad distribution in some other manner, LNC recommends that you prefix Public variables, constants, and procedures with a unique prefix
identifying you, your company, or the application. The prefix consists of two to four unique characters (optionally followed by an underscore), and prevents your object names from conflicting with object names in the host project, or in other referenced or
referencing applications on a user's machine.
To create an author prefix, use your personal or company initials. For example, author prefixes for my companies are lci_ for Leszynski Company, Inc. and kwc_ for Kwery Corporation. Before using your selected prefix, make an effort to determine if the
prefix is already widely in use.
With the large number of methods and properties listed in the Object Browser for most objects, differentiating built-in attributes of objects from those added during development can be a challenge. Procedure tags in class or form modules add a high
degree of order to working with user- defined elements in the Object Browser (and other sorted lists), by clearly grouping custom procedures, methods, and properties apart from built-in object attributes.
On the other side of the coin, some developers feel strongly that procedure names should not have tags, especially in OLE Automation server applications. Before you blindly accept or condemn the use of tags in this context, try it awhile and then
decide for yourself.
The LNC style prescribes the following naming convention tags for procedures:
cbf. | Use this tag on procedure names for general code inside a class module or form. |
mtd. | Use this tag on custom method procedures defined for class modules. |
prp. | Use this tag on Property procedure names defined in class modules with Property Get, Property Let, and Property Set statements. |
LNC does not require or suggest assigning a data type tag to functions to reflect their return value. However, if you have a specific need to tag procedures to reflect their return value type, use the appropriate tags from the
prior "Tags for Variables" section and apply them consistently to all procedures in an application.
Table B.15 shows examples of VBA variables applying the various conventions for VBA objects.
Declaration | Description |
Dim oxlsappBudget As ObjectFunction lci_ArraySum (ParamArray | Excel.Application |
ravarNum() As Variant) As Double | Company identifier |
Public giaintPartNum As Integer | Global index into array |
Const clngCustNumMax As Long = 10000 | Const for max CustID |
Function FileLock(ByVal vstrFile As String) As Boolean | ByVal argument |
The data building blocks of many data-centric VB applications are Jet database objects. Creating names for database objects is no less important than creating VB application object names.
The rules for database object base names are similar to those for VBA objects expressed earlier. Follow these rules when developing a base name for a new database object:
Rules 1 and 2 also apply to the other naming convention elements: prefixes, tags, qualifiers, and suffixes. These elements should never include spaces or special characters.
Previously, some developers used all lower case names to allow for upsizing to Microsoft SQL Server. Starting with version 6.0, that product is now installed case-insensitive and allows you to maintain upper and lower case in object names that are moved to the server from Access.
You should abbreviate object base name elements wherever possible using a standardized abbreviation table such as the one in the section "Standardized Abbreviations." You can extend LNC with your own standard abbreviations as well. You
should also create and use standardized terminology in your applications wherever possible. For examples, see the section "Standardized Terminology."
LNC includes some constraints and suggestions for object name lengths. We target our table name length at 15 characters maximum, for two reasons:
Beyond the 15 character target, we absolutely limit our table name lengths to 30 characters, which maintains compatibility with the table name length limit in SQL Server. For other objects, we target a 30 character limit as well, because
the Access and VB interfaces show no more than the first 30 characters of object names in the default width of any lists or property grids.
The name of an object that is driven by a table must include the base name of the table. Thus, for the tblCust table, the primary query would be qryCust, the primary form frmCust, and so forth. Queries and forms that are sourced from multiple tables
should reflect the base names of all the tables if it is practical. If not, you must decide which tables are the primary tables and list as many as possible in the name. Generally, in a multi-table query or form, the most "important" tables are
not necessarily the first and second, but more often the first and last. So, a query joining tblCust to tblAddr to tblPhon to get the phone numbers for customers, would be named qryCustAddrPhon if the address information is included in the query result, or
simply qryCustPhon if the address information is used to join to the phone numbers and is not displayed.
Bound control base names on forms are always equivalent to the base name of the bound field (the ControlSource). For example, a text box tied to the LastName field is named txtLastName.
As a part of standardizing terminology, we adhere to the concept of a "integrated data dictionary". This principle dictates that any fields in the data structure with the same name must have the same properties and data purpose. For example,
if the LastName field in tblCust is of type Text 30, and holds customer last name data, any other field named LastName in the same application must have the same type, length, properties, and purpose. If your application needs last name fields for
customers and dealers, this philosophy dictates that you name them differently (such as CustLastName and DlrLastName).
Applying the integrated data dictionary principle also means that table fields do not get leading prefixes or tags, since I prefer my data dictionaries to be platform-neutral. That way, a field does not have to be renamed if data is "upsized"
or ported to a platform with different data types. A table is still called a table in SQL Server, so moving tblCust there from Jet would require no table rename. However, if tblCust had a field lngCustID defined as a Long Integer in Jet, moving the
database to SQL Server would require a field rename to intCustID, since SQL Server uses the data type name iInteger to mean the same as Jet's Long Integer. Since renaming fields affects all dependent objects and code, it should be avoided at all
costs, so I would call the field simply CustID from the start.
Qualifiers and suffixes are acceptable in field names, however, because they describe the object's data purpose and not its type, and the purpose does not change between platforms.
Object base name elements should be ordered from left to right with respect to their importance, readability, and desired sort order. In the example from the previous section, CustLastName is a better name than LastNameCust, because the group name
portion (Cust or Dlr) carries greater weight in an object's name than the specific item name (LastName or PhonNum). Think of Cust as the name of a collection of customer-related items, and this rule becomes clearwhat you are really saying is that
CustLastName is analogous to Cust(LastName) or Cust.LastName in Collection.Object terminology.
Some of you will naturally carry this example to its extreme and say that the Customers collection really has a Names collection with multiple elements, including Last, thus the representation of that idea as Cust.Name(Last) would lead to the field
name CustNameLast instead. Such a construction model still fits within the rules of LNC, and we won't debate you against using it. In practice, however, such names often become fairly unreadable, even if they are accurate.
In LNC, tags are required for Jet table and query database objects. Table B.16 lists the tags for Jet database objects.
Object | Tag |
Query | qry |
Query (form source) | q[obj] |
Query (append) | qapp |
Query (crosstab) | qxtb |
Query (data definition) | qddl |
Query (delete) | qdel |
Query (form filter) | qflt |
Query (lookup table)3 | qlkp |
Query (make table) | qmak |
Query (select) | qsel |
Query (SQL pass-through) | qspt |
Query (union) | quni |
Query (update) | qupd |
Table | tbl |
Table (linked Btrieve) | tbtv |
Table (linked dBASE) | tdbf |
Table (linked Excel) | txls |
Table (linked FoxPro) | tfox |
Table (linked Lotus 1-2-3) | twks |
Table (linked ODBC) | todb |
Table (linked Paradox) | tpdx |
Table (linked SQL Server) | tsql |
Table (linked text) | ttxt |
Table (lookup)3 | tlkp |
Table (audit log) | tlog |
Table (many-to-many relation) | trel |
Table (summary information) | tsum |
These tags provide rich detail about the objects and sort objects with similar attributes together. For example, lookup tables and their maintenance forms are often used over and over in multiple applications. The tags tlkp, qlkp, and
flkp clearly identify these objects, making it easy for you to import them from an existing database into a new one or manipulate them together in other ways. However, if a particular database does not warrant rich detail, LNC provides generic tags
to use as well (for example qry instead of qsel).
The conventions prescribe a single character tag added to the front of the full object name (including the tag) of the related object in one special case shown (q[obj]). This situation occurs where a query is created solely to serve as the data
source for one particular form, as in qfrmCust.
The following list describes the database object prefixes and their usage.
_ | (underscore). Use this prefix for objects that are incomplete and under development. When the Access Database window is sorted by object name, this prefix sorts objects to the top where they are immediately recognized as unfinished and unusable. When the object is ready for testing or deployment, remove the underscore. This prefix is not used with form controls. |
zh. | Use this prefix to denote "system" objects, which are for use by developers and application code only, and should be hidden from the user by default. In LNC terms, system objects provide the infrastructure for an application but are not meant for user interaction. For example, you would use this prefix on a form's hidden text box that is used to compute a value, or on a hidden table that provides message strings to your VBA code. If the system object should not be hidden, use the zs prefix instead. |
Access has its own prefixUSyswith a similar meaning. Items prefixed with USys are also not for user interaction and are not displayed in the Database window by default. In past versions of Access, it was necessary to use USys instead of zh to prevent the display of system objects in the Database window. With Access 95, you can use the zh prefix combined with setting the object's Hidden property to True to achieve this result.
zs. | Use this prefix to denote displayed system objects, which are for use by developers and application code only and should be displayed in the Access Database window. If the system object should be hidden, use the zh prefix instead. |
zt. | Use this prefix for temporary objects that are created programmatically. For example, a query written out from VBA code, used in code, and then deleted by the code, would have a zt prefix. Any database object labeled with zt showing in the Access Database window should be deleted during administrative sweeps of a database (before each repair and compact), because by definition it is probably left over from an abnormally terminated process that did not clean up after itself. |
zz. | This prefix denotes backup copies of objects that you keep in the Access Database window for reference or possible re-use. Items with this prefix should be periodically reviewed to determine their value, and deleted if not needed. |
Most of these database object prefixes use "z" as the first character. Database objects with such prefixes sort to the bottom of the Access Database window, below the user-oriented objects that are accessed more frequently.
Table B.17 shows examples of database objects, applying the various conventions in this section.
Object | Description |
zhtxtUser | Hidden system text box |
zttfoxCustHist | Temporary FoxPro table attachment |
qupdCustBal_Dlr | Update customers that are also dealers |
trelCustAddrPhon | Relate many addresses to many phones |
What do you do when LNC doesn't address a particular object naming need? First, contact us and let us know why, so that we can improve the style for the benefit of all users. Second, consider if what you are trying to do is covered by the style
in some other way. Suppose that your development team calls tables that link two other tables in a many-to-many relationship "linking" tables, and you want to create a new table tag tlnk as a result. However, on examination of all table tags, you
would find trel already exists, defined as "Table (many-to-many relation)", which is the correct tag for what you need. Even though the nomenclature is not exactly what you might use, it is better to use an existing tag than create another one.
Finally, when other options are exhausted, you can create a custom tag to address your need. When creating a custom tag, these should be your guidelines:
Item | Segment | Examples | Location |
bar | br | mmbr, pbr, tbr | anywhere |
database/databound | d | dcbo, dgrd, dlst | leading |
form | f | fdlg | leading |
MAPI | mp | mpm | leading |
module | b | bas | leading |
query | q | qsel | leading |
set | st | rst | anywhere |
table | t | tdf | leading |
view | vw | lvw, tvw | anywhere |
When creating a new tag, it should be mnemonic enough to uniquely shorten the word it represents, and should only use characters from the root word or a generally accepted shorthand.
To create tags for object variables pointing to OLE Automation server applications, start with a three character application prefix that is unique and applicable. Add to the application abbreviation a three-character tag for the entry point of the
application, such as bas for "Basic" in "Word.Basic".
For example, to create a tag for OLE Automation with Shapeware's Visio program, which is an OLE server, use either vsd (the data file extension) or vis (a mnemonic for Visio) as the basis for the tag. Next, add app for Application, because the entry
point to Visio's automation engine is a call to "Visio.Application". Thus, the tag and it's use in variable declarations would look like this:
Dim ovisapp As Object Dim ovisappDoc As Object Set ovisapp = CreateObject("Visio.Application") Set ovisappDoc = ovisapp.Documents.Open("C:\VISIO\HOUSE.VSD")
In addition to object naming conventions, LNC suggests several standardized coding conventions for VBA procedures.
Common coding practices in VB coding that are supported by LNC include:
There are as many in-line Basic code commenting styles as there are Basic coders. Whatever convention you use, the keys are to be terse yet descriptive, and to be consistent.
LNC suggests placing the following minimum set of comments at the beginning of each procedure:
Purpose | Briefly describe the purpose of the procedure. |
Arguments | List the arguments to a function and how they are to be used. |
Returns | Describe what the return value of a function signifies. |
Authors | Name the creator, the date created, the last editor, and the date last edited. |
In addition, I personally sometimes use these sections in the heading of a procedure:
Example | A sample call to the function that can be cut-and-pasted elsewhere as a template. |
Calls | A list of other procedures that are called by this procedure (a dependency list). |
Revisions | Notes about major revisions. |
Some developers like to keep a change log as comments noting all revisions in a procedure. I suggest keeping such comments at the bottom rather than the top, since they are less frequently accessed than the code they displace.
Comments placed on the same line as code should be separated from the code by at least two spaces. Comments placed on their own line should be no longer than 60 characters so they are displayed in full in the default module design view size.
Every procedure that can failwhich is virtually every procedure with more than a few simple linesshould have an error trap. Error traps are created by placing this line at the beginning of the procedure, after the header comments and before
any other statements:
On Error GoTo procname_Err
The marker procname should be replaced with the full procedure name. The error handler is placed at the bottom of the procedure, denoted with the label procname_Err:. At the end of the error handler, control is returned somewhere in the
procedure, usually to a line label name procname_Exit that precedes a block of code immediately above the error handler.
To allow you to turn off error trapping during program debugging, LNC suggests that you place the On Error statement inside a conditional compilation directive, like this:
#If pcccDebug Then On Error GoTto 0 #Else On Error GoTto procname_Err #End If
Before running an application, you can enable or disable error trapping by setting the value of pcccDebug to -1 (True) or 0 (False) in the "Conditional Compilation Arguments" text box on the Module tab of the
Options dialog.
We use the procname_label structure rather than the label_procname structure preferred by many coders in order to maintain our ObjectVerb construction metaphor as described. Some developers prefer to place the qualifier of the
label first, as in Err_procname, but philosophically the phrases Err_, Exit_, and so forth are not class tags, they are qualifiers for the line label object, thus they belong at the end like any other qualifier. This argument becomes more compelling
when you remember that you can also create line labels for GoSub and GoTo statements in VBA, and thus creating many different combinations of leading characters, as if they were tags, becomes problematic.
Table B.19This section lists some of our standard abbreviations we use when building object names.
Abbrev. | Description | Abbrev. | Description |
Acct | account | Mgr | manager |
Actg | accounting | Mkt | market |
Addr | address | Mktg | marketing |
Admin | administration | Mon | month |
Agmt | agreement | Mtg | meeting |
Amt | amount | Mtl | material |
Apvd | approved | Mtls | materials |
Arch | archive | Num | number |
Arvl | arrival | Ofc | office |
Asst | assist(ant) | Ofcr | officer |
Atty | attorney | Op | operation |
Auth | authorized | Ops | operations |
Avg | average | Ordr | order |
Beg | beginning | Othr | other |
Bilg | billing | Perd | period |
Bldg | building | Pers | personal, personnel |
Busn | business | Phon | phone |
Char | character | Phys | physical |
Comm | comment | Pmt | payment |
Cont | contact | Prim | primary |
Corp | corporate, corporation | Prnt | |
Ctrl | control | Proj | project |
Ctry | country | Pros | prospect, prospective |
Cnty | county | Qty | quantity |
Cur | currency | Rec | record |
Curr | current | Recd | received |
Cust | customer | Rem | remark |
Dept | department | Schd | schedule, scheduled |
Desc | description | Secy | secretary |
Det | detail, details | Seq | sequence |
Devlpmt | development | Srce | source |
Disc | discount | Stat | status |
Dlr | dealer | Stats | statistics |
Empe | employee | Std | standard |
Engrg | engineering | Sum | summary, summaries, summation |
Exec | executive | Super | supervise, supervisor |
Extd | extend, extended | Svc | service |
Extn | extension | Titl | title |
Fin | finance, financial | Tran | transaction |
Genl | general | Ttl | total |
Glbl | global | Var | variable |
Int | interest | Ver | version |
Intl | international | Whse | warehouse |
Inv | inventory | Whsl | wholesale |
Invc | invoice | Xsfr | transfer |
Loca | location | Xsmn | transmission |
Mfg | manufacturing | Xsmt | transmit |
Mgmt | management |
When creating code comments, object names, help files, and system documentation, it is important to use terms that have an accepted and non-ambiguous meaning. You should build a list of standardized terms for your specific industry or application to
ensure consistency. Table B.20 provides a short sample list of standardized terminology. These terms are not a feature of LNC, they are only examples as a starting point for your efforts.
Term | Description |
Add | To create a new record. You should select one of: Add, Create, Enter, and New to be consistent. |
Beg | Beginning, the start of a process. |
Close | To close an open object. |
Comment | A more familiar term for text originating with a human than Remark or Notes. |
Desc | A description, often a long text string. |
Edit | To change or modify. |
Editor | The last person to change a record. |
End | The end of a process. |
Flag | A programming item with fixed set of values, usually True/False (a Boolean). |
Key | A unique index used to find a record. |
Max | The maximum, better than Most. |
Min | The minimum, better than Least. |
Open | To open. |
Owner | The creator of a record, process, or object. |
Save | To commit a record. |
User | The person currently running an application. |
You can get copies of this document from Kwery Corporation. The following additional information is also available: the Leszynski Naming Conventions for Microsoft Solution Developers document, the Leszynski Naming Conventions
for Microsoft Access document, Windows Help file versions of each LNC document, and LNC programmers' tools. Contact Kwery via the order line at 1-800-ATKWERY, or on the product information line at 206-644-7830. Kwery can also be reached
by CompuServe and fax at the numbers that follow.
We welcome your feedback on these conventions, including your likes, dislikes, stories, and suggestions. You may also submit new tags for consideration. Please communicate with
Kwery via CompuServe at 71573,3261 or by fax to 206-644-8409.
This document is provided as is, without warranty of any kind, either express or implied, including but not limited to implied warranties of quality, performance, merchantability, or fitness for any particular purpose.
Some naming convention elements in this document are from the L/R white paper Naming Conventions for Microsoft AccessThe Leszynski/Reddick Guidelines for Access 1.x, 2.x, Copyright c 1994 Stan Leszynski
and Greg Reddick. For a comparison of L/R and LNC, see the document Leszynski Naming Conventions for Microsoft Access.
386MAX, Btrieve, Lotus 1-2-3, Microrim, Microsoft, Microsoft Access, Microsoft Excel, Microsoft Office, Microsoft PowerPoint, Microsoft Project, Microsoft Schedule Plus, Microsoft SQL Server, Microsoft Visual Basic, Microsoft Visual C++, Microsoft
Visual FoxPro, Microsoft Windows, Microsoft Word, Paradox, R:BASE, Qualitas, and Visual Basic for Applications are trademarks or registered trademarks of their respective owners.
Kwery Document Version Number: 95.1.1.