Sei sulla pagina 1di 196

Microsoft Access for Beginners

Copyright 2013 - Andrew Comeau


All Rights Reserved
For information regarding this book, please contact:
Andrew Comeau
P.O. Box 770253
Ocala, Florida 34477
acomeau@drewslair.com
http://www.AndrewComeau.com
Microsoft and product names including Microsoft Access, Microsoft Excel and Microsoft SQL Server
are registered trademarks of Microsoft Corporation in the United States and other countries.
Proper names and contact information used as examples in this book including company and
individual names are fictitious. No association with any real organization or individual is intended or
should be inferred.

Contents
Introduction..............................................................................................................................................1
Using the Sample Database....................................................................................................................3
Interface Guide........................................................................................................................................6
Chapter I - Creating the Database...........................................................................................................9
A Different Set of Tools.......................................................................................................................9
Creating a New Database.................................................................................................................12
Conclusion.........................................................................................................................................16
Chapter II - Organizing the Data............................................................................................................17
A Structure for Your Data..................................................................................................................17
Database Normalization Overview....................................................................................................27
Conclusion.........................................................................................................................................30
Chapter III - Building the Tables............................................................................................................31
Introduction........................................................................................................................................31
Creating a Table................................................................................................................................31
Relating Tables..................................................................................................................................42
Conclusion.........................................................................................................................................44
Chapter IV - Writing the Queries...........................................................................................................46
Introduction........................................................................................................................................46
Background.......................................................................................................................................46
The LeadsList Query.........................................................................................................................48
Conclusion.........................................................................................................................................57
Chapter V - Understanding SQL............................................................................................................58
Selecting Data...................................................................................................................................58
Modifying Data...................................................................................................................................63
Conclusion.........................................................................................................................................67
Chapter VI - Designing the Forms.........................................................................................................68
Introduction........................................................................................................................................68
A Word about VBA............................................................................................................................69
Data Sources.....................................................................................................................................69
Creating the Form.............................................................................................................................71
Additional Controls............................................................................................................................80
Conclusion.........................................................................................................................................90
Chapter VII - Generating the Reports....................................................................................................91
Introduction........................................................................................................................................91
From Forms to Reports.....................................................................................................................91
Creating a Report..............................................................................................................................91
Sample Reports.................................................................................................................................94
Managing the Interface....................................................................................................................101
Conclusion.......................................................................................................................................102
Chapter VIII - Automating the Interface with Macros..........................................................................103
Introduction......................................................................................................................................103
Access 2007 and Earlier.................................................................................................................103
Access 2010....................................................................................................................................108
Conclusion.......................................................................................................................................111
Chapter IX - Introducing Visual Basic for Applications........................................................................113
Introduction......................................................................................................................................113
What is Visual Basic for Applications?............................................................................................113
The VBA Environment.....................................................................................................................117
Variables..........................................................................................................................................123

Contents (continued)
Procedures......................................................................................................................................130
Arrays and Enumerations................................................................................................................138
Operators.........................................................................................................................................145
Using DoCmd..................................................................................................................................148
Decision Structures.........................................................................................................................151
Program Loops................................................................................................................................156
Error Handling.................................................................................................................................162
Algorithms........................................................................................................................................168
Appendix I - "Where do I go from here?".............................................................................................173
Appendix II - Using Lookup Fields.......................................................................................................175
Appendix III - Glossary........................................................................................................................180
Suggested Reading and References..................................................................................................190
Books...............................................................................................................................................190
Links................................................................................................................................................190

Microsoft Access for Beginners

Introduction
This book started out as a series of articles on my website at Drewslair.com. I decided to write
the series after answering questions about Microsoft Access as a result of my work with it and
talking to people who didn't understand exactly what Access was or how it compared to other
programs in Microsoft Office. I've seen many examples of databases created by people who
approach Access in the same way as they would use Excel, setting up one table to hold
everything and duplicating data as necessary.
It's understandable that many people try to use Access this way as more people are familiar
with the spreadsheet concept than database concepts. Access presents tables that look
something like the spreadsheet format that people are used to and, since it's offered as part of
the Microsoft Office suite, it's easy to see it in relation to the other programs and overlook its
power as a standalone product.
Microsoft Access is significantly different than any of the other Office applications, however.
While programs like Word and Excel focus on documents, Access files are database
applications that contain a variety of objects such as tables, forms and reports, all of which
work together to organize and manage your data. The most sophisticated Access databases
function as programs in and of themselves with user interfaces made up of forms, reports and
custom menu systems. Access is even used by some programmers to design sophisticated,
standalone systems for fields such as document management, customer relations and
inventory tracking.
Before you design the next software sensation however, you need to learn some basic
database and design concepts so you can use Access to its full potential. I consider this book
to be a mid-level introduction to Microsoft Access as I don't spend a lot of time on step-by-step
instructions. Instead, I introduce you to the basics of the program and provide enough
information so you will understand how to correctly create tables and design queries to read
from them. Then I show you what you can do with forms and reports. I also provide an
introduction to SQL so you will better understand what queries do. I don't provide exhaustive
detail on every feature but I do show you how to use Access well.
Most books about a program like Access focus only on the latest version but I take a different
approach. As of this writing, the current version of Access is Office Access 2010. I primarily
focus on the 2007 and 2010 versions but I also realize that there are still people using earlier
versions so I've tried to ensure that these users will find the book helpful as well. Most of the
concepts I write about here are common to all versions of the program and, where necessary, I
give specific instructions by version.

Page 1

Microsoft Access for Beginners

A Word on Design Wizards


For many of the objects in Access such as tables and forms, there are wizards that you can
use to quickly create an object by answering a few questions and making a few selections.
Microsoft Access even enables quick, wizard-based design of entire applications. The result is
a ready-made solution designed to do exactly what you specified, whether that's what you
wanted or not. In this book, I rarely mention the wizards because I don't use them for anything
significant when designing a database. I don't believe that they are good tools for creating
professional applications.
If you want to 'create' something you know nothing about and spend a lot of time thinking that it
doesn't meet your needs, then use the wizards. You don't need my help on that. On the other
hand, if you want to take ownership of the project and be able to support it, do it yourself. You'll
develop your skills that way and it's a lot more fun. Eventually, you will have a library of your
own work that you can consult whenever you want to figure out how to do something. The Job
Search Plus demo is an example of what can be done without design wizards. Throughout this
book, I will show you how to create things on your own so you will learn how to design
programs with Microsoft Access.

For More Information


This book is mainly about Microsoft Access and the principles behind its use. While knowing
how to design robust database applications with Access is a very useful skill, it's only the
beginning when it comes to mastering database design and programming. If you would like a
broader perspective on the software options and principles in database design, please check
out my other book; Your First Guide to Database Design. This book presents the basic
concepts behind database design and provides examples of everyday activities that can be
organized more effectively with the right database solution. The book also provides details on
other database software including MySQL and Microsoft SQL Server. For more information,
you can download a simple the book from Amazon.com, Barnes and Noble or my own site at
AndrewComeau.com.
I welcome your comments and questions concerning the material presented here. You can email me with any comments at dbdesign@drewslair.com.
Enjoy!
Andrew Comeau
October 2013

Page 2

Microsoft Access for Beginners

Using the Sample Database


Throughout this book, you'll see references and screenshots from a sample application that I
adapted for use here. Job Search Plus is a program that I designed to help individuals
organize all the information related to a job search including job lead details, company and
contact information and search activities. It also features flexible reporting and an interface that
demonstrates how Access can be used to design a professional application. The full program
is available as a free download from AndrewComeau.com with multiple versions in order to
accommodate people running different versions of Microsoft Access. There's even a version
that includes the free Access runtime for those who do not have an Access installation.
You can find more information, an online manual and download links to all versions of the
program at:
http://www.andrewcomeau.com/pages/jsmanual.htm.
The online manual contains links to the download files, installation instructions and a complete
overview of the program.

Macro Security and Trusted Locations


Starting with Access 2003, Microsoft took extra steps to guard against the possibility of
malicious code being distributed as part of Microsoft Access files. Access now notifies the user
when opening a file of the possibility of malicious code. Depending on your version and
settings, Access will even deactivate this code by default. As the sample database depends on
VBA code for its operation, you need to be aware of the steps to allow the code to run.

Access 2003
Access 2003 had some relatively simple precautions against potentially unsafe code.
Assuming that all the service pack updates are installed, you might just see a message like
this when opening the sample database.

Page 3

Microsoft Access for Beginners

Figure S.1 - Access 2003 unsafe code warning

Clicking on the Open button will open the database and run the necessary code. You can turn
off this warning if you like by changing the macro security options under the Tools >> Macro >>
Security menu. In the example in Figure S.2, I have the security set to Low which will run the
code without warnings. The options under the Trusted Publishers tab enable the user to trust
content from certain publishers although this requires the content to be signed with a security
certificate which you might never encounter with Access databases.

Figure S.2 - Macro security options

Page 4

Microsoft Access for Beginners

Access 2007
In Access 2007, Microsoft introduced the Trust Center which enabled the user to trust content
in specific locations on the computer. This enables you to define places on your computer
where you know that the content is safe rather than changing the security setting for the entire
Access application. When you open the sample database in Access 2007, you might see the
following message bar:

Figure S.3 - Access 2007 active content security warning

You can enable the content for the current session by clicking the Options button and selecting
'Enable this Content'. One of the choices on the Options screen is a link to open the Trust
Center which can also be opened from the Access program options screen available from the
Office 2007 Button. The Trust Center dialog provides options to manage the list of trusted
locations on the local system. Adding locations such as the Windows Desktop or My
Documents folder will allow content in these locations to be run without restriction.

Figure S.4 - Access 2007 Trust Center

For more information, see the MSDN article "Security Considerations and Guidance for Access

Page 5

Microsoft Access for Beginners

2007", the link for which is available in the Suggested References list at the end of this book.
You can also find the article by searching on the above title at msdn.microsoft.com.

Access 2010
Access 2010 takes the trust settings down to the document level. Clicking the 'Enable Content'
button on the security warning will permanently enable that database at that location. If you
copy the database to another location or rename the database, you will get the warning again.
The Trust Center is still available from the Actions Options panel which is available on the
Access 2010 File tab.
The Trust Center in Access 2010 also has more options including the option to disable
document trusting and clear the list of previously trusted documents.

Interface Guide
As mentioned in the Introduction, this book accommodates users of multiple versions of
Microsoft Access. With Access 2007, Microsoft introduced some major changes to the Office
interface that required users to learn where everything was all over again. These changes
were refined in Access 2010. I've included a short explanation here so you'll know what I'm
referring to in upcoming chapters.

Figure IG.1 - Access 2002 interface

In Access 2003 and earlier, Access used a standard menu and toolbar interface. Figure IG.1

Page 6

Microsoft Access for Beginners

shows the demonstration program with a customized menu system in Access 2002.
Office 2007 introduced the Office Button and Ribbon. The Office Button is a pull-down menu
that replaces the old File menu. You can use it for file and print management functions, to
close the database and to access the program options. The Ribbon groups all of the program
functions under tabs according to category. Figure IG.2 shows the Office Button and many of
the examples in this book show a customized ribbon that I created for the full version of Job
Search Plus.

Figure IG.2 - Access 2007 interface

Office 2010 did away with the Office Button and returned its functions to a File tab on the
Office Ribbon. Customizing the Ribbon is also easier in 2010. In Access 2007, it was
necessary to create a special table containing custom XML code, Office Access 2010 provides
an interface for adding and removing controls from the ribbon.
While the Ribbon interface took some time to get used to, I feel that it was a good move for
Office. With the increasing number of features available in the programs, the ribbon makes it
easier for users to find the one they need. The return of the Office Button features into the
main ribbon interface was also an improvement.
If you're generally familiar with the way things work in Windows and Office, then you shouldn't
have much of a problem switching between versions of Access but in this book, I do try to
make things as easy as possible for users of all versions. While many features maintain the
same interface between the various versions, I will provide an explanation for how to
accomplish something in each version as necessary.

Page 7

Microsoft Access for Beginners

Figure IG.3 - Access 2010 interface

Page 8

Microsoft Access for Beginners

Chapter I - Creating the Database


A Different Set of Tools
For many people, Microsoft Access is probably the most enigmatic of all the Microsoft Office
applications. It's only included in the Professional editions of the suite or as a standalone
package which means that most home users won't have it installed. People will often hang out
in Word, Excel and Outlook but never have reason to wander into the database portion of the
suite. The interface itself is unfamiliar to the average user who is more accustomed to a
spreadsheet or blank word processing document than the collection of objects that Access
presents. Even in Access 2007 and later, the ability to create entire applications from
templates departs from the document focus that many users expect.
Those who do explore the features in Microsoft Access, however, find that it is likely the most
powerful of all the Office applications with its ability to store and organize huge amounts of
information in related tables, then query and sort the information as needed and finally present
the data in attractive, professional reports. Custom data entry forms make it easy to enter and
review data and guard against data entry errors. All of this is available even before a user
might start playing around with Visual Basic for Applications, the programming language that
enables users to create virtually any type of interactive application and turns Microsoft Access
into a full development environment.

What is Access?
As a Windows desktop database, Microsoft Access provides many of the features of a
Relational Database Management System (RDBMS). In order to understand what that means,
we have to take the term a bit at a time.
A database is any collection of information that can be organized by a standard set of fields.
Your address book is one classic example. Each entry in the book represents a record with
fields such as Name, Address, Phone Number, etc.. A dictionary could also be considered a
database with its standard entries including the word, pronunciation and definition. Databases
might include relatively few records or tens of thousands of records, depending on the need.
A database management system such as Access enables this data to be stored electronically
according to a set of rules. The tables in Microsoft Access organize the data and provide
features that are common to databases such as indexes to make it easier to search and sort

Page 9

Microsoft Access for Beginners

the data, primary keys that identify each record with a unique value and validation rules that
help to ensure the data conforms to the necessary limitations. Access also provides a way to
retrieve and manipulate the data through queries. Finally, a database management system
enables the creation of new databases as needed and can be used to manage large
collections of separate database applications.
Access is also a relational database system. There are different types of database systems
that are structured differently in order to serve various purposes. In a relational database:
1. Data is organized into tables which are sometimes called relations by database experts.
This is because each table has a subject (i.e. Companies) and every field in a given
table is supposed to be directly related to the subject of the table.
2. Tables can be linked or related to each other. This is demonstrated in the sample
database by a link between the Leads and Activities tables. Since there can be more
than one activity for each job lead, the Activities details are placed in a separate table
and the two tables are linked by an ID number assigned to the job lead. This eliminates
the duplicate entry of information such as job title or description. This, in turn, reduces
the size of the database and the possibility of data entry error and database corruption.
This is how Access differs from a program like Excel. While Excel organizes information and
allows for calculations and analyses, Access takes it a step further and enables relationships
between different categories of data and faster analysis of information.

Figure 1.1 - Relational databases enable you to link different categories of data as shown in this
diagram of two related tables.

Database experts will point out that Access lacks a couple of the features that would fully
qualify it as a relational database system, however it is still a good tool for small to medium
sized database applications and provides an excellent training ground for database and

Page 10

Microsoft Access for Beginners

programming concepts.

File Formats
Microsoft Access uses a single file to store all of the objects used in a database application
including tables, queries and reports. This differs from other desktop database systems which
might store queries and other items in separate files. The use of one file makes the databases
very portable.
Despite the use of one file to store everything, Access applications can make use of external
files by linking to data in other Access databases. This ability is commonly used to separate
the data tables from the interface portion of an Access application by storing the tables in one
Access database file (referred to as the back end) and linking to them from another Access file
which stores the forms, reports and other items (the front end). This has a number of
advantages, such as enabling multiple users to access the data at the same time from different
locations and making it easier to change reports and forms without disrupting access to the
data. Access can also link to data in other file formats, including Excel and Microsoft SQL
Server. Access references the links to external data sources just like any other table.

Figure 1.2 - Access is able to link to other data formats.

Figure 1.2 shows the table listing from an Access 2007 database that includes a couple of
linked sources. The ResultLog item is a linked Access table while LeadsImport is a link to an
Excel file. When linking to other formats like Excel, Access will look for data structures such as
worksheets or tables that can be read like an Access table and provides a wizard that will
guide you through the process of linking to the data.
Microsoft Access has many file extensions that can be used for different types of applications
such as templates and add-ins but there are only a couple that you need to be immediately
familiar with. In Access 2007 / 2010, the .ACCDB file extension indicates a typical database
that you would create and work with. The .ACCDE file extension indicates an Access database
that has been protected against changes to the objects within it. The data can still be changed

Page 11

Microsoft Access for Beginners

but no design changes can be made to the tables or other objects. The corresponding file
extensions in Access 2003 and earlier were .MDB and .MDE. As with other Office applications,
Access is able to open and save files created in other versions of the software although there
are limitations in the creation of the protected databases (.MDE / .ACCDE).

Figure 1.3 - A few of the extensions and file formats used by Access.

Protected Access databases are also used to protect programming code and design details
within the database from being viewed or modified. The demonstration database for this book
is distributed as an unprotected MDB file created in Access 2002. It can also be opened and
modified in any version of Access after that.

Creating a New Database


Once installed, Microsoft Access adds itself to the New Object menu in Windows. From the
File menu in any folder, or by right-clicking on the Window Desktop, select 'New' and then
Microsoft Access Application'. This will create a blank database which you can then rename
and open within Access. The other way is to use the New command from the Office button in
Access 2007 or from the File menu in all other versions and then choose 'Blank Database'.
Access offers a number of pre-designed templates and wizards that can help you create entire
applications just by answering a few questions. These are great examples of applications and
worth studying if you're new to Access but, as I said in the Introduction, I would not
recommend them for use with real data. As complex as Access applications and the
requirements for them can be, it is in your best interests to learn what you need to know to
design and support your own database.
When you first open a database in Access, you can press F11 to show the database window if
it's not already visible. This window will display all of the objects in the database. Figure 1.4
shows the Access 2007 window with the menu that enables you to change the objects listed.

Page 12

Microsoft Access for Beginners

In Figure 1.5, you can see an example of the window from the sample database.

Figure 1.4 - Access 2007 database window settings

Protecting your Database Design


Earlier, I mentioned the .MDE and .ACCDE formats available in Microsoft Access. These are
protected database formats in which all design features are disabled and all editable code has
been removed. Sometimes, if you are distributing your database application to other people,
you might want to use one of these formats to prevent unauthorized users from making design
changes or prevent access to your code.
Creating a protected database is pretty simple in any version of Access.
In Access 2010, select 'Save & Publish' from the File menu and select 'Make ACCDE'
under the advanced options.
In Access 2007, select 'Make ACCDE' under the Database Tools tab of the Office
Ribbon.
In Access 2003 and previous, select the 'Make MDE File' menu option under the Tools
>> Database Utilities menu.
The Microsoft Access file that you are trying to convert must be saved in the same version of
Access in which you are working before creating a protected file, i.e. if you are working in
Access 2007, you must be working with an ACCDB file in order to make an ACCDE. You
cannot make an ACCDE file from an MDB. If the Make ACCDE / MDE command is grayed out,
it's probably because the file you're working with was saved under a different version of
Access.
When you create an ACCDE or MDE, a new file will be created separately from your ACCDB

Page 13

Microsoft Access for Beginners

or MDB file. It's important to keep the original file in which you can make design changes
because the protected database that you just created cannot be used to recover the original
file.

Database Objects
Other Office applications deal primarily with documents such as letters and spreadsheets but
Access takes a different approach; the database file can contain many objects of different
types which work together to provide the functions you need in your database program.
Tables are the heart of the database, storing your data and organizing it for quick retrieval.
Access data is, ideally, stored according to certain principles that organize the data by subject
and eliminate duplication. I will provide more details on this in Chapter II. In Chapter III, you'll
see how to design the tables and use table properties in order to get the maximum benefit out
of Access as a database.
Queries provide a way to retrieve and manipulate data stored in the tables. Access uses
Structured Query Language (SQL) to perform any type of operation that's needed on the data
or even the structure of the tables themselves. Beyond reading and manipulating data, queries
can act as data sources similar to tables, performing intermediary processing of the data and
passing results on to other queries for further processing. Chapter IV provides additional
information on queries and a beginners' guide to SQL is presented in Chapter V.
Forms provide a fast and customizable way to manage data within your program. Entering
data directly into tables can be slow and prone to errors. Forms offer a wealth of tools and
controls that will speed up your data entry and help prevent user errors. Chapter VI details
some of the possibilities that are available with forms and how they can be used to create a
professional user interface.
Chapter VII will get you started with reports which are essential to any data management
system. The report designer is one of the greatest strengths of Microsoft Access. Access is
loaded with features to help you analyze your data and all of these features come together in
an easy-to-use report designer that will help you communicate the data to others within your
organization.
Learning to use macros and modules is the next step once you've learned the basics of
Microsoft Access. Chapter VIII introduces macros which are the most basic of programming
features in Access, enabling you to automate basic tasks by scripting sequences of steps for
Access to follow. Modules are used to hold advanced custom functions that you can create
using Visual Basic for Applications (VBA). You'll see more information on them in Chapter IX.

Page 14

Microsoft Access for Beginners

Figure 1.5 - The database window shows all of the objects in the database in one place.

Compact and Repair


Microsoft Access database files are designed to hold up to two gigabytes of information,
including your tables, forms, reports and other objects. The problem is that once the file grows
to accommodate new data or design changes, it doesn't automatically let go of that space
when data or objects are removed from the database. This can cause the database to grow
quite large, especially during the design process when a lot of objects are being changed.
The solution for this is to use the Compact and Repair function in Access.
Prior to Access 2007, the Compact / Repair function is available from the Tools >>
Database Utilities menu.
In Access 2007 and later, you can find it by clicking on the Office button and selecting
'Compact and Repair' from the Manage menu.
In Access 2010, the Compact and Repair button is moved to the Database Tools tab of
the Access ribbon.

Page 15

Microsoft Access for Beginners

Access will exit the database and create an entirely new database file from the old one,
releasing the extra space. This process will also attempt to repair certain types of corruption in
the database file.
Compact and Repair also resets certain counters in the database. For example, in a future
chapter, you'll learn about AutoNumber fields which automatically generate a new unique
number for each record that's entered into a table. These are often used for ID fields and are
usually sequential. Compact and Repair will reset this number so that the next number used is
continuous from the last one. This can be useful when you are first designing a database and
entering and deleting a lot of test records in tables. Before releasing the database to other
users, you should run a Compact and Repair which will reset those AutoNumber counters.
Compact and Repair is not foolproof for eliminating all wasted space or fixing errors. The
Access file format holds on to temporary data that is not released even when compacting and
there are some problems it won't fix. This is one reason backups are important. Be sure to
backup your database often and before making any major changes to the design.

Conclusion
Microsoft Access is a little bit of a paradox; marketed as part of the Microsoft Office suite and
yet providing enough functionality and power to stand on its own. Its ability to analyze data
from a host of other programs makes it a valuable part of the Office environment and
accessible to the average user. Yet, there are also people who have started programming
careers by using Access to master the database and programming concepts involved in
creating a great database application.
Whatever your goal with Access, the following chapters will provide you with all you need to
know to start building databases and add some very valuable skills to your resume.

Page 16

Microsoft Access for Beginners

Chapter II - Organizing the Data


A Structure for Your Data
In Chapter I, I explained how a relational database enables you to categorize data by subject
within your database and then create relationships between different categories so the data
can be viewed according to those relationships. In this chapter, I want to explain the system
that's used to do this. In the next chapter, I'll show you how to actually create and fine-tune
tables but first, I need to show you the proper way to design what's called the database
schema (pronounced SKEE-mah) which is the collection of related tables and other objects
that form the structure of the database.
Beginning in 1970, a computer scientist at IBM, Edgar F. Codd, developed a set of rules by
which data could be organized in relational databases such as Microsoft Access (although
neither Microsoft or Access would be around for a few years at that point). This system is
called Database Normalization and has become the accepted standard for designing relational
databases. The purpose of normalization is to simplify the updating of data and avoid
inconsistencies and duplication within the database. It also makes adding new types of data to
the database structure easier because there is already a context to build on.
While there are several rules in database normalization, also referred to as Normal Forms,
there are only three that you really need to be concerned with when working with Microsoft
Access. If you implement these three in your database, you will have a very stable and wellorganized system.
The basic rules of normalization that you need to know at this point can be summed up as
follows:
1. Table fields should be designed to hold single values that represent basic units of
information.
2. There should be no repeating fields or groups of fields in a table. (i.e. Item1, Item2,
Item3, etc..).
3. All fields in any given table should relate directly to that table's entire primary key and
non-key fields should not be dependent on each other.
This is a very basic summary and I will present a more detailed explanation later in the
chapter. First, let's see the rules in action in the Job Search Plus demonstration database.

Page 17

Microsoft Access for Beginners

Tables and Relationships


After downloading the demonstration database, start by opening the database in Access.
Press the F11 key to show the database objects window. The database window will show you
all the tables and other objects in the database.

Figure 2.1 - In all versions of Access, the database window is accessed by pressing F11.

Although the F11 key works in all versions, Access 2007 introduced some radical changes to
the Access interface. While many screens look the same, some are different enough to be
worth mentioning and I will note the differences as necessary.
One of the goals of a user-friendly Access database is to minimize the amount of work
required to enter and retrieve the information, thereby reducing workload and the possibility of
error. This is where the ability to group data into separate tables comes in handy. These tables
organize the data so that it's easier to find and, as you'll see, they help to eliminate the need to
enter the same information over and over again. The tables you create and the relationships
between them are the backbone of your database. Once you have the tables designed
correctly, you're halfway there.
Job Search Plus was designed to assist individuals in managing the information involved in a
job search so the Leads table is the central table in the database and it contains the essential
information for each job opportunity. In accordance with database normalization, Leads only
contains the information that specifically relates to the job lead itself such as the date recorded,
job title and description.
If you view the design of the Leads table by right-clicking on the table in the database window
and selecting 'Design View', you will see by the key symbol next to the field name that the
LeadID field is identified as the table's Primary Key. This means that the field contains a value
that is unique for each record in the table, enabling the database to identify that particular
record. Access encourages you to create a primary key for every table that you design.

Page 18

Microsoft Access for Beginners

Figure 2.2 - The table design view provides complete access to settings for the table and the
individual fields.

In the second column of the design view, you'll see the data types assigned to each field.
Assigning specific data types to fields enables the database to more efficiently store the data
and enforce rules for entering the data as needed. A number of types are shown in the Leads
table including the Date/Time type which stores dates and enables date based calculations,
the Yes/No type which stores a simple 'Yes' or 'No' value appropriate to checkbox options and
the Number type which allows for a wide range of numeric formats. The data type assigned to
the LeadID field is called an AutoNumber. This is a unique number assigned by the database
to every record that the user enters and cannot be edited by the user.
For example, if you were creating an employee database, you would not want to use this
number as an employee number within the company records because there is no guarantee
that it won't skip values if records are canceled as they're being entered. It will also assign the
numbers in the order that the records are entered while employee numbers are often assigned
in order of hire. The main, and often the only, purpose of an AutoNumber primary key field
such as LeadID is to create an identifier that the database can use to refer to each record.
The Activities table in the sample database, which lists actions for each job lead such as
applications, correspondence and follow-ups, also has a field titled LeadID but the data type is
Number instead of AutoNumber. In the Activities table, this field is referred to as the Foreign
Key because it's used to relate records in Activities to the job lead records in Leads. The value
originates in Leads as an AutoNumber that identifies a specific job lead and each record in the
Activities table that relates to that job lead will use the identifying number from Leads to refer to
the correct Leads record. In Figure 2.3, you can see a relationship drawn between the two
tables in the Relationships diagram. This relationship enforces the link between the LeadID
field in each table.

Page 19

Microsoft Access for Beginners

In a later chapter, you'll see how forms use this relationship to automatically insert the correct
LeadID value in the Activities table to link the records there to the right records in the Leads
table.

Figure 2.3 - Relationships between tables use corresponding fields such as record IDs to link
data. In this example, the LeadID field links the Leads and Activities tables.

Using the LeadID value in the Activity table as a unique identifier, rather than something like
the job title field, saves space and allows for additional report functions that you will see later.
The nature of the Leads table also means that there is no single field or even combination of
fields that will be unique for each record. By using the number, the database knows exactly
which Leads record each Activity corresponds to.
Sometimes it might be tempting to use a naturally unique value such as a Social Security
Number or credit card number as a primary key, depending on what type of database you're
building. I cannot stress this enough - NEVER use confidential information as a table key. You
cannot prevent users from viewing table keys if they wish, especially if they're referenced by
every other table as in this database.
This arrangement between the Leads and Activities tables is an example of how a relational
database works. In a flat spreadsheet, you might see all of the Leads fields laid out and then
repeating groups like 'Activity1', 'Activity2', 'Activity3', etc.. There are problems with that
approach. First, it limits the number of activities that can be entered to an arbitrary number. It's
also very difficult to search on. If you wanted to see all of the activities that involved a resume
being sent, for example, you would have to search each of the fields separately. The approach
shown in Figure 2.3, on the other hand, changes the direction of the data. The Activities table
can hold an unlimited number of activities for each lead and uses the LeadID as an identifier
for which Leads record is being referred to. It's also easily searched with a simple query.
In the bottom half of the table's design screen, you'll see some extra settings for each field.
When adding fields to a table, you should pay particular attention to settings such as 'Field
Size', 'Input Mask', 'Default Value', the validation settings and 'Required'. Proper use of these

Page 20

Microsoft Access for Beginners

settings will provide the controls needed to help ensure that data is accurately entered. I
provide more information on these properties in the next chapter and you can get more
information on any of them by placing the cursor in one of the setting boxes and pressing F1.

Types of Relationships
If you select 'Relationships' from the Access menu, it will bring up the relationship diagram for
the database like the one shown in Figure 2.4. In Access 2007 / 2010, select the
'Relationships' option from the Database Tools tab on the Office Ribbon. In Access 2003 and
prior versions, it's available from the Tools menu.

Figure 2.4 - The relationship diagram for the Job Search Plus sample database.

Page 21

Microsoft Access for Beginners

This is an interactive tool that you can use to view and manage relationships between tables.
The relationship diagram for Job Search Plus might look complicated until you remember
some of the things I've mentioned so far and notice relationship lines between ID fields in one
table and corresponding fields in another. The link between Leads and Activities is one of
these.
Many of the relationships travel in the other direction. Reference tables such as Companies or
Contacts use an AutoNumber as a primary field and the Leads table stores that value to refer
to a specific item.
At first, this diagram might also seem to contradict what I said about making data entry easier.
Another aspect of a relational database, however, is that it can contain data that is entered
once and then referenced many times. The Companies and Sources tables in the database
are good examples of this. The Companies table is a reference or lookup table for the
information related to companies on various leads. By putting this information in a separate
table from the job leads, the company information can be entered once and then referenced as
needed. This is a lot better than having to enter a company name over and over again, hoping
that it's always spelled right and then trying to retrieve all information on all leads related to a
specific company.
By looking at the relationships between these tables, you can see how these relationships are
defined. Double-clicking on an existing relationship line on the diagram in the database will
bring up the Edit Relationships screen shown in Figure 2.5 where you can view the settings. In
the relationship between Leads and Activities, the 1 and
symbols above the line indicate a
One-To-Many relationship between the tables. This means that for every job opening listed in
Leads, there can be many activities recorded.

Figure 2.5 - The Edit Relationships dialog

Back in the relationships window, you'll also notice that the direction of the arrow points to
Activities. If you click on the Join Type button on the Edit Relationships panel, you can see that

Page 22

Microsoft Access for Beginners

the relationship is set to show all records from Leads and then any records in Activities that
match those records. This will pull records from Leads even if there are no records for that job
lead in Activities. It is referred to as an Outer Join. The first option on the Join Properties panel
would pull only the records where the value for this field is present in both tables and this is
called an Inner Join. In this case, job leads with no activities would not be listed and this might
or might not be what you want. You'll see the importance of using the proper join type when
you start designing queries to work with your table data as shown in an upcoming chapter.
A one-to-many relationship might be the most common type used but there are other types. A
one-to-one relationship is formed when each record from the parent table can have no more
than one corresponding record in the child table. The job search database does not have an
example of this but one example would be a Human Resources database where the employee
address and contact information is split off into a separate table from the main employees table
as shown in Figure 2.7. This might be done to isolate the contact information for security
purposes or simply to reduce the size of the main table.

Figure 2.6 - The Join Properties dialog

In order for the database to recognize the one-to-one relationship in this example, the
employee and contact information tables would need to link on an Employee ID field. This ID
field would be the primary key and an AutoNumber in the Employees table. In the contact
information table, the corresponding EmployeeID field would be a regular numeric data type
but would be set to prevent duplicate values so that a specific employee ID could only be used
once in the table. Fields outside the primary key can be set to be unique as you will see later.
When a relationship was created between the two tables using the corresponding EmployeeID
fields, Access would recognize that the field was unique in both tables and see it as a one-toone relationship.
Sometimes, a third type of relationship, a many-to-many relationship, is needed. Again, it's not
used in the job search database but an example would be a student database tracking class
registrations. A hypothetical relationship diagram is shown in Figure 2.8. For each class, there
will be many students and each student will take more than one class. This is a many-to-many
relationship. These relationships are not directly definable in Access so a third intervening
table that breaks the relationship down into two one-to-many relationships is needed. This
table is also known as a cross-reference table. In this example, a class registration table
includes fields for the Student ID and the Class ID as well as any other information pertinent to

Page 23

Microsoft Access for Beginners

that student's registration in the class. This table then links to both the student and class tables
on those fields.

Figure 2.7 - Another example of a relationship between parent and child tables.

Figure 2.8 - A many-to-many relationship with an intervening table.

Page 24

Microsoft Access for Beginners

Referential Integrity
In the bottom half of the Edit Relationships box, you'll see a section dealing with something
called Referential Integrity. This is a method for ensuring that if data from one table is
supposed to match data in another table, then any changes are made on in both tables.

Figure 2.9 - Referential Integrity options

An example of this would be if one of the records in the Companies table was deleted. If there
were job leads recorded for that company, this could cause a problem. Without referential
integrity, you would be left with job leads but no company information. It would get even worse
if a number of companies were deleted at once. With referential integrity activated, Access
protects records and primary keys that are referenced by records in other tables. If you try to
delete a record that is referenced by another table, you might get a message like the one in
Figure 2.10. On the other side of the example, it would not be possible for someone to enter a
non-existent company number in the Leads table because the database would not find a
corresponding company in the Companies table.

Figure 2.10 - Referential integrity prevents the deletion of records that are referenced by other
tables.

Of course, in some cases, you do need to be able to delete or change records, even if they are
referenced in other tables. The two options under referential integrity for 'cascade' updating
and deleting of records address this. Using cascade update, if a record's primary key is
changed, that value is also changed throughout the database in any records that reference it. If
cascade delete is active, then instead of getting the message shown in Figure 2.10, you'll get a
message informing you that you are about to delete records in a related table and confirming
that you wish to proceed. If you select 'Yes', then any records in other tables relating to that
record would be deleted. In the case of the relationship between Leads and Activities, if a job
lead record was deleted, a cascading delete would delete any activities associated with that
lead.
The options for referential integrity are not automatically appropriate for every situation. Always
take the nature and needs of the data being stored into account when you set options for

Page 25

Microsoft Access for Beginners

tables and relationships.

Remaining Tables
In addition to the tables already mentioned, the job search database has others that are used
for reference and one or two interesting features.

Figure 2.11 - Job Search Plus relationship diagram.

The Sources and Contacts tables act much like the Companies table, holding reference
information as indicated. Sources stores a few details on lead sources such as online job
boards and newspapers. It's linked directly to the Leads table with a one-to-many relationship
so a Source reference can be stored with each lead. These tables are examples of how

Page 26

Microsoft Access for Beginners

information that doesn't directly relate to the Leads table primary key is moved to a separate
table for lookup as needed.
BusinessTypes is a basic lookup table that supplies business categories to the Companies
table. Again, each category might be used an indefinite number of times so it has a one-tomany relationship to Companies. This table doesn't eliminate any information from Companies
as the Business Type description is still stored. Instead, the table provides a list of types for the
user to select from and limits the entry in the Companies table to those types, eliminating
errors so that searches are more accurate.
The unique feature is the double listing of the Companies table under 'Companies' and
'Companies_1'. These are actually the same table, just with a separate reference name in the
relationships diagram. The reason for this is that the Leads table includes two fields that can
hold a company reference; CompanyID and AgencyID. This enables the user to record leads
that are being pursued through a placement or recruiting agency. Since it would be
exceedingly rare to have more than two companies that the job seeker would have to work
with on any one job lead, I decided to include both fields in the Leads table rather than doing a
separate table for the companies associated with a lead. By having both fields related to the
Companies table, both of them can use the table as a lookup but it does require separate
references in the Access Relationships window.
Also notice that the Contacts table is linked to both the Companies and the Leads table. The
Leads table stores a primary contact for a job lead that might come from either the company or
the agency and the Companies table links to it so that all contacts can be assigned to a
specific company. The Companies-Contacts relationship would be the most obvious
relationship but being able to link a table to multiple other tables provides flexibility in the
database.

Database Normalization Overview


Now that you've seen an example of the rules in action, here are the first three normalization
rules with some clarification. Normalization rules are referred to as Normal Forms and
references to them are often abbreviated with the rule number followed by NF'.
First Normal Form (1NF): All fields contain just one value and there are no repeating
groups within the table.
The first part of this rule is sometimes referred to as atomicity. Each field value within a table
should be atomic meaning that, just like an atom, it can't be broken down into anything smaller
and still be useful. An example of this would be a company address. When designing the table
to hold company addresses, you could have a single field that held the city, state and zip code
and your database might work okay until you decided that you wanted to search for companies
by city or sort on the state in a report. You wouldn't be able to because these values would be
part of a larger value rather than having been stored separately. That's why you will usually

Page 27

Microsoft Access for Beginners

see separate fields for the three values.


Depending on the database and what it's being used for, there might be some gray areas. An
example would be a person's name. In most databases, you would want to split it into at least
two fields; first and last, so that you could sort or search on either name. In some special
cases, however, if you know that you're never going to need to do that, you could decide to
keep the entire name together in one field.
There is a certain thing as over-normalization, where the normal forms are carried too far and
no longer provide a benefit. An example would be if you decided to break up the street address
into different fields, i.e. the street number, street name, suite number, etc. There is usually no
clear benefit to this, it would result in a lot of blank fields (What if there is no suite number?)
and it would force you to refer to more fields in order to construct an address. The various
fields would no longer be useful in and of themselves as a City or State field would. This is
where a certain amount of judgment is required when normalizing data.
The second part of this normal form is that there are no repeating groups within a table. The
Leads and Activities tables were used as an example earlier. In Excel or another denormalized
environment, the activity items might be recorded in multiple numbered columns or groups of
columns but this causes problems such as limiting the number of items that can be added to
one order. The proper way to do this in Access is to change the direction of the data by having
an Activities table with a record for each activity and a LeadID number that references the
order that item is part of.
Second Normal Form (2NF): The requirements of the First Normal Form have been
satisfied and all fields within the table are solely dependent on the entirety of the table's
primary key.
Notice that the normal forms are cumulative. This requirement cannot be satisfied unless the
values in your tables are atomic and repeating groups have been eliminated as mentioned in
the First Normal Form.
The Second Normal Form simply means that every table must have a specific subject and
every field within the table must relate directly to that subject. When evaluating a table against
the rules of database normalization, that subject is what determines the field or combination of
fields that would serve to uniquely identify the record. This is the primary key. In the example
database, I often use AutoNumbers as primary keys for the purpose of linking tables but the
normalization rules were not written with those in mind.
For example, in the demonstration database most job leads will have a company associated
with them and if the table wasn't using an AutoNumber as the primary key, the company would
be one of the fields that would be part of a unique identification for the job lead, probably in
addition to the Job Title and the Date. These three fields would make up the basis of the job
lead. While the company identifier is stored in the Leads table, there is no reason to store the
company address or phone number in the same table because that information does not relate
directly to the job lead itself but only to the company. It is supporting information but not

Page 28

Microsoft Access for Beginners

primary information when referring to the job lead. If you were applying to more than one job at
the same company, you would not want to have to store the same company address over and
over again in different Lead records. This would be duplication and could lead to errors when
the information wasn't copied correctly. Instead, a separate table is built for the company
information and only the company ID number is stored in the Leads table. The Leads table
then links to the Companies table to get the information as needed.
The primary goal of this normal form is to avoid duplication of data. If you find that you are
storing the same information more than once in your database, you need to ask why.
Information that is stored in multiple places takes up space and is harder to update
consistently.
Third Normal Form (3NF): First and Second Normal Forms are met and all non-key fields
within a table are mutually independent of each other.
This means no calculated fields or any other instances where the changing of one field will
require a change in another.
In the example of a customer order database, this would prohibit the practice of having a total
field that multiplies the number of items ordered by the item price. This type of field is not
needed at the table level because it's easy enough to include as part of a query or data entry
form so that it's available when it's actually needed. If you include it in the table, that means:
a.) if the fields it's dependent on are ever changed, the field must be updated even if you don't
need the information at the time which can affect the performance of your database or b.) the
field is not updated automatically in which case it is not reliable. Calculated fields also take up
additional space within the database for values that can easily be calculated as needed in a
query or on a form or report.
Having said this, Access 2010 introduces calculated fields within tables. Microsoft's reasoning
is that this provides a central location for expressions that might otherwise be duplicated on
different forms and reports. Another reason is to increase the compatibility of Access with
Microsoft SharePoint, a system used to share files and web-based information over networks.
While I understand the logic here, I still believe that it is inherently poor design for a relational
database because of the reasons stated above, especially when there are alternatives such as
queries that only perform the calculation as needed. You'll learn about queries in an upcoming
chapter. Nevertheless, Access will allow you to do a lot of things that fall outside best practices
in database design and it is ultimately your responsibility to learn as much as you can and
weigh all the options when designing your database.
When learning the rules of database normalization, some students have found it helpful to
remember this rule which comes from E.F. Codd's definition of the Third Normal Form.
Every field in the table must provide information about the key, the whole key and nothing but
the key (so help me Codd).
You probably have a basic understanding of these rules at this point but don't be surprised if it

Page 29

Microsoft Access for Beginners

takes some practice on your part to learn how to apply them when designing your own
databases.

Conclusion
Microsoft's support site offers a couple of very good articles which detail the rules of
normalization and provide more examples. For more information, please refer to the
Suggested Reading list at the end of the book.
As I listed the tables in this database, you might have found yourself thinking that it looks like a
lot of data entry. If the tables were actually intended for data entry, that would be true. This is
why I almost never allow users to enter data directly into the tables; that's what forms are for!
In an upcoming chapter, you'll see how properly designed forms use the relationships between
the tables to bring much of the data entry work together in one place. They can automatically
supply many of the values required in the tables and include interesting features like dropdown lists and default values that eliminate a lot of typing and help to ensure correct data
entry.
In Chapter III, I'll go into greater detail about how you can create tables like the ones you've
seen here.

Page 30

Microsoft Access for Beginners

Chapter III - Building the Tables


Introduction
In Chapter II, I wrote about designing a database in terms of organizing the information into a
set of tables so that the data will be most accessible. The next step is to actually build the
tables. The table design environment has a number of features that contribute to a stable
database and some of these features can be confusing to someone new to Microsoft Access
or even databases in general. More information on all of the features in this article is available
through the help system in Access which I encourage you to become familiar with. For now, I'd
like to point out some of the most important items.

Creating a Table
There's often more than one way to do something in Access and this is true of creating tables
as well.
1. In Access 2007 / 2010, these options are shown on the Create tab of the Office Ribbon
control.
2. In previous versions, select the Tables option in the Database Window and click the
New button at the top of the window. This brings up the New Table dialog with options
for creating the table.
For this article, I'm going to focus on creating a table through the Design View screen. Figure
3.1 shows the design view for Leads, the main table in the demonstration database. Each field
in the table is represented by a row in the top half of the window with additional settings for the
field in the bottom half. You can switch between these two sections by pressing F6. This
screen enables you to completely customize any table in order to get the most advantage from
storing your information in Access.

Field Names
Access is very flexible in what it will accept for field names and allows names up to 64
characters in length. I try to keep mine short but descriptive enough to avoid confusion. Field
names can contain spaces but I don't use them because they lead to confusion and possible
errors that are hard to track down. The names shown in Figure 3.1 use a naming convention

Page 31

Microsoft Access for Beginners

called CamelCase where multiple words are joined without spaces but with each initial
capitalized. Some people also use underscores between words.

Figure 3.1 - Pressing F6 in table design view switches between the list of fields and the field
settings.

It's also important to avoid using reserved words such as function names in tables. 'Date'
would be a very common choice for a field name but Date() is a function in Access that returns
the current date and this can cause conflicts when referring to the field. Something like 'Name'
is not a reserved word but is not very specific either.

Data Types
After you name a field, you specify the type of data that will be stored there under the Data
Type column in Table Design view. If used correctly, data type assignments help Access to
store the information more efficiently with less wasted space and in a way that will enable you
to use the data as needed.
The following is a list of available data types and some pointers on their use. Again, for full
information, refer to the Access help system. In my comments, I often reference the number of
bytes used to store a data type. This should not be confused with the number of digits allowed
in numeric fields. For example, Access can use one byte of space to store a number up to 255
and four bytes can store numbers up to 2,147,483,647!
Text
The Text data type stores general text and alphanumeric data including names and formatted
numbers that aren't used in calculations (i.e. phone numbers, serial numbers). Each field can

Page 32

Microsoft Access for Beginners

hold up to 255 characters.


This type will not reserve extra space for a field if you specify a field size larger than the actual
data, i.e. a field size of 35 characters when your data only takes up 10. Still, for the sake of
accurate data entry, it's better to specify field sizes only as large as you need them. It's easier
to increase a field's size after data has been entered than to decrease it.
Memo
This is another text field for longer entries, up to 65,535 characters (64 KB). While memo fields
can hold more information than text fields, they also have limitations such as the lack of lookup
functions and some of the formatting features available to text fields. Heavy use of memo fields
can also make your tables less structured and they should only be used when necessary.
Number
This type is for numeric-only values that might require calculations to be performed on them.
When you select the Number data type, you'll see a list of options under the Field Size instead
of a simple number. These are subtypes that determine how the number will be stored and
how much space each field will take in the database. It is determined by the maximum value
that can be stored in the field and the number of decimal places that can be used. The Long
Integer is the default and can store whole numbers (no fractions) from -2,147,483,648 to
2,147,483,647. Access uses four bytes to store a long integer. A normal integer (-32,768 to
32,767) only takes two bytes. The Single and Double types store floating point values
depending on the level of precision that you need. Choosing the right type can also help to limit
the type of values entered to prevent mistakes.
Date / Time
This type stores date and time values from the year 100 through the year 9999. Access
includes functions to add and subtract days, months and years within date fields. Date fields
can also be formatted and sorted in ways that text fields cannot be. Each field uses eight bytes
regardless of formatting.
Currency
The Currency type stores monetary values and formatting with up to 15 digits to the left of the
decimal point and four digits on the right. It also eliminates rounding during calculations. Each
value uses eight bytes.
AutoNumber
As I mentioned in Chapter II, this is a value that is generated by the database which cannot be
updated by the user. It can be set to start at 1 and increment for each record or it can be set to
generate a random unique value. This field can be stored as a random or incrementing long

Page 33

Microsoft Access for Beginners

integer which takes four bytes of space.


Yes / No (Boolean)
This is a field with only three possible values; 0, -1 and 1. It's often used behind checkboxes.
It's the smallest of all fields as it only needs to store a simple True or False value. While -1 and
1 both equal True, the extra possible value allows for checkboxes with three possible values
which can allow for an indeterminate value.
OLE Object
The OLE Object is a generic field used to store objects such as pictures or other files within the
database. The data is not directly readable within the table but the object can be opened by its
required application. The size of this field depends on the size of the object stored within it
although there are special considerations when storing images because the field does not
compress image data so the images will take up amounts of space far beyond their actual file
size. The field's maximum size is one gigabyte.
Hyperlink
This field type stores a three-part text value that enables a hyperlink to be stored and activated
from the table or a form field. The hyperlink field is broken down into three parts; the text
displayed in the field, the address / subaddress and the screen tip that is displayed when the
user moves the mouse over the hyperlink. Each of these parts can hold 2048 bytes (2 KB) for
a total of 6144 bytes.
Lookup Wizard
This is listed with the field types but is actually a wizard that configures the field to
automatically retrieve data from a table or query or to supply a list of values provided at design
time. The determination of the field type is made automatically after the steps of the wizard are
completed.
Attachment
The Attachment type was introduced in Access 2007 and is an improvement over the OLE
object field. An Attachment field can store multiple files in one record including images,
Acrobat files and other Office files. Double-clicking on the field in either form or table view will
bring up the Manage Attachments dialog where you can add, view, save and delete any of the
attachments stored. This field type uses less disk space than an OLE Object field when storing
images.
Calculated Fields
Introduced in Access 2010, calculated fields enable you to store the results of calculations

Page 34

Microsoft Access for Beginners

between fields within the same table row. For example, you could have two fields specifying
the number of items ordered and the price for that item and then a third, calculated field which
multiplies the two field values to get the total for that row.
While this might seem like a handy feature, it presents a couple of problems. Most seriously,
even though Access 2007 and 2010 use the same file format, calculated fields are not
compatible with Access 2007. If you add calculated fields to a database with Access 2010 and
even try to open the table in Access 2007, you'll get a message like the one in Figure 3.2.
You'll also see a compatibility warning as soon as you open the database and Access 2007
detects the use of the calculated field.

Figure 3.2 - Although the file format is the same, Access 2010 has features that are incompatible
with Access 2007.

Another problem is that calculated fields cannot be indexed which can slow the performance of
a database with large tables. The final, most basic problem I'll mention is that calculated fields
are a basic violation of database normalization as detailed in the last chapter. They take up
unnecessary space and can decrease the overall performance of your program.

Adding a Primary Key


One of the essential tasks of designing a table is choosing one or more fields to uniquely
identify each record. This is referred to as the table's primary key. Without a table key, it's
impossible to organize your data as shown in Chapter II. The primary key is important enough
that if you don't set one, Access will prompt you when you try to save the table design. A table
key can be a single field or a combination of fields (a composite key). In some cases, one field
is not enough to uniquely identify a record, so additional fields are needed.
While a primary key can be used to ensure unique data, its main purpose is to identify specific
records in the table and enable their retrieval. While designing the table structure for Job
Search Plus, I chose to use an AutoNumber field as the primary key for the Leads table. A
composite key including the Job Title, Record Date and Company ID certainly would have
been unique and could have served as the primary key but could not have been used to link to
the Activities table. For the sake of simplicity, I decided to let the database assign the new
value for each record by using the AutoNumber. This number is unique for each record in
Leads and can be easily shared by any other table that needs to reference this table.

Page 35

Microsoft Access for Beginners

Figure 3.3 - Most tables require a primary key that acts as an identifier for each row.

After you decide on the fields involved, setting a primary key is as simple as selecting the
field(s) in Table Design view, right-clicking and selecting the option from the pop-up menu as
shown in Figure 3.3. A small key icon will show up at the left of each field in the key.

Figure 3.4 - Indexes other than the primary key can be set to require unique values or
combinations of values.

After you set the primary key, the fields involved will show as indexed in the field properties.

Page 36

Microsoft Access for Beginners

The primary key is the main index for the table. If it's a single field key, then the index will not
allow duplicates for that field. For a composite key, each field in the index will allow duplicates
on its own but the combination of fields that make up the index will not allow duplicates.
The UniqueLead index demonstrates another way to ensure that data is not duplicated within a
table. This index is separate from the primary key as shown in Figure 3.4. Single or multi-field
indexes can be set as unique so that the database will not allow more than one record with the
same value or combination of values to be entered.

Field Properties
For each field in the table, there is a list of settings that you can use to customize how the
database displays and processes the data.

Figure 3.5 - The field properties grid

This is shown in the bottom half of the design screen and the list changes depending on the
data type of the field you're working with. The sample in Figure 3.5 is a Date / Time field which
has most of the settings filled in.
Many of these options display a small button on the right side as shown in Figure 3.5 for the
Format option. The drop down shown here will provide a list of options for the setting. Other
settings, like the Input Mask property, display a Build button which has an ellipsis (...) for a
symbol. Clicking on the build button will activate a wizard or dialog that will guide you through
the settings. It's important to pay attention to these settings whenever you are designing a
table. These give you full control over how data is entered into the table. The following notes
give a brief explanation of the major properties. For more information on any of these settings,
click inside the setting box and press F1.
Format

Page 37

Microsoft Access for Beginners

For number (including currency) and date types, this setting offers predefined formats for the
data being entered. Among other possibilities, currency can be formatted with or without
symbols and dates can be formatted to include weekdays. You can also define custom formats
if you want to add dashes or other symbols to your data. The advantage of using this setting is
that Access will automatically reformat the data as it's entered.
Input Mask
This is a great setting for controlling data entry. Whenever a user moves to a field with an input
mask, Access places a template inside the field to guide the user in entering the data. Access
can also use the input mask to create a password field where all characters entered are
displayed as '*'. As with the Format setting, you can select from pre-defined masks based on
the data type or you can create your own. Form fields will inherit masks from the table fields
they are based on.
Caption
Any text you enter here will be shown in the table header in place of the field name or as a
caption on forms. I prefer to use the Description property next to the field's Data Type selection
in the top half of the Design View screen if a field requires some explanation beyond the name.
Data entered under the Description will show up in the status bar when the user views the field
on a form.
Default Value
This can be helpful if a field is supposed to hold the current date or another value that can be
predicted. Using this setting when possible speeds up data entry and reduces error. In addition
to holding single values, it can also use calculations and formulas.
Validation
The validation settings are also useful for data entry control. In the example screen in Figure
3.5, this setting uses a formula to test that the date entered is less than 61 days in the future. A
date in the past would pass this test. A date three months from now would not. The validation
text setting provides an error message that the user will see when the table refuses to accept a
value. This test is only performed when entering new data or editing existing data. It will not
cause an error for data entered prior to the rule being setup unless that data is edited.
Required / Allow Zero Length
The database will not save a record that does not have entries for fields where Required is set
to True. I use this sparingly during design as it can be difficult to test a database with a lot of
required fields. Allow Zero Length is a setting for text fields that will determine if the user is
allowed to enter zero length strings for text fields. This needs to be used carefully because in
some cases it can be difficult to tell the difference between a field where there is no value (null)

Page 38

Microsoft Access for Beginners

and a field with a string that's zero characters long.


Indexed
An index is used by Access to speed up sorting and searching the data in a field. According to
the Access specifications, you can have up to 32 indexes on a single table although the more
indexes are present, the more work Access has to do to maintain these indexes. Indexes
should not be used on fields such as Boolean (True / False) fields where there are only two
possible values.
Indexes can also be used to prevent duplication of values. The index for a field is automatically
set as unique when choosing the field as the table key. If it's a composite key combining two or
more fields, then each field in the key might allow duplications on its own but the index will not
allow the fields to contain a duplicate combination of values. In Access 2007 / 2010, the
collection of indexes on a table can be viewed and managed by clicking on the Indexes icon on
the Access Ribbon while in table design mode. In previous versions, you can select it from the
View menu.

Figure 3.6 - Tables use indexes to help search for and sort data faster. The indexes dialog
enables the creation and editing of indexes.

Unicode Compression
In Access, text characters are stored with a character set that uses two bytes for a character
instead of one to allow for additional alphabets and symbols. Unicode compression is used to
offset the difference in fields over a certain size. New users can safely ignore this field and
leave it on the default setting
IME Mode / Sentence Mode
These are also settings that new users can pass by. They concern the use and display of

Page 39

Microsoft Access for Beginners

Asian character sets. For more information, refer to the help files.
Text Align
This setting was introduced with Access 2007 and determines how the information is aligned in
the field; left, right, center and full-justification.

Table Properties
In addition to individual field properties, an Access table has a panel of properties that apply to
the entire table. You can view these by right-clicking anywhere in the table design screen and
selecting Properties. The example in Figure 3.7 shows the panel in Access 2007 and the
following is a list of some of the key properties.
Description
When Details view is selected in the main database window, this value will show up next to the
table name. It can be useful, especially in large databases.
Default View
Most beginning users will stick with Datasheet which shows a simple row and column format.
The Pivot views listed here, though, provide a simple and flexible way to analyze the data in a
table with grouping and totals by specific fields.

Figure 3.7 - Tables feature properties such as validation rules that apply to the entire table.

Page 40

Microsoft Access for Beginners

Record Validation
In addition to validating the entry in specific fields, you can use the expression builder to
validate fields against each other and setup rules for the entire record.
Filter
By placing a filter on a table, you can restrict the number of records that you want to view at
one time. This can be useful for very large tables or when accessing data from other
databases.
Order By
The default order of records as displayed by the table can also be set for one or more fields.
Subdatasheet / Child and Master Fields
When viewing the data in a table, you can show subdatasheets for linked tables. In this
example, when viewing the Leads table, a datasheet is set to display for every activity on each
job lead. When you select the table or query to use, the Child and Master fields are
automatically set by default. This can be changed if necessary.

Figure 3.8 - Datasheet View features subdatasheets based on table relationships.

The subdatasheet height setting sets the maximum height of the subdatasheet when
expanded. A vertical scroll bar will be shown if the number of records exceeds this height.
The subdatasheet expanded setting, when set to 'Yes', automatically expands the
subdatasheet for each record in the table view.
Orientation
The table can be set to display fields and related controls either left-to-right or right-to-left.

Page 41

Microsoft Access for Beginners

Relating Tables
Once you've created the table, the next step is to decide how it's going to relate to the other
tables in the database. This can be done through the Relationships window which is displayed
by clicking on the Relationships button under the Database Tools section of the Access 2007 /
2010 ribbon. In earlier versions, select Relationships from the Tools menu.

Figure 3.9 - The relationships window enables you to click and drag fields to create relationships
between tables.

If you don't have any relationships defined yet, the Show Table dialog will appear as soon as
you open the Relationships window. Double-clicking on the tables in this dialog will add them
to the Relationships layout. If the dialog doesn't appear, right click on any empty space in the
Relationships window and select Show Table from the pop up menu.

Page 42

Microsoft Access for Beginners

To set a relationship, click on the field in one table, such as the primary key, and drag that field
to the corresponding field from another table. For example, the relationship between the Leads
and Activities tables would be created by clicking on the LeadID field in the Leads table (the
Primary Key) and dragging it on top of the LeadID field in the Activities table.
If you want to try this, right-click on the relationship line between the two tables in the
Relationships view, choose Delete from the pop-up menu and click Yes to confirm. Then click
on the LeadID field in the Leads table and drag it on top of the LeadID field in the Activities
table. The dialog in Figure 3.9 should appear.

Figure 3.10 - The Edit Relationships dialog enables you to set the relationship type between
tables.

Notice the LeadID field under both tables and that Access has already assigned a one-to-many
relationship based on the fact that LeadID is the primary key in Leads and that it's not unique
in Activities. Referential integrity is not set so this is a good time to choose the settings.
The Cascade Update and Cascade Delete options determine how the database will respond if
the field value is changed in a row in one of the related tables. If referential integrity is
activated without selecting either of these options, then the database will not allow deletions or
updates on the 'one' side of the relationship. For example, if you tried to delete a record in
Leads that had corresponding records in Activities but Cascade Delete wasn't chosen, you'd
get a message like this:

Figure 3.11 - Referential integrity protects the relationships between tables.

Page 43

Microsoft Access for Beginners

On the other hand, if Cascade Delete is chosen, you'd get a confirmation message notifying
you that corresponding records in the Activities existed and asking if you really wanted to
delete the record. I did not design the database to allow lead records to be deleted so my
choice for settings would be to activate referential integrity without any cascade options.
The Join Type button on the Edit Relationships dialog enables you to decide what kind of join
will exist between the tables.

Figure 3.12 - The Join Properties dialog enables you to specify which table has the priority in the
relationship.

The first option shown in Figure 3.12 is an Inner Join. Only records in Leads that have
corresponding records in the Activities table will be shown in the default join between the
tables. I don't really want this since some job leads might not have any activities on them. The
second option is what's called a Left Outer Join which shows ALL records from Leads and then
any corresponding fields from Activities. This would be my choice because I want to give
preference to the Leads table in any queries. The third option would create a Right Outer Join,
giving preference to the child table (Activities) and only showing the records in Leads that
match.
The names I'm using for the joins are the names used in SQL and you can read a more
detailed explanation in the introduction to Structured Query Language in Chapter V.
Tables can have more than one relationship as shown by the relationships between Leads and
Companies and, in a large database, the relationships can get complicated. You can actually
show and hide tables within the Relationships window without affecting the relationships
between them and then restore all tables by right-clicking within the window and choosing
'Show All' from the pop-up menu.

Conclusion
In this chapter, I've explained the settings that you'll encounter in Access table design. Access
is a powerful program and with that power comes a certain amount of complexity. There are
some settings in the table design panel that you might not use for a long time, if at all, and still
produce very professional databases. Still, the more features you are aware of, the more

Page 44

Microsoft Access for Beginners

options you will have available to you when building your solutions.
Getting familiar with the various features of table design and the settings shown here is
actually one of the most straightforward aspects of learning to work with databases. At the
same time, it includes some important concepts such as proper use of data types and data
entry validation. I'd encourage you to take some time to experiment with these settings. The
more you know, the better your databases will be.

Page 45

Microsoft Access for Beginners

Chapter IV - Writing the Queries


Introduction
A database storing every bit of knowledge you could ever need wouldn't be of much use
without some way to retrieve the data. After I create the tables, my next step is usually to
create the forms for the database but first I need to provide some information on queries. Many
of the queries that you use will actually be created automatically as you design forms and
reports which use them to obtain the required data. If you do any significant amount of work
with Access, you will need to know how to construct queries for those times when you need
something specific.

Background
Microsoft Access uses Structured Query Language (SQL - often pronounced "sequel") in order
to manipulate the data in the database tables. It is not necessary to know this language in
order to create queries and work with Access but going the extra mile and being familiar with it
will make you more productive if you decide to continue working with Access and other
databases long-term. In addition to viewing the data as shown in the example in this article,
queries can also be used to add, delete and change data from various sources based on the
criteria that you specify.
If you don't have the demo database open already, open it now. Press F11 to view the
database window. Select 'Queries' under the Objects selector. Open the query titled 'LeadsList'
by right-clicking on it in the window and selecting 'Design View'.
The Query by Example (QBE) window enables the user to quickly create the desired query by
selecting the appropriate tables and fields and setting the right options to retrieve the data.
When you use the QBE screen, Access writes the necessary SQL behind the scenes.
Figure 4.1 shows the screen you'll see when you open the query in design view. Figure 4.2
shows the raw SQL code behind the query. It looks complicated until you break it down by
keywords shown in all caps such as SELECT, FROM and GROUP BY. Then notice that much
of the rest is made up of table and field names with a few formulas here and there. At this
point, it actually becomes very simple to learn. In a later chapter, I'll show you how to write
SQL queries without using the QBE window.

Page 46

Microsoft Access for Beginners

Figure 4.1 - The Query By Example designer

The LeadsList query is a simple query based on the Leads and Companies tables that
demonstrates the different functions of the QBE window. This type of query is known as a
SELECT query as it doesn't actually affect the data in any way. It only selects it for viewing
based on the user's specifications. By default, all new queries are Select queries until you
specify otherwise.

Figure 4.2 - SQL View

Other query types include:


APPEND - Queries can be used to append data to a table from another source such as
other tables, queries, user input or real-time calculations.
DELETE - You can delete groups of records from a table based on one or more criteria.

Page 47

Microsoft Access for Beginners

MAKE TABLE - Queries can create new tables from the same sources used by Append
queries.
UPDATE - Values can be changed throughout a table using an UPDATE query. This
might be handy if a certain mistake has been made consistently when entering
numerous records or if a piece of data such as an area code changes.
All of these query types and more can be created using the Query menu in the query design
view. In Access 2007 / 2010, look for the Query Design option under the Create menu. Check
the help files for more information on each of them and take some time to play around with the
different options.

The LeadsList Query


When you create a new query, you'll see that the program immediately asks you to add tables
or other queries to the new query. The LeadsList query is adapted from the query behind the
main Leads listing screen in the database and includes the Leads and Companies tables. In
Figure 4.5, you can see how the one-to-many relationship that already existed between the
tables is automatically included.
You can add and remove tables from a query and manage the relationships between them
much as you would in the Relationships window as explained in Chapter II. To add a new
table, right-click in the top half of the QBE window and select the 'Show Table' command. The
query will automatically add any relationships that exist between that table and the others in
the database. The relationships between tables can be changed in a query without affecting
the rest of the database. This is handy when you want to create queries that perform analyses
from a different perspective than normal. Double-clicking on a relationship line within a query
shows a dialog like the one in Figure 4.3 that displays both the tables and fields involved and
the type of join it represents.

Figure 4.3 - Tables can be joined in a query design just as they are in the relationships window.

Page 48

Microsoft Access for Beginners

For this query, the default relationship works fine as it will show all active job leads and the
necessary company information for each one. If there is no company entered for a lead, blank
fields will be shown. If I wanted to, I could double-click on the relationship line shown here and
change the relationship for this query to get different results. It would not affect anything else in
the database.
You can add fields to your query by double-clicking on the table fields in the top half of the
window shown in Figure 4.1. You can also select multiple fields by holding down the CTRL or
SHIFT keys and then add them by dragging the selected fields to the grid in the bottom half of
the window. Selecting the asterisk (*) at the top of the field list selects all fields in the table.

Navigating the Design Grid


The bottom half of the query window is known as the design grid. The first two rows in the grid
show the relevant field and table names. If you place your cursor in any of these spaces, you'll
notice that a selector button appears on the right side of the text. This tab enables you to
quickly change the selected fields or table if necessary.

Figure 4.4 - Displaying the Totals row in query design view

The Total row shown in the example does not appear automatically when you create a new
query. You activate it by clicking on the toolbar icon (in Access 2003 and earlier) or ribbon icon
(in 2007 and later) or by right-clicking on the design grid and selecting 'Totals' from the context
menu as shown in Figure 4.4. This row specifies aggregate functions for the columns in the
query. These functions enable you to group the data in the query and return calculations based
on those groupings such as averages and row counts. Once you activate this row in the query
settings, each field must have one of these functions specified. Group By is the default setting
for each column in the query.
As an example of what you would do with aggregate functions, suppose you had a query that
returned a simple list of job leads with company information for each lead. You could change

Page 49

Microsoft Access for Beginners

the function under the LeadID field to 'Count' and then include the City or ZIP fields as Group
By fields. This would return a list of Cities or ZIP codes, depending on the field that you used,
with the number of job leads for each item in the list. In a query that linked the Leads and
Activities tables, you could create a query that used the Max function to return the latest
activity date for each job lead. These are just a couple of things that you can do with all of the
functions available and you should take time to experiment.

Figure 4.5 - The Totals, Sort and Criteria rows can be used within the Query Design Grid to
analyze the data within your tables.

The Sort row specifies the sort order by field. In this example, if you select more than one field
to sort on, the query will give preference to the first selected field on the left and work its way to
the right of the query. In other words, if I sorted by job title and location, the records would be
sorted by job title and then if there was more than one lead with the same title, it would sort
within that title by location. You can change the order of the columns in the query window by
selecting and dragging them around.
The next row in the query window, Show, specifies if a field should be shown or hidden in the
query results. In some cases, you might use a field to specify criteria for a query but not
actually want to show it in the results.
The Criteria rows in the design grid supply the criteria or desired values for each field in the
query. In the LeadsList query, there is only one field that has criteria added and that is the
Active field which is a Boolean (True/False) field. I've specified 'Yes' (True) to show only active
leads. You can also use values and expressions to specify what rows should be returned. For
example, you could enter an expression like > 1/1/2011 to only return leads that were entered
after January 1, 2011 or Like A* in the City field to specify job leads where the city starts with

Page 50

Microsoft Access for Beginners

'A'. In both cases, Access will add delimiters around the sample values that you enter; the
pound sign in the case of date values and double quotes for string values.

Figure 4.6 - By using the Criteria row in query design view, queries can accept parameters from
the user.

The criteria fields are very flexible and can even contain equations and specialized functions
that present choices based on user input. Using the 'Or' row and the rows below it, you can
specify multiple alternate conditions for a field. Specifying conditions for multiple fields such as
JobTitle and Location, on the same criteria row would act in a cumulative way to limit the
records returned. For example, specifying criteria for the JobTitle and Location fields on the
same criteria row means that the query will be limited to records where both of those criteria
are met while if you specified the criteria on different rows, the query would return records
where either condition was true.
Figure 4.6 shows another way to use the Criteria field. A bracketed value has been entered in
the Criteria row for the Location field and the screenshot shows the result after I clicked on
Datasheet View. The text in brackets becomes a user prompt that accepts a parameter for use
in the query. The brackets actually indicate to Access that a field value is being specified as
the criteria but Access doesn't recognize that field name so it requests the value of the field
from the user. It will apply whatever value is entered in the input box as the criteria value.

Getting the Results


After creating the query, it's time to run it. There are two ways of seeing the results of a query.
In the case of a SELECT query like this one, there is no difference between the two. It's
important to know the difference when running other types of queries, though, and to be in the
habit of using the right one because otherwise the consequences can be disastrous.

Page 51

Microsoft Access for Beginners

Figure 4.7 - There are two ways to view the results of a SELECT query.

Datasheet View, available through a pull-down option on the left of the toolbar or ribbon, will
show you the records affected by your query without actually running it. This distinction
becomes important when you are working with queries that are adding or changing data in a
table. By using datasheet view, you can see the affected records without actually committing
the changes.
The Run option, activated by the exclamation point highlighted in Figure 4.7, actually runs the
queries and performs any actions specified. If data will be changed or deleted, Access will
warn you about the changes and ask for verification unless this option has been turned off.
Once verified, however, the changes are permanent.
To be safe, it's best to use Datasheet View when working with select queries like this one so
as to develop the right habits.

Figure 4.8 - Datasheet View shows the records affected by the query without applying any
changes made.

Beyond Field Selection


Queries can do more than select data for display and I want to point out a couple of other
things about the LeadsList query that demonstrate this.

Page 52

Microsoft Access for Beginners

The first example is the CompanyLocation field in the LeadsList query. This is an example of
how expressions can be used to manipulate separate fields into one value. In the original
query, the city and state are contained in separate fields. While this might be okay in some
cases, I want the query to combine these two values into one that shows the company's
location.
By right-clicking on the CompanyLocation field in the Field row and selecting 'Build' from the
pop-up menu, you can display the Expression Builder. This tool is very useful for building
expressions and adding them to query fields.
In Figure 4.9, you can see how the lower left-hand box in the Expression Builder displays all of
the objects within the database by category along with some extra features such as functions
that you can use in your expressions. The first item in the box is the LeadsList query that the
Expression Builder was opened from. In the middle box, it displays all of the fields within the
query.

Figure 4.9 - With the Expression Builder, you can design sophisticated expressions for use in
queries.

To build an expression, just double-click on the necessary objects in the lower boxes and add
the correct operators using the buttons below the expression area at the top. You can also
paste an expression in the box and modify it as needed. For this example, I've created a
simple expression that will concatenate the city and state fields into one value with a comma
between them.
This expression combines the three values into one using the concatenation character (&). I've
added a comma and a single blank space between the city and state values. Any non-field text
that's added must be surrounded by quotation marks. Thus, 'Atlanta' and 'GA' would become

Page 53

Microsoft Access for Beginners

'Atlanta, GA'.
It's not necessary to include the table names since the field names are unique within the query.
When using a field name that exists in more than one table and both of the tables are
represented in the query, it's then necessary to enter it with the table name (i.e.
'Companies.State'). If there are any spaces in the field or table names, remember to use
brackets around the name so Access will recognize it as one name (i.e. [Employees].[First
Name]). The same holds true in the Expression Builder as shown in Figure 4.9. The brackets
around the field names are the way Access indicates the name of an object such as a field,
table or form name. The brackets are optional unless there is a space in the name.
After entering the expression and clicking the OK button, Access inserts the expression back in
the design grid in place of the field name that was there before. It also adds a name to the
expression since the query field needs a single name for the field. This name can be changed
to anything that complies with Access field name rules.
One question you might be asking is "Why go to the trouble of storing the name or the city and
state information in two parts only to combine it again?" One reason is that you have greater
flexibility in the way data is used. The CompanyLocation field in the query cannot be sorted by
state, for example. Breaking the information down into the smallest useable parts makes the
data more versatile. This is referred to as atomicity' in database theory and discussed in the
rules of database normalization from Chapter II. There is some flexibility when it comes to
something like the employee name and the decision depends on the needs of the organization.
Queries can also call functions in order to manipulate data while the query is running. Like
Microsoft Excel, Access includes a long list of built-in functions that you can use to perform
calculations. These functions and any custom functions that you design, can be called by
queries in order to display the necessary results as part of the query. The LatestActivity field in
the LeadsList record source is an example of this.
LatestActivity:
DMax("[ActivityDate]","Activities","[LeadID] = "
& [Leads]![LeadID] & " AND [Complete] <> 0")

This field actually calls two functions, one nested inside the other, and a table that's not
officially included in the query. The DMax (domain maximum) function will retrieve the
maximum value from a field within a specific domain such as a table. A simplified example of
the one shown in the database would look like this:
DMax("[ActivityDate]", "Activities" , "[LeadID] = " & [Leads]![LeadID])

The DMax function is a kind of query in and of itself. It looks for the maximum value in a
specific field based on the specified criteria. In this example, it's looking at the ActivityDate field
from the Activities table. It then limits its search by the LeadID field using the LeadID value
from the current query record.

Page 54

Microsoft Access for Beginners

The result is that for each lead shown in the query results, you will see the date of the latest
activity recorded for that lead. The function used in the actual query takes it a step further and
adds a second condition to the function; it only searches activities that are marked as
complete. This means that you will see the date of the last completed activity on the lead.
The second function used is the Format function which will take the date generated by DMax
and format it as directed. In this case, it uses the 'Short Date' format which would be
MM/DD/YYYY.

Figure 4.10 - Expression results being returned as part of query results.

One thing to note here is that these calculations are being done separately for every record in
the query. In this case, it doesn't cause a problem because there aren't that many records and
for each record, the DMax function only looks at a few activity records at the most. If this query
returned a few hundred records, however, or the calculations were individually looking at more
data, the time that it took to run the query could become a problem.
There are two design considerations here; first that the number of records being accessed at
one time should be limited where possible. The first limitation occurs naturally in the number of
activities per lead as most leads will only have a few activities. The second limitation is in the
use of filters on the query, in this case 'Active = True'. The query only looks at job leads that
are still open. Data retrieval uses resources like memory and bandwidth, especially if you're
accessing a database over a network or a server database like SQL Server. In a database with
multiple users, it can also cause records to be locked unnecessarily. Data inconsistencies or
even corruption can occur if rows are changed but not correctly updated back to the database.
Retrieving unnecessary data also takes time which can cause noticeable delays in your
program. Your database might be rich in data but it should be thrifty in the way it accesses that
data.
The second design consideration is where a calculation should be performed. In this example,
I decided it was okay to place it in the query but if the calculation took longer to perform and
there was another place to do it, for example on a form or report that pulled a single record at a
time, I might put the calculation there instead. Of course, I would also check for ways to reduce
the amount of time the function was taking. It's best to learn to think of these things now
because if you find yourself working on more sophisticated systems, the efficiency of your
program might affect more than the local user.

Page 55

Microsoft Access for Beginners

The Role of Queries


In this chapter, I've shown you a query as a standalone object within the Access database.
This is not the only place you will find a query in Microsoft Access. Queries are the primary tool
Access uses to retrieve information for use within your applications. They can be very useful
when stored as standalone objects but they are also used as the record source for forms and
reports.
In Figure 4.11, you can see the properties for the main listing of the job search program. The
first property is the Record Source which defines the data available to the form. The Record
Source is in the form of an SQL query and if you were to click on the Build button to the right of
the field, it would bring up the QBE window with a query very much like the LeadsList query
you've been looking at in this chapter.

Figure 4.11 - Queries are used as the record source for forms and reports.

I could also use a standalone query object for this source. Queries are also used as the record
source for reports and can be called from VBA code. Finally, a SELECT query can be included
in another query just as you would include a table. This makes the records returned by the first
query available as a data source to the second query.
You'll learn more about all of these items in later chapters. Right now, it's just important to
understand that queries are pretty much everywhere in Access. They act as both data retrieval
and manipulation tools and as data sources.

Page 56

Microsoft Access for Beginners

Conclusion
As you continue to work with Microsoft Access and get into some of the more advanced
functions, you'll see that the program often treats tables and queries very much the same. As a
database management system, Access deals primarily with data, not the objects in which it is
stored. Further, both tables and queries can exist as abstract collections of data in memory
without being bound to the table and query objects that you see in the database window. This
might not be something you need to be concerned with now but understanding this can help
you avoid some confusion later on.

Page 57

Microsoft Access for Beginners

Chapter V - Understanding SQL


Selecting Data
In the chapter on queries, I briefly wrote about Structured Query Language (SQL) which
Microsoft Access and other relational databases use to select and manipulate information.
SQL (often pronounced "sequel") is a scripting language resembling English that is used to
relay instructions to the database and specify exactly what is to be done with the data. Many
Access users might think of a query as an object within the database window that can be run
to retrieve data but the query is actually the SQL code within this object. The Query By
Example (QBE) window that most Access users are familiar with is simply an interface that
makes it easier to select tables and fields and specify what the query should do. As you use
this interface, Access writes the SQL code, referred to as an SQL statement, in the
background and saves it when you click the save button in the query designer.
In addition to these standalone queries, SQL statements can be used as the data source for
forms, reports and controls within Microsoft Access. SQL statements can also be issued from
macros and within VBA code in order to automate operations on data. If you move beyond
Access to databases like Microsoft SQL Server, you will also see that SQL statements can be
run from a command line to affect data being stored in a network database. The following are
examples of queries that you could actually run on the Job Search Plus demonstration
database and you might find them self-explanatory.
SELECT * FROM Leads WHERE Location = "Atlanta, GA";
UPDATE Companies SET City = "Tampa" WHERE CompanyID = 6;
DELETE FROM Activities WHERE LeadID = 2;

(The asterisk [*] is a wildcard symbol used to indicate all columns in record source. It is not
required for DELETE queries in Microsoft Access.)
Many Access users will rely on the QBE interface to construct queries as needed. While this
might be all that you need when designing applications, it's important to understand the basics
of SQL if you actually want to understand how your database works. You will be much more
efficient when it comes to retrieving and analyzing data if you can write at least basic queries
rather than depending on whatever interface might be available at the time, especially if you
use other database systems. Despite its appearance, SQL is a very simple language that you
can learn the basics of with a day or two of practice so there's really no reason to avoid it.

Page 58

Microsoft Access for Beginners

Behind the Scenes

Figure 5.1 - The Query By Example (QBE) grid provides a easy way to create new queries.

You can view and edit the SQL statement directly by opening the QBE window and selecting
'SQL View' from the View menu or by right clicking within the tables area in the QBE window
and selecting it from the pop-up menu.. Figures 5.1 and 5.2 show the LeadsList query which
shows basic information on each lead and links to the Companies table for company details.
At first, the SQL view looks like a confusing mess until you focus on the keywords shown in all
caps in Figure 5.2. Notice that all of these keywords are followed by table and field names.
Each of these keywords corresponds in some way to a part of the Query Builder window.

Figure 5.2 - SQL View shows how the query is written in the background.

Page 59

Microsoft Access for Beginners

When processing the SQL statement, the program ignores extra white space and lines in the
statement. I formatted the statement below as I usually do for readability but I could also put
everything in one continuous line or every word on a separate line and Access would read it
just as easily. I've also removed the table names from the code below to simplify things.
Specifying the table names before the field names often isn't necessary in queries unless you
have the same field name in more than one table.
SELECT JobTitle, EmploymentType, CompanyID, Description, Active
FROM Leads
LEFT JOIN Activities
ON Leads.LeadID = Activities.LeadID
WHERE Location = "Orlando, FL"
GROUP BY JobTitle, EmploymentType, CompanyID, Description, Active
HAVING Active <> 0
ORDER BY EmploymentType;

Let's take a look at the individual parts:


SELECT FROM - First, the query specifies the fields to be displayed. It lists the fields that are
to be shown in the order they are placed in the grid and separates them with commas. Notice
that the Location field is not listed, even though you'll see it further down in the query. In the
QBE window, the Show checkbox for the field would be cleared as it's only being used in the
query to provide criteria to limit the records returned.
JOIN ... ON - SQL uses JOIN clauses to refer to the relationships between tables. These are
much the same as the relationships that are defined between tables in the Relationships
window. In this case, it means that all of the records from the table on the left side of the
relationship (Leads) are available to the query while only the corresponding records from the
right side of the relationship (Activities) are available. This join displays all employees,
including those who have no records in Activities. This is also referred to as a Left Outer Join.
An Inner Join would only show employees who had records in both tables. The ON keyword
specifies the fields on which the tables are to be joined, in this case the LeadID field. The
corresponding fields on which two tables are joined must be of the same data type in order to
permit a join.
The use of the words LEFT and RIGHT do not refer to the placement of the tables in the QBE
window but rather on their order in the relationship. In this case, the value of the LeadID field is
supplied by Leads on the left side of the relationship because the LeadID field is the primary
key for that table. The Activities table uses that value to link an address record to an employee
record and is therefore on the right side of the relationship.
Thinking of LEFT and RIGHT for table relationships can be confusing but it might help if you
compare it to reading a sentence from left to right, and think of the parent table (the table that
supplies the value for the field that's being linked on) on the left. As you move to the right of the
relationship, you see the child tables that use the field as a foreign key to link to the parent
table. A LEFT JOIN would therefore be a join that starts from the left of the relationship (Leads

Page 60

Microsoft Access for Beginners

in the SQL example) and a RIGHT join would start from the right (Companies). Note the word
OUTER is optional in both relationships. Both of these conditions place a priority on one of the
tables, selecting all records from one and matching records from the other. An INNER JOIN
only looks for matching records in both tables.
WHERE - This clause specifies the criteria that each row must meet in order to be included in
the results. In this example, we're looking for records where the Location field equals a
particular string. This clause can specify multiple conditions using the AND / OR keywords and
parentheses to group conditions for the right result. Some of the possible WHERE clauses in
this sample could be:
WHERE JobTitle = Driver
WHERE Active <> 0 AND Location = Orlando, FL
WHERE (Active <> 0 AND EmploymentType = Full-Time) OR EmploymentType =
Freelance

GROUP BY - Group By is used to create groupings within the data based on specific fields.
This query is grouping by the fields in the query that identify the job lead, they are listed here in
the order shown on the design grid. Grouping is the default treatment for fields in SQL queries
and is only noticeable in the end results when aggregate functions like counts or averages are
applied. For example, in the following query, the COUNT() function is used to get a count of
leads in each group.
SELECT Count(LeadID) AS CountOfLeadID,
RecordDate, EmploymentType, Location
FROM Leads
GROUP BY RecordDate, EmploymentType, Location;

The groupings in the query are applied in the order that they're shown in the statement so this
query is going to group first by the date the lead was recorded. If that was the only grouping,
you would get a list of recording dates and the number of leads for each date.

Figure 5.3 - A query of the Leads table showing number of leads by date.

Then the query breaks out the results by Employment Type and finally Location so the final
query returns the job lead count for each combination of RecordDate, EmploymentType and
Location in the table.

Page 61

Microsoft Access for Beginners

HAVING - HAVING is used to limit the records returned based on properties of groups defined
by the GROUP BY clause and cannot be used unless GROUP BY is present. The difference
between WHERE and HAVING is that WHERE is applied to individual records before the
query performs any grouping. If you specify a particular city in the WHERE clause, only
records with that city will be returned. HAVING is applied after the grouping is done. In Figure
5.4, you could use HAVING to return only the cities for which there was more than a specific
number of leads found. This would have to be done after the SQL statement completed the
grouping by city so it would be done through the HAVING clause. The HAVING keyword is
more often used to select by the results of aggregate functions like COUNT or AVG.

Figure 5.4 - Adding fields to the query gives a more detailed view of the data.

ORDER BY - The final keyword lists any fields used to sort the query results. In the example
query, the records are sorted by the Employment Type. Again, you can sort by multiple fields
and the results will be sorted according to the order of the sorted fields in the SQL code.
Note that the semicolon at the end of the ORDER BY clause is not part of that clause but
actually indicates the end of the SQL statement. This indicator is optional but if you include it
and then continue the statement after it, you will not be able to run the query.
The example in Figure 5.5 also demonstrates the WHERE and HAVING keywords. This is a
short query on a database I created to analyze data from my website logs. The query shows
the number of page requests and it groups the data by the file name requested from the site
(shown in the cs-uri-stem field). The Count() function on the first line counts the number of
requests in each group. The WHERE clause uses the Like keyword to limit the query to certain
types of content, in this case, it's using the asterisk (*) wildcard to select all files that end with
the ZIP extension. Finally, the HAVING clause uses the Count() function again to limit the
query results to groups with a count of over 100. In other words, I only want to see cases
where a specific type of file (ZIP files) was requested more than 100 times.

Page 62

Microsoft Access for Beginners

Figure 5.5 - Another example of the WHERE and HAVING keywords in SQL.

SQL contains many other statements, commands, operators and functions but the ones listed
above will be enough to keep you from feeling lost when you view the SQL for a query.

Modifying Data
Beyond selecting records, SQL is also used to change data when necessary. With some very
simple statements, you can make changes to large numbers of records or very precise
changes to a single record. Using some of the same clauses that you would use for SELECT
statements, you can be very specific about what changes you make.
SQL statements that change data are often called action queries or data manipulation queries.
The most important thing to remember with action queries is that they cannot be undone. Once
the data is changed, the only way you're going back to the original data is if you have a backup
of the database. For this reason, it's very important to double-check your queries before
running them. The old saying 'Measure twice, cut once' applies. Of course, it's also good to
backup the database every so often.
Here are some of the common action queries you can use in Access and other databases. You
can test each one of the sample queries in the demo database.
UPDATE queries
With UPDATE queries, you can change a single record or large numbers of records with a
single statement. The syntax is a little different than the SELECT statement but still pretty
straightforward.

Page 63

Microsoft Access for Beginners

UPDATE Leads
SET Active = 0
WHERE Location = "Atlanta, GA";

The first line specifies the table to be updated and the SET clause uses a simple expression to
set the Active field to '0'. The WHERE clause is important here as it limits the records on which
the change is made. Without this clause, the query would change the Active field for all leads
to '0'. In a really large table, you might find yourself wondering why the query is taking so long
and then realize with a sinking feeling that you'd forgotten the vital WHERE clause and that
you're changing a lot more records than you meant to.
Microsoft Access offers Datasheet View within the Query Builder to show you the results of the
query before it's executed and it's a good idea to get in the habit of using this. Since other
database systems like SQL Server don't offer Datasheet View, another way to avoid such
mistakes is to write queries as SELECT queries first to see what records will be affected and
then changing it to an action query. This is also a good way to get practice writing SQL
statements. The example below shows how this would be done with a simple query.
SELECT *
FROM Leads
WHERE Location = "Atlanta, GA";

Becomes
UPDATE Leads
SET Active = 0
WHERE Location = "Atlanta, GA";

JOIN clauses can also be used in UPDATE statements when two or more tables are related
and you need to make changes in one table based on an identifying record in another. Here's
an example:
UPDATE Leads
INNER JOIN Companies
ON Companies.CompanyID = Leads.CompanyID
SET Leads.Active = 0
WHERE Companies.State = "GA";

This is a variation on the earlier query which sets the Active field to 0 based on the location.
Instead of using the Location field in Leads, it uses the State field in the Companies table. The
two tables are linked on the CompanyID field so the query uses a join to ensure that only the
Leads records that link to Companies in Georgia will be updated. An INNER JOIN is used to
limit the records with the value in both tables.

Page 64

Microsoft Access for Beginners

DELETE queries
DELETE queries are used to delete records from specific tables and again, I will emphasize
that these queries cannot be undone so it is important to carefully check the query before
executing it.
The syntax for a DELETE query is actually very similar to a SELECT query so it's easy to use
the method I mentioned earlier of creating the SELECT first.
SELECT *
FROM Activities
WHERE LeadID = 3;

You can change this to a DELETE query by changing one word:


DELETE
FROM Activities
WHERE LeadID = 3;

As with SELECT and UPDATE queries, you can join on other tables to determine which
records will be selected for deletion.
INSERT INTO (Append) queries
With SQL, you can insert new records into tables, using either a combination of values
assigned to the fields or records from another table. You can even copy records from a table
back into that same table, changing selected values as needed.
INSERT INTO Companies (CompanyName, City, State)
VALUES "ProSoft", "Ocala", "FL";

In the query above, the INSERT INTO clause names the table that will receive the records with
the second line specifying the field names. The VALUES clause specifies the values to be
entered in the same order as the field names.
Here's another example where records are copied from one table into another.
INSERT INTO Leads (RecordDate, JobTitle,
Description, EmploymentType, Active)
SELECT Date(), Title, Details, EmploymentType, Active
FROM tblLeadImport;

The above is an example where records from an import table are being imported into Leads.
The names in the import table are slightly different but so long as the data types of the fields
are compatible with the fields in the target table, it will work. The first field in the SELECT
clause isn't even coming from the Import table; it's the Date() function which will provide the
current date. Also notice that after the INSERT INTO clause, the rest of the query is an

Page 65

Microsoft Access for Beginners

ordinary SELECT statement. It could even use a WHERE clause to limit the records being
transferred from tblLeadImport.
INSERT INTO Activities (Activities.LeadID, ActivityDate,
ActivityType, ActivityDetails, Complete)
SELECT 4, Date(), ActivityType, ActivityDetails, Complete
FROM Activities
LEFT JOIN Leads
ON Activities.LeadID = Leads.LeadID
WHERE Leads.LeadID = 5

The above query would copy all the activities for one job lead back into the Activity table under
another job lead number. It uses a join on Leads to help identify the records to be copied by
the LeadID. The result is that the query finds records matching a LeadID value of '5' and
copies them, replacing the LeadID with '4'.
The above query will run as shown but if you switch to design view and then back to SQL view,
you might see extra text added after the specified values; 'AS Expr1' is added after '4', etc..
These are referred to as aliases and are used as shortcut references to elements within a SQL
statement. Access SQL assigns these aliases to values that are manually entered like the
ones in the example. Aliases can also be assigned to tables as shortcut references for long
table names.
The important thing to remember with INSERT queries that you must supply values for any
required fields in the target table or the query will fail when you try to run it.
MAKE TABLE queries
Sometimes you might want to export data from one table to another. One way to do this is to
use a Make Table query. By this time, you'll find the SQL statement pretty familiar.
SELECT LeadID, RecordDate, JobTitle,
Description, EmploymentType, Location, Active,
CompanyID, AgencyID, ContactID,
SourceID, Selected
INTO LeadsCopy
FROM Leads
WHERE RecordDate < DateAdd("d",-30,Now());

This query copies all records from Leads where the RecordDate is more than 30 days prior to
the current date into a new table called LeadsCopy. The new table doesn't have to exist before
you run the query. The query will create it on its own. Access even assigns the correct data
types. The only difference between this and a SELECT query is the INTO clause which
specifies the destination table.

Page 66

Microsoft Access for Beginners

Conclusion
There are additional types of queries available in Access that enable you to retrieve and
analyze data in different ways but the four mentioned here should give you an introduction that
you can build on as you learn to write your own queries. Learning how to write SQL
independently of an interface is an important step in realizing the power available to you when
working with Access or any other database.

Page 67

Microsoft Access for Beginners

Chapter VI - Designing the Forms


Introduction
In Chapters II and III, I demonstrated how to build the foundation of your database application
with properly designed and related tables. Then I showed you how queries can read and
manipulate the data you've stored in your tables. Now you need a way for the average user to
quickly access and edit the data when needed. As wonderful as a properly designed set of
tables and queries is, the database window does not provide a great interface for someone
who knows little about the structure of your database or even for you on a regular basis.
The word 'interface' is important because that is what you are designing when you create a
data entry form. A well-designed application interface does the following:
Provides easy access to the features of the program
Simplifies data entry and retrieval with fields that anticipate, where possible, the values
to be entered
Helps to ensure correct data entry and protects existing data by providing templates,
masks and validation rules that require items such as dates to be entered correctly
Anticipates user error where possible and prevents or corrects for it
Offers as much compatibility as possible with accepted design standards and user
expectations so as to minimize the learning curve required to use the program
Conforms to the user's natural workflow so that data can easily be entered and updated
in the relevant order
This represents the ideal that you can work toward as you gain experience with Access and
other programming tools. When you design an interface with these goals in mind, your
programs are more likely to be readily accepted by other people and you will have an easier
time training people on how to use them.
I design my Access applications so that the average user will never have to directly open a
table or even view the database window. All work should be completed through the forms and
menus. This reduces errors and the chance of a necessary form or query being accidentally
deleted or records being improperly deleted from a table. It's not necessary to completely
prevent access to the database window except in the most secure applications as some users
might be qualified to add their own queries and tools. You should, however, do everything you
can to minimize the confusion for those who aren't.

Page 68

Microsoft Access for Beginners

A Word about VBA


For me, any discussion of forms includes references to Visual Basic for Applications (VBA), the
programming language that Access uses to provide extra functionality behind forms and
reports. In this chapter, I make references to the VBA code that I've attached to the form
objects in the sample database. You don't need any actual VBA knowledge to benefit from this
chapter beyond the understanding that code can be attached to objects to carry out tasks
when a button is pressed or other events are triggered. I do recommend that you look at these
examples as a first introduction to the use of VBA with Access and start learning the language
as soon as possible. A complete introduction to the language is featured in Chapter IX.

Data Sources
Creating forms from scratch is about two things: learning how to use the different controls that
are available and how to link the data to them. Every form has a Record Source property which
determines where the data comes from. This can be a table, a query or an SQL statement.
Figure 6.1 shows part of the properties sheet for the main leads form from the demo database
with the Record Source holding a SQL statement.

Figure 6.1 - Forms use the Record Source, usually a SQL statement, to view and edit data in the
tables.

The record source of a form specifies where the data comes from. Clicking on the Build button
on the right of the Record Source setting will bring up the query window to show you the query
behind the form. The text for this query is stored completely within the form rather than as a

Page 69

Microsoft Access for Beginners

separate query in the database.


The record source can also hold the name of a table or a separate query that will function as
the data source. If it does, then all of the records returned from that source will be available to
the form. Using a SQL statement as shown in Figure 6.1 or a separate query is one way to
limit the number of records shown. The form works with the record source to determine which
record is currently displayed and to manage the transfer of data between that record and the
controls on the form.
Another word for the collection of records made available to the form is a recordset. This
recordset is sorted according to the specifications of the query or the order in which the
records are held in the table.

Figure 6.2 - The query behind a form can be viewed and edited using the Query By Example
screen.

The controls you place on the form such as text boxes, combo boxes, radio buttons, etc.
access individual fields from the recordset. Each control has a Control Source property which
determines which field it will work with. In Figure 6.3, the properties sheet for the JobTitle text
box from one of the Job Search Plus forms is shown with the Control Source set to the JobTitle
field provided by the record source shown in Figure 6.2.
This control reads from the JobTitle field so that each record on the form displays the value
from the next record in the recordset. Once you understand these two properties, the rest is
about placement of controls and fine-tuning of their properties.

Page 70

Microsoft Access for Beginners

Figure 6.3 - A form control's Control Source determines where the data will come from.

Creating the Form


To create a new, blank form in Access 2003 and earlier, select the Insert option from the from
the main Form menu or select 'New' in the Forms section of the database window. In Access
2007 / 2010, click the Form Design icon from the Create tab on the Access ribbon and then
click on the Add Existing Fields icon on the Design tab.

Figure 6.4 - The new form dialog prior to Access 2007.

In Access 2003 and earlier, the New Form dialog shown in Figure 6.4 lets you select a table or
query to use as the form's recordset source. In Access 2007 / 2010, you can select a table or
query from the database window, select the Create tab on the Access ribbon and click on the
Form icon as shown in Figure 6.5 and a form will be generated for that table or query. In order
to see what you're actually doing in either of these actions, try this:

Page 71

Microsoft Access for Beginners

1. Select Design View from the New Form dialog (in Access 2003 and earlier) or click the
Form Design icon on the Office ribbon in Access 2007 / 2010.
2. Once in design view, display the properties for the form and verify that the Record
Source is defined. If it isn't, select a table or query or create a new query by clicking the
Build button next to the Record Source property.
3. Try selecting the LeadsList query as the Record Source.

Figure 6.5 - The form creation controls in Access 2007

To view the list of fields available, select Field List from the View menu in Access 2003 and
earlier or click the Add Existing Fields icon from the Design tab on the Access 2007 / 2010
Office ribbon. You'll then see the Field List dialog shown in Figure 6.6.
You can click and drag these fields onto the form to automatically add the necessary controls.
You'll notice that the type of control added to the form depends on the fields. Fields with lookup
functions behind them result in combo boxes being added while normal fields create text boxes
or checkboxes. When you switch from Design to Form View, the form automatically loads the
first record from the table it's using as a data source and displays the data from the fields that
have been placed on the form.
At the bottom of the form is the record navigation toolbar which enables you to move through
the available records. As with any list, the recordset has a beginning and an end. On this form,
moving beyond the last record will create a new blank record and the function of the controls
will change. Instead of reading and editing the data, anything typed into the controls will be
written to the new record. Depending on the needs of your application, the form can be set to
simply display read-only data, to disallow the creation of new records or to hide the navigation
bar altogether and only show a single record.
Experimenting with the other form properties available in Design View will also help you
become familiar with the many ways in which you can get the most out of your forms.

Page 72

Microsoft Access for Beginners

Figure 6.6 - Adding controls to the form is as simple as dragging the controls to the form design
grid from the field list.

Figure 6.7 - The Record Navigation bar displayed at the bottom of Access forms.

Types of Forms
Forms can be used in a number of different ways in Access which is why there are different
layouts available. The form shown in the previous section was designed to display a single
record at a time with the navigation bar at the bottom enabling the user to move between
records. This might not be appropriate to your needs, however, and there are other ways to
display your data.
In the form properties, you'll see the Default View setting which, by default, is set to 'Single
Form'. You might decide instead to select the 'Continuous Forms' option which enables the
user to scroll through multiple records using a scroll bar rather than the navigation control. This
might be the choice if you were designing a form around a recordset with only a few fields or
wanted to focus on scanning through large numbers of records rather than one record at a
time. The main Job Leads listing in the sample program is an example of continuous forms. It
provides the user with a way to quickly scan through all the available records and select one to
work with.

Page 73

Microsoft Access for Beginners

Datasheet View is a format that looks like a table view but allows the fields to have form level
controls. The design view for a datasheet form is the same as for single or continuous forms in
that you place fields in the grid and set their properties. When you enter Form View, however,
the form looks like a datasheet.
PivotTable and PivotChart forms enable quick analysis of numeric data such as sales figures
or, in the case of Figure 6.8, my website statistics. Using a PivotTable, you can drop fields
from a table or query into the analysis grid and instantly generate counts, averages and other
summaries. Using the controls on the form, you can view as much or as little detail as you
want for specific elements within the data. In this example, I'm able to see the average number
of requests for specific pages across a given month or quarter and quickly determine the
popularity trends for different content.
The unique thing about the Pivot forms is that they focus on analysis rather than entry of data
and the view that's shown in Figure 6.8 is the actual Form View where fields can be rearranged
within the analysis grid and settings can be adjusted to show the totals needed. Most form
types would limit this type of work to the design view but Pivot forms have a dynamic design.

Figure 6.8 - Pivot tables offer a flexible way to analyze data.

When designing Job Search Plus, I designed most forms to display a single record at a time
and provided a couple of forms such as the main job leads listing that would enable the user to
select a record for viewing. Even the leads listing is designed to pull only a few fields and is
filtered by default. As I mentioned in the last chapter, I did this to minimize the amount of data
being retrieved from the database and to protect the data from accidental edits to the wrong
record.

Page 74

Microsoft Access for Beginners

Working with Properties


As you've seen by now, every object in Access has a list of properties that you can set to
customize your application. The form designer is especially flexible in the ways you can adjust
the look and feel of your program. If the properties screen is not already visible, pressing F4 or
right-clicking anywhere on the form and selecting Properties from the menu will bring up the
list.

Figure 6.9 - The form's property dialog provides a great deal of control over your form's operation
and appearance.

One of the things to keep in mind about form properties is that a form has a number of subsections including the main detail area, a header and footer section. This is in addition to all
the controls you place and a main list of properties that apply to the entire form as a whole.
In Figure 6.9, notice the combo box at the top of the properties sheet. This control contains a
list of all of the form elements including the controls that you create. Here, it's set to the
properties for the form itself. Each element has a different list of property settings available to
it. As you select different controls or sections with this box, you will notice that they are
selected within the form design window as well. This can be an easy way to find a specific
control on an intricate form.
There are far too many properties available to detail here but you can get more information on
any of them by placing the cursor in one of the properties fields and pressing F1 for help. The

Page 75

Microsoft Access for Beginners

more time you spend getting familiar with them, the more you will be able to access the power
behind Access form design.

Form Design Toolbar


One of the standard toolbars that you'll use quite a bit when working with Access is the Form
Design Toolbar, sometimes called the Toolbox. If this bar doesn't appear automatically when
you enter form design mode, you can view it by selecting Toolbars on the View menu. In
Access 2007 / 2010, an equivalent set of tools is available in design mode from the Design
menu on the Access ribbon. This toolbar includes icons for all of the form controls that I
mention in this article plus a few more. It also has a Control Wizards option which is activated
by the magic wand icon. Figure 6.10 shows this toolbar in both Access 2002 where it is
selected on the left end of the toolbar and Access 2007 where it appears on the right side.

Figure 6.10 - The form design toolbars from Access 2002 and 2007

For the beginner, command buttons and other form controls are one of the few exceptions that
I make to what I said about not using the wizards. If you have the Control Wizards activated, a
dialog box will appear as soon as you create a form control and guide you through setting up
the control to perform any one of a limited number of actions. The wizard will write all the code
necessary to carry out the action needed. For small controls such as buttons, it is fine to use
these when first designing forms until you become comfortable designing macros and writing
code. It is still important, however, to learn how to design without them for finer control.

Startup Options
Forms can serve other purposes besides data entry. The Welcome screen (frmSplash) is one
example of this in Job Search Plus. It provides a title screen for the program that includes the
version and copyright information. In the application startup options, you can specify a form to
load as soon as the application starts. In Access 2003 and prior versions, you open this screen
by selecting the Startup option from the Tools menu. In Access 2007, it's opened by clicking on
the Office button and selecting 'Access Options' at the bottom of the menu. Access 2010
features an Options button under the File tab of the Access ribbon. The Startup Options enable
you to define a welcome screen like the Job Search Plus splash screen or run code that is
attached to a form to carry out almost any task at startup.

Page 76

Microsoft Access for Beginners

Figure 6.11 shows images of the startup settings screens for the sample application under
Access 2002 and 2007 / 2010. These settings are unique to the application you're designing.
I've set an application title that will display at the very top of the screen while the application is
loaded. I've also set frmSplash as the form to be displayed at startup. The option directly below
this, Display Database Window, specifies if the window will be shown or hidden. I've set it to be
hidden but you can see it whenever you need to by pressing F11.

Figure 6.11 - The startup options enable you to set such things as the application title and the
form that will open on startup.

Sometimes you might want to override these settings and keep the startup from from loading if
you're making changes to the database. If you hold down the SHIFT key as you're opening the
database, this will bypass all of these properties and give you immediate access to the
database window for the application.

Page 77

Microsoft Access for Beginners

Subforms
When viewing the main job leads listing in Job Search Plus, if you double-click on any of the
leads, the program brings up the Lead Central screen which shows all the data for that lead in
one form. In addition to data from the main Leads table, there's company, contact and activity
information for each lead.
The form itself is based on a single table as you'll see if you open the form in design view and
find the Record Source property in the form's properties listing. It contains a SELECT
statement that pulls exclusively from the Leads table. Previously, I mentioned the importance
of limiting the fields in each table to those directly relevant to the table's subject. Now the
program needs to bring that data back together in a coherent way. This was done to a certain
degree by the LeadsList query which used the link between the Leads and Companies tables
to retrieve company information for each lead. The Lead Central form does it in a different way.
With tables that maintain a one-to-one relationship with Leads, it would be simple to include
them in the record source for Lead Central. Each lead would still generate one record although
it would include the fields from the other tables. The Activities table, however, has a one-tomany relationship with Leads and I needed a way to display the Activities information as a part
of each job lead record on the form.

Figure 6.12 - Subforms enable data from related tables to be brought together in one form.

A subform is a form that can reside within another form. This creates a parent / child type of
relationship just like the tables the forms are based on. In this case, the subform object on
frmLeadCentral holds a subform named subActivities which uses the Activities table as a
record source and is related to the main form by the one-to-many relationship between the
Leads and Activities tables. This relationship is defined when the subform is added to the main
form and is shown in the property sheet in Figure 6.13. You can see the relationship reflected
in the Source Object and Link properties. Because of these settings, whenever you pull up a
lead in the Lead Central form, the Activities subform will show the correct activities for that
lead.

Page 78

Microsoft Access for Beginners

Figure 6.13 - Subforms use the relationship between tables to link the data on the form.

Subforms can be created independently of the main form and then added or created with the
subform / subreport button on the toolbar. In either case, they are saved as separate objects in
the database. Using subforms, you can add, edit and delete multiple records in the related
tables as needed.
There are a few ways to add a subform in Access. The primary method is to select the subform
control from the control toolbox while in form design view and click anywhere on the form to
which it is to be added. If the Control Wizards option is activated, a series of dialog boxes will
guide you through the selection of a subform and setting up the relationship.

Figure 6.14 - The subform wizard makes it easy to create a new subform.

Page 79

Microsoft Access for Beginners

You can also drag a subform from the database window to the main form while in design view
and Access will automatically add it as a subform control. If you do this or if you insert a
subform normally but without the Control Wizards activated, you will need to manually set the
Master and Child Field settings as shown in the property sheet shown in Figure 6.13. Clicking
on the build button next to one of these properties brings up the Subform Field Linker dialog.
This dialog can recommend field relationships based on the recordset in each form.
A unique feature of the subform object on LeadCentral is that it actually uses a number of
subforms to display all of the data available. If you click on the option buttons above the form,
you can switch between the activities data and the company, contacts or related leads. Often a
Tab control would be used to do this but I decided it didn't fit with the appearance I wanted for
the program so I decided to program my own system to change out the subform when the user
clicks on one of these radio buttons. This is all done with VBA code which is not exactly one of
the basics of Microsoft Access but all the code really does is change the Source Object and
Link fields for the subform control on the Lead Central form. As you gain more experience with
Access, it will help you to learn something about VBA as it makes it possible to dynamically
change form settings based on user actions and apply these types of customizations possible.
For more about Visual Basic for Applications, see Chapter IX.

Figure 6.15 - The subform field linking dialog

Additional Controls
The Job Lead Central form has a good sampling of some of the controls you can use to enter
and manage data in Access. Using these very flexible controls, you can build an interface that
provides the features and protections outlined in the introduction to this chapter. You'll
probably want to have the form open in Design View as I go over some of the controls that this
form uses. To view the properties on any control, right-click on it and select the Properties
menu option.

Page 80

Microsoft Access for Beginners

Combo Boxes
A number of fields on the Job Lead Central form are represented by combo boxes which are
the fields with the dropdown arrow on the right side which enable you to choose from a list of
values. When typing values in these boxes, you'll notice that they also attempt to supply
possible values based on what you're typing. This is called the Auto Expand feature. In
addition to speeding up data entry, combo boxes can also help to ensure accuracy by
supplying a set number of choices for the user to enter into the field.
To see the flexibility available through this control, look at the properties for one of the combo
boxes. See Figure 6.16 for an example.

Figure 6.16 - Combo box controls also use queries as data sources.

If you look at the Row Source property for the Location field, you'll notice that it's actually a
query. The control uses a query to pull up a list of the Locations that were previously entered in
the database so that when the user enters a location for a lead, he or she only has to start
typing the location name or press F4 for the pull-down list. Also, you'll notice that the 'Limit to
List' property for this control is set to No. This means that the user can enter new locations that
are not in the database and those locations will be added to the available choices.
The Limit to List property could also be set to Yes if the user was to be limited to a specific list
of choices. An example of this would be the ActivityType field on the Activity subform. All of the
properties in this section affect the way this control accesses and displays information. By
clicking once on a property and pressing F1, you can find additional information on its function
and uses.
The ActivityType field also demonstrates another setting. The values from this field do not
come from a table. Instead, it's a small list of values that are stored within the field setting itself.

Page 81

Microsoft Access for Beginners

The options are entered in the Row Source property as string values (non-numeric values
enclosed in quotes) separated by semi-colons. The pull-down list on the control shows these
values just like the other controls did and the user is limited to using one of the values
supplied.

Figure 6.17 - Value lists can also be used as the data source for combo boxes.

This type of control can be created manually when designing the form and you can adjust the
settings as needed. In the case of these fields, however, the settings were made automatically
as soon as the fields were placed on the form. This is because the lookup functions described
above were actually defined when creating the tables. If you open the Leads table in design
view, you'll see that the Location field is designed to get its information in the same way as its
control on this form. When I placed the control on the form, it inherited the properties of the
table field that it was bound to. This inheritance only happens when the control is created. If
you change the table field properties, the control does not change automatically.

Radio Buttons and Checkboxes


Sometimes, you might want to provide a small list of choices for a user to select from and then
use the result to update a field. The radio button is one control that you can use for this. In the
lower right-hand corner of the Job Lead Central form, you'll see the following control which
enables the user to mark the lead as active or inactive by changing the value in the Active field
of the Leads table.

Figure 6.18 - Radio buttons provide a good interface for Yes or No options.

This is actually a Boolean field which would normally generate a checkbox when placed on a
form but I decided that radio buttons would make the choice clearer for the user so I used them
instead. In this case, the individual buttons return either a -1 or 0 depending on the selection
and that value is used to update the Boolean field.

Page 82

Microsoft Access for Beginners

Radio buttons are contained within an Option Group control which groups the buttons together
to deliver one value to a table field. To create the control, you would create the Option Group
on the form first, set its Control Source property to the necessary field, drop the Radio Buttons
inside the group and set the Option Value property of each Radio Button control to the value
you want the button to return. When the user clicks on one of these buttons, it will return that
value to the Option Group control which will update the field through its Control Source setting.
Again, the Active control shown in figure 6.18 would normally be represented by a checkbox.
When a checkbox is checked, it equals a True value which can be represented by -1. When
unchecked, it equals a False or 0 value. You can also use the Triple State property of the
checkbox to have the control deliver a third value to the field if necessary which could be
shown as 1.

Figure 6.19 - Some controls are more appropriate than others depending on the situation.

I generally favor using a combo box supplied by a value list as shown with the ActivityType
field because it takes up less space on the form. Sometimes, however, an option group can be
the appropriate choice depending on the application. The example in Figure 6.19 shows how
the appearance of an option group compares to the combo box control.

Command Buttons
Command buttons are one of the most useful and versatile tools in form design. The buttons at
the bottom of the Job Lead Central screen enable the user to navigate to different screens and
perform necessary functions. The appearance options for command buttons are much more
flexible in Access 2007 and 2010 than in previous versions.

Figure 6.20 - Command buttons provide a simple way to run commands or navigate between
forms.

A command button provides a familiar device that the user will recognize as a way to start a
task. When the user clicks on the button, it appears to act just like a real button, moving in and
out. What the user is actually doing is activating the macro or section of VBA code that is
attached to one of the button's event properties, usually the 'On Click' or 'On Dbl Click' event.

Page 83

Microsoft Access for Beginners

To see what I'm referring to, choose one of the buttons in design view and find the On Click
event in the button's properties. The words '[Event Procedure]' indicate that VBA code has
been written for that event. Then click on the Build button that appears next to the property.
This will bring up the VBA design environment in a separate window and you can view some of
the code that I've written for these buttons.

Figure 6.21 - Form events are used to run macros or VBA code when a specific action occurs.

The code in Figure 6.21 is an example from the button that returns the user to the main Leads
List form. The first and last lines indicate the beginning and end as well as the name of the
subroutine and its attachment to the command button's click event. The rest represents
instructions to save the record shown in the Job Lead Central form and then close the form if
the record has been successfully saved.
If you place a button control on the form and have the Control Wizards activated, you can use
the wizard to select what action should take place when the user clicks the button. This could
be anything from moving to another record to closing the form to closing Access itself. The
command button wizard will create the button based on your instructions and actually write the
VBA code in the background for you. I'd recommend experimenting with the button control
wizard to get a sense of all the things you can do with this type of control.

Page 84

Microsoft Access for Beginners

Figure 6.22 - The command button wizard provides an easy way to create buttons for a variety of
tasks.

Tab Controls
A tab control features tabbed pages, each with its own set of properties and controls. You can
add and remove pages as needed from the control. In Figure 6.23, you can see how a tab
control from another sample database organizes information on a form.
Controls can be dragged from the form to a tab control which can hold as many tabs as you
need. They are very useful in cases like this one and there are a couple of extra features that
I'll talk about later on.

Form Events
As I mentioned in the section on command buttons, forms and other objects have events that
are triggered by user actions or other events. These include events such as On Current (the
event that runs every time the user moves to a new record) and On Click (run when the user
clicks a button). The events on the form's property list can hold VBA code or macro references
that can be used to change other form properties or perform various actions when a specific
event occurs. A number of events can and often do occur in rapid succession in what would
appear to the user to be only one event. For example, when the demo program's splash
screen closes, this triggers the form's On Close event which contains code that opens the job
leads listing. When this form is opened, the following events occur between the time the
command is issued to open the form and the time you see the form on the screen:

Page 85

Microsoft Access for Beginners

Open >> Load >> Resize >> Activate >> Current


You can see all of these events listed on the form's property sheet where you can get more
information by clicking on any of them and pressing F1. For right now, just understand that
these events are always going on in the background and Access makes them available to give
you precise control over how your application operates. For this reason, Access programming
is referred to as event-driven.

Figure 6.23 - The tab control provides a way to fit more controls on a form without making it
cluttered.

Custom Menus and Tools


If you are using the sample database, you might notice that the tool and menu bars at the top
of the screen look different than normal. This is because in addition to designing forms for the
database, I also designed a custom menu and toolbar as part of the interface. If you right-click
anywhere on these bars in Access 2003 or previous versions, the pop-up menu should contain
a Customize command with which you can pick and choose the buttons and menu options you
want to show to users. This can be very useful both for hiding potentially dangerous options
from inexperienced users and providing custom functions that will automate various tasks in
your application.
Access 2007 and 2010 still have a Quick Access toolbar which is displayed above the Office
ribbon and can be customized to include the controls you need. When using the demonstration
database within Access 2007 / 2010, you'll find the custom menu and tool bar shown under the
Add-Ins tab on the Office ribbon.
Custom utility bars are part of the application and are not dependent on the forms. You can
specify different menu and tool bars for different forms and reports. In this way, you could

Page 86

Microsoft Access for Beginners

design separate custom bars based on the needs and functions of specific sections of your
program. If you import a form from one database file to another, you will see an option to
import whatever custom utility bars are referenced by it. If you don't want to specify a menu bar
on every form you create, you can also name one menu bar as the default in the application
startup options and it will appear throughout the database, even when viewing the database
window.

Figure 6.24 - Custom menu and toolbars are useful for refining your application's interface.

A third type of custom menu is a pop-up menu. This is the menu that appears when you rightclick on a form or another object. Again, this menu can be customized to meet the specific
needs of the application.
The Office 2007 / 2010 ribbon can also be customized to fit your application. In Access 2007,
however, it is a complicated process that involves writing XML code in a hidden table and is
beyond the scope of this book. If you want to tackle it, start with the following link:
http://www.databasedev.co.uk/access2007ribbon.html
Access 2010 simplifies the process by adding a dialog interface which you can access by rightclicking on the ribbon and selecting Customize Ribbon.
My personal use of custom utility bars is mostly limited to removing unneeded or confusing
options but as you work with Access, you might find the ability to customize these menus to be

Page 87

Microsoft Access for Beginners

a powerful part of application design that you wouldn't want to be without. It is one more tool
that you can use to make the application your own.

Tab Order

Figure 6.25 - Tab order determines the order in which controls on the form receive the focus.

One of the properties of your form that determines its behavior is the Tab Order. This one can
be seen in Design View by right-clicking on the form and selecting it from the pop-up menu.
This dialog shows the order in which the focus will move between your form controls when you
press the Tab key. The property sheet for each control contains the Tab Index and Tab Stop
properties which determine if and when a control will receive the focus. In the Tab Order
dialog, you can drag the fields within the list to change their tab order or you can click Auto
Order which will reorder the fields according to the order in which they appear on the form, left
to right and then top to bottom. The Tab Order settings are very important in terms of making
the form's behavior conform to the order in which the user can most easily enter the data.

Storing Pictures and Attachments


Storing photos or other images in Access is a challenge because of the way the program
stores the image information. Access has an OLE Object field type that will store any kind of
file, including other Office documents, Acrobat files and images. For binary files like Word and
Acrobat, this works great. For image files, however, Access stores the image in an
uncompressed format. In other words, an image that takes up less than 50 KB in compressed

Page 88

Microsoft Access for Beginners

JPEG format on disk can take up well over a megabyte when inserted into the Access table.
That's over a megabyte for every picture stored. The database file would get huge.
A common solution in Access 2003 and earlier is to store images on disk instead and store the
path information of the image file in the database. Figure 6.26 shows this solution implemented
in an employee database.
The picture is actually an unbound OLE field and the text field above it is bound to a field in the
table that stores the path information. The Hide Employee Pictures button under the picture
uses VBA code to switch between showing and hiding the photos. The On Current event for
the form fires every time the user pulls up another record and includes code to read the
location from the text field and display the picture in the box so long as the Hide button hasn't
been invoked. The field displays the image without taking up room in the database.

Figure 6.26 - A database can also store pictures, however they do take up a lot of space.

Access 2007 introduces an Attachment field that can store different file types including images
and the database settings can be adjusted to avoid the bloat that would previously occur from
storing images. The field also allows multiple files per record and features a nice interface for
browsing through the stored files which is a huge improvement over the OLE fields. Still,
storing files in your database takes up extra space and if the database is corrupted in any way,
you could lose the photos. Storing them in a dedicated directory that Access can link to is the
better solution when possible.

Working Out the Bugs


It's a rare occasion when anything I'm designing works exactly right the first time. At the very
least, some tweaks are needed here and there to get the right result. Sometimes the process
can be much more involved and can take hours before a form or function works the way I need
it to. During that time, I'll be making changes here and there, consulting technical forums and

Page 89

Microsoft Access for Beginners

help files and almost always learning something I didn't know before. Another rarity is a project
where I don't learn at least two or three new and fun things I can do with Access. Discovery is
half the fun, after all.
The more time you spend testing and debugging a program, the better. Every hour that you
spend testing means at least one less potentially embarrassing problem for the user to
discover. Entering pages of test data and coming up with test scenarios can be tedious and
sometimes Access can seem to have its own obstinate personality when that one function you
know should work doesn't. Debugging is essential, however, if the interfaces you design are
going to meet the user's needs.
Of course, beyond the process of debugging, there's the time that you spend looking for ways
in which to improve the application. One saying that's stuck with me over the years is "That
which is 'good enough' seldom is." Your willingness to look for improvements in your programs
for the benefit of the users, even when you don't believe they're strictly necessary, makes the
difference between designing a barely adequate program that eventually has to be replaced at
great expense by a professional programmer and providing a great solution that is praised by
the people who see and use it.

Conclusion
The introduction of forms and the event-driven interface in this chapter shows a different side
of Access than you saw when setting up tables and queries. Where tables need to be setup
according to the rules of database normalization for the application to work efficiently, forms
and reports allow for much more flexibility and creativity on your part. Your next step should be
to learn as much about form design and event handling as possible so you will have the
foundation to build any application you need to. This knowledge will help you not only with
Access but with other database systems and programming environments.

Page 90

Microsoft Access for Beginners

Chapter VII - Generating the Reports


Introduction
Most database applications of any size involve some kind of reporting system. A well-designed
system compiles and summarizes information in a way that can be easily understood by those
who need to make decisions based on it. Fortunately, one of the strengths of Microsoft Access
is its built-in reporting tool. With Access, you can design a variety of report types, including
charts and graphs, as easily as you would design a form.

From Forms to Reports


Designing reports is very similar to designing forms. Once you're familiar with one, you'll find
many of the same features in the other. The only difference is that, in general, reports are
intended for printing where forms are meant for screen display and user interaction. While
reports use the same controls to display data such as text boxes, labels and subreports, the
data is only intended for presentation and cannot be edited on the report.
Some other similarities:
Reports are based on a query that pulls the data from the tables. The data can be
drawn from multiple related tables.
Once the source of the data is specified, controls are arranged and placed on the report
design grid in the same way as they are on forms.
The report uses the same controls and tools as forms do although some controls such
as combo boxes might appear differently in an environment where the data cannot be
edited.
Reports have a set of properties and events that you can work with to control the
behavior of the report.

Creating a Report
Creating a new report is very much the same as creating a new form; in Access 2007 / 2010,
you can find the report controls under the Create section of the Office ribbon. In Access 2003
and earlier, select the Reports section from the database window and click 'New'.

Page 91

Microsoft Access for Beginners

Figure 7.1 - New reports are created in a similar way to new forms.

As mentioned above, reports share many features with forms. The report has a Record Source
property that determines where the data comes from and each control on the report has a
Control Source that specifies which field in the record source it interacts with. The main
differences are a greater emphasis on header and footer sections and the formatting of pages
for printing rather than display. New reports are automatically divided into three main sections
that can contain data:
Report Header / Footer - This section appears at the beginning and end of a report and
can contain such things as the report title and the date it was run. On a multi-page
report, the header only shows on the first page and the footer on the last.
Page Header / Footer - This section is for information you want on every page such as
page numbers or data headings.
Detail - This section is for the actual report data and would contain all of the rows
generated by the recordset behind the report.
Any of the header and footer sections can be shown or hidden based on your report needs by
right-clicking on the report design and selecting or deselecting the option from the pop-up
menu. You can also add custom header and footer sections to reports based on the way data
is grouped in the record source. An example in the demo database is the Lead Detail report
where the data is grouped on the LeadID value. This value is unique for each job lead so it
provides a value for the report to reference. By adding a header section for this value to the
report, I was able to generate a separate report section for each job lead as needed. I'll show
more of the details on how this is done later in the chapter.

Page 92

Microsoft Access for Beginners

Figure 7.2 - The report design view interface with report and page header / footers visible

Report Margins
While in Design View, you can select the 'Page Setup' tab from the Access 2007 / 2010 Office
ribbon or 'Page Setup' from the File menu in Access 2003 to see the page settings for the
report as it will be printed. The first tab shows the margin settings for the report. Figure 7.4
shows some of the page settings for the Lead Detail report.

Figure 7.3 - Report design view for a finished report

Page 93

Microsoft Access for Beginners

Figure 7.4 - Report page setup options in Access 2007

I have all of the margins on this report set to 0.5 inches to provide plenty of space for the data.
I've used the default settings with letter-sized paper (8.5" x 11") and set the orientation to
Portrait. The Page Setup options also enable you to print from specific trays on your printer or
to use a manual feed for such things as labels and envelopes. Also note that you can specify a
specific printer for the report from the Page Setup control panel in Access. An example would
be if you had a wide report that could only be printed on a wide-carriage printer.
Another useful feature of the design environment is the ruler guide that shows the height and
width of the report page. While a form that is too big for the screen will only require the user to
move a scroll bar, a report that is too big for the paper it's being printed on will print the
overflow on separate pages which will probably not be what you want.

Figure 7.5 - Report designer rulers can help place controls just right.

Figure 7.5 shows part of the design view for the Lead Detail report. Notice that the right edge
of the report is set at 7.5" because the report is set with 0.5" margins on either side and it's
printing on 8.5" paper. Setting it wider would result in a warning message when the report was
opened in preview mode.

Sample Reports
To demonstrate some of the features available on Access reports, I've included the Lead Detail

Page 94

Microsoft Access for Beginners

report in the demonstration database. For the rest of this chapter, I'll offer some details on how
I created it.
The Lead Detail report provides an overall picture of the information stored on each job lead.
The query behind it is much like that of the Job Lead Central form. It contains linked tables to
provide different types of data.

Custom Report Sections


In addition to the normal sections, this report also has a section titled 'LeadID Header'. This
section represents a report grouping based on the LeadID field which uniquely identifies each
job opportunity. To see the group settings, right-click on the group title bar and select 'Sorting
and Grouping' from the pop-up menu. Access 2003 and earlier shows a separate dialog box
while Access 2007 / 2010 displays the settings below the report design area. These controls
are shown in Figure 7.6.

Figure 7.6 - Sorting and grouping options enable a report to be customized as needed. Dialogs
from Access 2002 and 2007.

The settings specify that a header section for this group will be shown but no footer. The report
is grouped on each value which, in this case, means each job opportunity.
Custom headers and footers have their own sets of properties just as the other reports

Page 95

Microsoft Access for Beginners

sections do. If you right click on the LeadID header bar and choose 'Properties', the Properties
sheet will appear.

Figure 7.7 - Report header and footer sections have their own set of properties.

Custom headers can also be created for other types of fields such as date ranges or currency
values.

Automatic Report Fields


At the top of each report page, you can see a header that shows the date the report was
printed. The bottom of each page shows the current page number. Since reports are often
multiple page documents and are meant to be printed for reference and presentation, these
are a couple of page elements that you can automatically insert to enhance the report.

Figure 7.8 - Dynamically generated text can add nice finishing touches to a report.

In Access 2003 and prior, choosing the options from the Insert menu in design view will bring
up dialogs which include the necessary formatting options and this makes it pretty simple to

Page 96

Microsoft Access for Beginners

add these elements. In Access 2007 / 2010, these options are found in the Controls section of
the Design tab on the ribbon. Behind the scenes, the dialogs simply create new text boxes on
the report where the Control Source contains text and codes that Access translates into the
current date and time or the correct page numbers.
Figure 7.9 is the property sheet from the page count on the profile report. Instead of referring
to a table or query field, it uses the equals sign and then concatenates a text string using the
[Page] and [Pages] values of the report which provide the current page and total number of
pages respectively. Knowing this, you could customize the box as needed.

Figure 7.9 - The Control Source property for a report field is useful for generating dynamic text.

The date and time are the same except that Access uses the Date() and Time() functions to
show the correct values.

Figure 7.10 - Functions can be combined with other text to return information on the report.

In this case, Access also uses the Format property to determine how to display the values.
Again, knowing how this textbox is made, you can customize it to your own needs. You could
even enter something like this for the Control Source:
= "Generated on " & Format(Date(),"Long Date") & " at " &
Format(Time(),"Medium Time")

Page 97

Microsoft Access for Beginners

This would show up on the report like this:


"Generated on Sunday, February 03, 2012 at 10:46 AM"
Because I'm concatenating a string with both the date and time and extra words, I have to use
the Format() function instead of relying on the Format property of the text box. The function
accepts the Date() or Time() function as its first parameter and then I use a pre-defined format
style for the second parameter, in this case "Long Date" which includes the weekday and the
full spelling of the date and "Medium Time" which displays the time with the AM/PM indicator.
For more information, search Access help for the Format() function as it applies to Date / Time
formats.

Adding Subreports
The Detail section of the report is where you would put most of the data generated by the
report query. In the detail section of the Lead report, I placed an activity subreport to show the
activities for each lead. Subreports act a lot like subforms. They are based on a table that is
related to a table in the main report query and linked to the main report on the corresponding
fields.

Figure 7.11 - Subreports work much the same as subforms, linking data from related tables.

In this case, the subActivity report uses a simple query on Activities and links to the main
report through the LeadID field. Because the detail section is contained within the LeadID
grouping on the profile report, the subreport limits itself to the records pertaining to the lead
shown on the current page.
The subreport object has a property that you need to be aware of. The 'Can Grow' property
enables the subreport to expand vertically to accommodate extra data. In design view, you'll
notice that the subreport is set to a minimum height but when you run the report for certain job
leads, the content of the subreport takes up more room on the page. With the 'Can Grow'
property set to 'Yes', the Activities subreport will expand as much as needed any other content
below it would move as needed.

Page 98

Microsoft Access for Beginners

Printing Labels
Although it's not used in the demonstration database, there is one more report type that I
wanted to mention as it's an exception to my warnings on using design wizards.
The Label Wizard does a great job of setting up a report to print labels on a range of
predefined label templates including different Avery sizes. Microsoft Word and other software
titles will also do this. The difference here is that you can fill the labels with data from your
current database without having to export it.
To use this wizard in Access 2007 / 2010, select a table or query in the database window that
contains the data you want to use, select the Create tab on the ribbon and select the Labels
icon under the Reports section.
For this report, I'm using Avery 5160 labels to print mailing labels for the companies in the
database. The report could be based on a query that selected the records to include. In this
case, I'm taking it directly from the Companies table. Again, some of the tasks that the wizard
does are ones that you could easily do yourself once you're familiar with report construction.
The wizard shown in Figure 7.12 will lay out the fields from the query on a sample label.

Figure 7.12 - The Label Wizard is a simple way to create a variety of labels from your database.

Page 99

Microsoft Access for Beginners

Figure 7.13 - The Label Wizard includes a wide variety of label sizes.

The main benefit of using the wizard here is that it works with the page setup to set the width
and height of the labels to the exact dimensions defined by the various label makers. This is
something where you would otherwise spend a lot of time on trial and error.

Figure 7.14 - Creating labels is as easy as laying out fields on the label template.

Page 100

Microsoft Access for Beginners

Figure 7.15 - Design view makes it easy to fine tune the label design.

In the design view of the label report, you can see how the fields from the query are setup in
the detail section and the report width is adjusted to the exact size of the label. The header
sections are available but are not used as this report is just printing the labels. There are a
couple of other screens in the Access 2007 / 2010 wizard that allow you to set the font size
and color and choose a field to sort by. This is a good beginning example of how Access
reports can be tailored to more than just straight reporting of data.

Managing the Interface


Users need some way of accessing new reports in the application, either from a button on one
of the forms or from a menu. I try to avoid having users work with the database window as
much as possible. Giving them interface elements to work with provides a smoother, more
professional experience and protects the collection of objects that your application depends
on. How you make a report available in the interface depends on how it will be used.

Figure 7.16 - Command buttons can be used to provide easy access to various parts of the
program.

For convenience, the Lead Detail report is available via command buttons on both the Leads
Search List and Job Lead Central. These two screens enable the user to select which lead the
report will be run for. In the full version of Job Search Plus, it's also available from a program
menu option which brings up a search options screen where the user can select the job leads
to include in the report. If you examine the code behind these buttons, you'll see how VBA can
be used to make the interface more responsive.

Page 101

Microsoft Access for Beginners

Conclusion
I've shown you the basics of reporting in Access but I hope you can see that there are a lot
more possibilities available to explore. Having such a rich built-in design environment is one of
the great strengths of Microsoft Access. Other development tools require you to either use a
separate reporting system or to design your own. I've even seen Access used solely for its
reporting tools by other programs.
Reporting might be the aspect of your application that adds the most value for the users who
will ultimately decide if the application succeeds or fails as a production tool. It can also be the
most demanding part of application design as it requires the most input from the people who
will be relying on the reports and that input can sometimes be detailed and conflicting. The
more familiar you are with the reporting tools and their abilities, the more likely you are to
create a successful application that will impress the users and have them coming back for
more.

Page 102

Microsoft Access for Beginners

Chapter VIII - Automating the Interface with


Macros
Introduction
In earlier chapters, I mentioned that Microsoft Access is an event-driven environment, meaning
that forms and reports can respond to events such as a user clicking on a command button, a
form opening or a control receiving the focus.
Access uses two kinds of programming in order to respond to these events; macros and Visual
Basic for Applications (VBA). In this chapter, I'm going to give you an introduction to the
simpler of the two; macros.

Access 2007 and Earlier


In Access, macros are an easy way to automate many types of operations such as the opening
of forms and reports, record navigation and even the administration of custom menus. Macros
enable you to specify a number of actions that should be taken in sequence and then to assign
these actions to form and report events. In Figure 8.1, you can see a simple macro in Access
2007 that opens the InitialEntry form from the sample database and then maximizes it on the
screen.

Figure 8.1 - The Macro design environment from Access 2007 and earlier

Page 103

Microsoft Access for Beginners

You might notice that the macro designer looks a lot like the table designer. Macros are stored
in groups as separate objects within the database and each macro object can store a single
macro or multiple individual macros. These individual macros can be distinguished by names
in the column at the very left of the designer. Each row in the top part of the designer
represents a separate action within the macro and there's a predefined list of actions that you
can select. In the bottom part of the designer, you'll see the parameters specific to the selected
macro action. For the OpenForm action selected in the first row, these parameters include the
name of the form, a form filter expression and options to determine how the form behaves on
screen. Just like in the table designer, you can switch between these two sections by pressing
F6.
The designer has five columns that can be used to define the macro actions, three of which
can be shown or hidden from view.
Macro Name
This column defines the start of a new macro in the designer dialog. When Access is running
the macro, it will start with that line and continue down the list until another macro name is
specified.

Figure 8.2 - Submacros can be created by adding a name in the Macro Name column.

In Figure 8.2, there are actually two macros defined. If Access is instructed to run the InitEntry
macro, it will start with the OpenForm action and continue with the Maximize action below it.
Once it gets to the MsgBox macro name, it will detect a new macro and stop. Blank lines within
the macro designer will not affect the execution of the macro commands.
Condition
This column can accept any expression that can evaluate to True or False. The condition is
used to determine if the action on that row should be executed. The Expression Builder can be
used by right-clicking in the condition column and selecting Build from the pop-up menu.

Page 104

Microsoft Access for Beginners

Figure 8.3 - The condition column allows for specific actions to be run only when necessary.

In Figure 8.3, a condition is placed on the MsgBox action so that it is only run if that condition
is met. The expression shown counts the number of active leads in the Leads table, or leads
where the Active field does not equal 0. If there are no active leads, the expression is True and
the message box is shown. If there are active leads in the table, the expression is False and
the message box does not display.
Action / Arguments
The Action column specifies what you want that line of the macro to actually do. By using the
dropdown list in this column, you can select from a wide range of actions that include
everything from record and control navigation to the opening of specific forms and reports. If
you select one of these actions, you'll see a description of the action in the bottom right-hand
corner of the macro design screen next to whatever parameters exist for the action. Most of
the time, you probably won't enter information directly in the Arguments column as this column
is automatically completed when you set the parameters for the action in the bottom half of the
design screen.
Comments
You can use this column to enter explanatory comments on your macros. This is a good idea
when you're designing so that when you go back to make changes later, you can know what
you originally had in mind.

Running Macros

Figure 8.4 - The macro control panel from Access 2007 includes buttons to run the macro, show
and hide columns and mange rows.

There are a couple ways to run macros in Microsoft Access depending on how you're using the

Page 105

Microsoft Access for Beginners

macro. Within the macro designer, selecting a row and clicking on the Run button shown in
Figure 8.4 will run that macro. Double-clicking a macro object in the Access database window
or right-clicking on it and selecting Run as shown in Figure 8.5 will run the first named macro in
the macro object. This would be appropriate if you have a single, large macro that you're using
for database maintenance or when testing a new macro. Next to the Run button in Figure 8.4,
you'll notice the Single Step option. When this is activated, the macro will pause after every
action and display a dialog box with the details of the step and any errors. This can be a useful
tool for testing a new macro and finding the source of errors.

Figure 8.5 - Macros can be run either through the macro control panel or by right-clicking and
selecting the Run option.

More commonly, macro names are referenced by the event properties of forms and reports. In
Figure 8.6, you can see the event properties for a command button where the Click event calls
the InitEntry macro in the FormEvents macro object. As soon as you save a macro, it will be
made available in these dropdown boxes. This macro will open the form for entering a new job
lead and selecting it for the On Click event will cause it to open when the button is clicked by
the user.
Notice that the macro object itself is available along with the individually named macros within
it. Again, calling the main macro object will run the first named macro within it. If there are no
named macros within it, the macro commands will run sequentially.
Macros can also be embedded within forms and reports rather than being stored in the macro
groups accessible from the database window. This might make it easier for you to manage
your application as the macro code will be right there within the form or report and accessible
from the event properties. To do this, select the event that will be calling the macro, click the
Build button and select 'Macro Builder' from the choices presented.

Page 106

Microsoft Access for Beginners

Figure 8.6 - Once a macro is saved, it can be selected to respond to events on forms and reports.

Figure 8.7 - Macros can be embedded within forms to simplify editing.

The macro editing screen looks the same as the designer for the standalone macros shown
earlier. After you save the macro, it will be available from the property sheet which will show
the '[Embedded Macro]' notation for the events affected. You can use the Build button on the
event property to edit the macro as needed.

Page 107

Microsoft Access for Beginners

Figure 8.8 - Macros can be embedded within forms and reports instead of being stored as
standalone macro objects.

The Autoexec Macro


In an earlier chapter, I wrote about the Startup option that enables you to specify a form that
will be opened whenever the application starts up. Macros provide an even more flexible way
to set actions at startup. By creating a macro and naming it "autoexec", you can specify a list
of actions that will run as soon as you open the database. Using this method, you could do
anything within the list of actions that macros can take, including running VBA code. The name
autoexec is a holdover from the days of DOS when PCs used a file called autoexec.bat which
would run a group of commands every time the system started.
Sometimes, when opening a database to make design changes or examining an application
someone else has written, you might want to avoid activating the Startup Options or running
the autoexec macro. To do this, simply hold down the SHIFT key while the database opens.
It's important to hold the SHIFT key down until you're certain that the database is finished
opening. In a previous job, I was responsible for documenting a collection of Access databases
that had been created by another developer. Some of these applications had been designed to
run complex routines at startup, some of which made changes to company databases. It didn't
take me long to get firmly in the habit of using the SHIFT key bypass as it's called whenever
opening an Access database unless I was absolutely sure of what was going to be running at
startup.

Access 2010
With the release of Access 2010, some major changes were made to the macro design
interface. Macros can now perform more complex decisions based on conditions within the
program. There were also changes in the look of the macro design environment.
One thing to remember is that for basic needs, macros still work essentially the same. In the
left half of Figure 8.9, you can see the OpenForm action opening frmSplash, the title form of
the database. Instead of laying out the actions in the old interface that was similar to the table
design screen, the settings for the action are shown vertically. Below that action, you can see a
dropdown box that enables the selection of the next action for the macro.

Page 108

Microsoft Access for Beginners

Figure 8.9 - Macro editing environment from Access 2010

The pane on the right of Figure 8.9 is the Action Catalog. This is where you can select from the
list of actions available to the macro. At the top are the Program Flow actions and a couple of
these are similar to functions in the old style macros. The Comment function does just what it
says; it inserts a comment at a point within the macro. Instead of being tied to a specific action,
however, these comments are meant to document the logic of the macro itself.
In Figure 8.10, you can see the comment that's been inserted at the top of the macro. Once
you're finished editing a comment, it changes to the condensed format shown with the start
and end points (/* */) shown. This is actually similar to the commenting style in other, more
advanced, languages. By clicking on the comment, you can re-enter edit mode and make
whatever changes you need to.
Another feature to notice here is on the OpenForm action. Notice the green arrow showing in
the top right corner of the action's edit box. In Access 2010, macro actions can be reordered
just by clicking on this up / down arrow. The X next to the arrow enables you to quickly remove
an action from the macro. Macro actions can also be dragged from one place to another in the
macro.

Page 109

Microsoft Access for Beginners

Figure 8.10 - Access 2010 macros can include comments to describe the flow of the macro.

Going back to the Action Catalog, the submacro command under Program Flow is essentially
the same as the internal macro names described earlier in the chapter. Commands added to a
submacro will only be run if that submacro is specifically called within the program. If you run
the parent macro, such as this autoexec macro, the submacros will not be run.

Figure 8.11 - Grouping in Access 2010 macros promotes organization and easier editing.

The Group action is strictly used for organizing the contents of macros and does not affect the
execution of the macro. In a large macro, you might want to divide it into sections to help when
deciphering it later. Groups can be given helpful names that will make it easier to find specific
submacros and actions. If you notice the minus sign next to the group name in Figure 8.11,

Page 110

Microsoft Access for Beginners

you'll see that they can also expanded and collapsed, allowing you to focus on the necessary
part of the macro. Actions and submacros can also be collapsed or expanded as necessary.
Again, this does not have any affect on the execution of the macro but is there for
convenience.
The most powerful new feature in the Action Catalog is IF. This function enables you to add
conditional statements to the macro which previously were only possible through VBA. The
If ... Then ... Else decision structure allows for multiple conditions, each with a different
response. The full syntax is something like this:
If <condition1> Then
<action1>
ElseIf <condition2> Then
<action2>
ElseIf <condition3> Then
<action3>
Else
<action4>
EndIf

In Figure 8.12, you can see the 'If ... Then' structure applied in decision about which report to
open based on the current date.
The rest of the commands from the Action Catalog are similar to those in previous versions
with, perhaps, a few new ones. The new macro designer does add the convenience of
grouping them by category which might help you find what you're looking for faster. Regardless
of which version you're using, I'd recommend taking some time to experiment with different
actions to get familiar with what you can do with macros in Microsoft Access.

Conclusion
Macros offer a fast and easy way to automate your application and make many tasks more
convenient. Learning how to use them will help you become that much more familiar with what
can be done with Access and you'll probably be surprised by the sophistication of some of the
commands available. Macros are not the end of the road, however. Once you are comfortable
with them, I highly recommend investigating Visual Basic for Applications (VBA) and learning
how you can gain even finer control and perform more advanced tasks within your
applications. As shown in Chapter IX, VBA adds looping functions to perform repetitive tasks
based on conditions or collections of items. It also provides the ability to respond to errors
within your application and log them as necessary.

Page 111

Microsoft Access for Beginners

Figure 8.12 - IF ... THEN ... ELSE statements enable complex decisions within Access 2010
macros.

Page 112

Microsoft Access for Beginners

Chapter IX - Introducing Visual Basic for


Applications
Introduction
Some people might spend years using Microsoft Access and never bother with one of its most
powerful features; Visual Basic for Applications (VBA). Some will learn how to use macros for
simple automation and stop there. It's only when you learn how to use VBA, however, that you
will understand what Access is truly capable of.

What is Visual Basic for Applications?


Visual Basic for Applications is a version of the Visual Basic language that is included with
Microsoft Office. When used with Office programs, VBA enables the user to design simple or
complex routines that will run in the background and respond to events such as the opening of
a form or the click of a command button.
Going back even further, Visual Basic for Applications is a version of the BASIC (Beginner's
All-Purpose Symbolic Instruction Code) programming language. This language is called a
high-level language because its commands and syntax are a few levels removed from the
machine code that the computer actually processes. VBA uses English-like instructions which
are then translated, or compiled, into instructions that the computer can use.

Reasons to learn VBA


There are two levels at which you can use Microsoft Access. The first is for simple database
management where you create some tables to store your data or link to data from other
sources and then create some queries and basic reports to analyze it. Maybe you'll have
some simple data entry forms to make things a little easier. If this is all you want to do, then
you'll probably get by without knowing VBA.
The next level is for building professional database applications. These are programs like the
demonstration program for this book, Job Search Plus, that are centered around the ability to
store important information but also include custom functions and an interface that makes it
easy for anyone to use those functions. Such an interface includes user-friendly forms for

Page 113

Microsoft Access for Beginners

entering data and a menu system to navigate through the available forms and reports. To
create something like this, you will need to be familiar with how VBA can tie your program
together and provide functions that macros just aren't capable of.
Earlier in the book, I stated that I almost never allow users to work directly with the tables
because it's safer for the data and easier for the user to go through data entry forms. When I
design an application, the entire interface and all of its functions from the command buttons to
the navigation and any analysis that the program performs in the background are enabled with
VBA. All the user sees is a smooth running application.
Carrying out the instructions behind command buttons is one of the simplest things to do with
the language. If you use the command button wizard to create buttons on your forms, it will
write the VBA in the background. There are also VBA routines in the application that work
independently of forms to oversee the application as a whole or to determine if a particular
form is loaded. The Job Lead Central screen shown in Figure 9.1 has VBA code behind it that
performs functions on specific job leads on request from the user.
All of these are still relatively simple routines. Some of the most advanced programs I've
written manipulate entire database files and instances of Access itself. I wrote one routine that
would enable an Access application to search for a newer version of itself. On finding the
newer version, the program would shut down, perform the necessary file updates and then
restart itself so the user could continue working.

Figure 9.1 - VBA can be used behind sophisticated user interfaces that make it easier for the
user to use and navigate through the application.

Page 114

Microsoft Access for Beginners

The way Access combines a relational database with a programming environment enables you
to design data-driven applications without being dependent on pre-programmed abilities of the
software. Although Access is included with Microsoft Office, in some ways it's set apart from
the rest of the suite by the user's ability to create solutions that are almost indistinguishable
from normal stand-alone programs. Access also provides a great training tool for both
database and programming concepts.

Event-driven programming
As I mentioned in Chapter VIII, Access programs are referred to as event-driven because the
forms and reports respond to events that are triggered, or fire, in response to actions by the
user or another part of the program. This is true whether you use VBA or simple macros. This
differs from other programming languages, including earlier versions of BASIC, where the code
was all contained in a single listing and was run in sequential order. In VBA, code is stored in
methods and functions which are designed to run when specific events fire, such as when a
form is opened, or when called by other code. This allows for a very flexible program operation
that can respond to the user's needs.

Figure 9.2 - VBA programming is driven by events which are triggered by user or program
actions.

Another feature of event-driven programming is that multiple events may fire in sequence in
response to a single action. On the main menu of the demo program, you'll see command
buttons that activate different parts of the program. If you click on the button to bring up the
Lead Entry form, it seems to open the form with a single action. Behind the scenes, however,
it's firing a number of events:
Open >> Load >> Resize >> Activate >> Current
Each of these events refers to a different aspect of opening the form and displaying its data so
that the user can interact with it. You can program any or all of these events so that the
application will perform the necessary tasks exactly when needed. For example:
The Open event can be canceled so that the form does not open if there is no data to

Page 115

Microsoft Access for Beginners

display.
The Resize event fires any time the size of the form is changed, including when it
opens, and can be programmed to prevent the resizing of the form or dynamically
arrange controls to compensate for resizing.
The Current event fires every time the user views a new record on the form and this can
be useful for adjusting properties of controls based on the data in the current record.

Figure 9.3 - VBA can be used to respond to events with custom actions and functions. This
example shows the code for the event from Figure 9.2.

If you look at the list of events under the form's Properties screen, you'll see quite a few that
relate to actions from the mouse, the keyboard and the form itself. Although it may appear
confusing at first, you'll find that this gives you very precise control over the operation of your
program. An example of this property list and the code it uses is shown in Figures 9.2 and 9.3.
The English-like commands of VBA and the ability to carry out tasks by assigning small
amounts of code to specific events actually makes the language easier to learn. The
integration of VBA with the form and report controls in Access provides you with a graphical
environment where you can focus on how the code works with the flow of your application
rather than just picking your way through a long code listing.
Throughout this chapter, you will see code examples used to illustrate various functions. The
main purpose of these examples is to demonstrate the function being explained and might not

Page 116

Microsoft Access for Beginners

represent the most efficient way to accomplish a given task. While learning to work with Visual
Basic for Applications, I encourage you to explore the functions you find here, in the Access
help files and other places and take plenty of time to experiment with different ways of doing
things.

The VBA Environment


To non-programmers, the Visual Basic for Applications environment can be a little intimidating
at first with its lack of directions and that big open area where the code resides. It's like being
confronted with a blank sheet of paper and being told to just make something up. At first, it
may be hard to see the connection between this and the work you've been doing in Access
until you break it down into its different parts.

Figure 9.4 - The VBA development environment includes a variety of tools for working in the
language.

The VBA environment is referred to as an Integrated Development Environment (IDE) because


it contains all of the tools that you need to write, compile and debug the code in one
place. Other programming systems might require you to edit the code with one program and
then compile it into an EXE file or other executable form with another command line program.

Page 117

Microsoft Access for Beginners

VBA does it all in one place.

Figure 9.5 - You can enter the VBA environment by using the Build button on the right side of the
event listing or by pressing Alt-F11.

There are a couple of ways to open the VBA environment. The simplest way is to press ALTF11 which will bring up VBA from anywhere in Access. If a form event already has code
assigned to it, you can also click on the Build button ( ) next to the event on the form
Properties listing as shown in Figure 9.5. This will go straight to the section of code that deals
with the event.

Project Explorer
In Figure 9.6, you'll see two smaller windows on the left side of the screenshot. One of these
sections is labeled Project - with the name of the VBA project after it. Inside the window, you'll
notice a directory listing which shows the names of some of the database objects. In this case,
it's the project forms, a report and the two modules. The reason these are listed is because
these objects have code associated with them that can be edited in the VBA environment.
Notice that this directory does not contain tables or queries. This is because those objects
cannot have VBA code associated with them. Only forms and reports have events that can be
programmed. Standalone modules, shown underneath the forms in the screenshot, are
independent collections of methods and functions that you can create. The code in these
modules can be called by forms and reports or by other modules. They're like reference
libraries that can hold code that doesn't specifically apply to any of the other objects or that you
want to make available to the entire application.
Also notice that not all of the forms in the database are listed in this directory. That's because
while all forms are able to contain VBA code, not all of them do. Each form and report has a
property that you can set when you view the item in Design View. The 'Has Module' property
determines whether the form has code behind it. For most of the forms and all of the reports in
the demonstration database, this property is set to 'No' as those objects don't require code at
this time and eliminating the modules behind them reduces the size of the database. If the Has
Module property is already set to "Yes", you can set it to No but this will delete any code that
exists in the module.

Page 118

Microsoft Access for Beginners

Figure 9.6 - The Project Explorer section of the VBA environment provides access to all codes
within the project containing code.

Figure 9.7 - The Has Module property determines if an Access form or report has a VBA code
module attached to it.

The code modules behind forms are similar to the standalone modules but they are
inseparable from their forms and supply instructions for the form events rather than general
functions.

Page 119

Microsoft Access for Beginners

As an exercise, try this:


1. Switch back to Access using the ALT-TAB keys and press F11 to bring up the database
window.
2. Select the subContact form and open it in design view.
3. Press F4 to bring up the properties dialog and select the 'All' tab.
4. Way down almost at the bottom of the properties, you'll see the Has Module property.
Double-click where it says 'No' to change it to 'Yes' or just type 'Yes' in the box.
5. Close the report, clicking 'Yes' when you're asked to save it.
6. Now go back to the VBA environment and you'll see that the report has now been added
to the directory because it now has a module that can hold programming for its events.
If you double-click on the object in the directory, it will bring up the blank module in the
code window.

Properties Window

Figure 9.8 - The VBA Properties window enables quick access to the properties of the Access
object for which the code is displayed.

The Properties window shows the properties associated with the object currently being edited.
If you're viewing the module behind a form that is open in design view, you'll see a long list of
properties in this window, much like the properties dialog in Access. If you use Alt-F11 to open
the VBA environment and start editing the code for a form that is not currently open in Access,
Access will automatically open that form in design view and the properties list will become
available in VBA. This list includes the events for the forms and it's a handy way to reference
and change the properties for a form or report while you make changes to the code. As you

Page 120

Microsoft Access for Beginners

learn VBA, you'll find that many of these properties can be set through code as the program is
running (also called run time) as well as at design time. The properties window shows how the
properties are set by default before the code affects them.

Code Window
There are three parts to the code window with the main one being the code editor itself. At the
top of the editor are two dropdown boxes. The dropdown on the left lists all of the controls on
the form or report that can be programmed such as command buttons and text fields. After
selecting one of these objects, the dropdown on the right will list the events that can be
programmed for that object. In Figure 9.9, the Controls dropdown is set to show the events for
the form itself while the Events dropdown is set to the Load event for the form.

Figure 9.9 - The main code area of the VBA interface. The dropdowns at the top provide quick
access to specific objects and events.

As an example, if you're using the demonstration database, bring up the code module for
frmLeadCentral and select cmdAddLead from the controls dropdown. You'll see that the righthand dropdown automatically changes to the Click event since this is the default event for a
command button. If you open the events dropdown, you'll also notice it's the only event shown
in bold since it's the only event with code attached to it. When you selected the cmdClose
button from the controls dropdown, the cursor in the code editor window immediately moved to
the related section of code. This can be a quick way of navigating through a large module.

Page 121

Microsoft Access for Beginners

Additional Windows
Although they're not shown by default and you might not use them right away, there are a few
extra windows that you can show when writing code. These windows are often used while
testing the code or tracking down errors. You can select them for display from the View menu
in VBA.

Figure 9.10 - Additional windows in the VBA interface enable tracking of specific variables and
monitoring of conditions within the code.

Immediate Window - This window is useful for testing formulas and seeing values as
they exist in the code. It can also be used by the program to display custom messages
for the programmer related to activity by the program.
Locals Window - The Locals window shows all the variables that have been declared in
the part of the program that is running and their current values. This gives you a realtime view of the conditions in the program. If you're stepping through the code line by
line, you can see when and how specific values change.
Watches Window - Sometimes when you're testing a program, you want to know when
a specific value changes without having to step through the code one line at a time. This
is when you tell VBA to watch the value and report any changes. This window shows
the watches that have been requested and their current status.
I'll include more details on the VBA environment later on. Meanwhile, you should take some
time to explore the IDE and get comfortable with it. You'll be spending a lot of time there.

Compiling VBA Code


One of the functions of the Visual Basic for Applications IDE is to compile the code. This
means that before the program runs, VBA examines all of the code for certain errors that could
cause it to crash while the program is running and translates the code into a form that is ready
to be executed by the machine. You can run your Access code without compiling it but it will
run slower because every time VBA encounters a new procedure, it has to check it for syntax
problems, compile it then and there and then run it. Weeding out the syntax errors before it
runs also avoids nasty surprises.

Page 122

Microsoft Access for Beginners

Figure 9.11 - To compile your VBA code before running it, you can select the Compile command
from the Debug menu in VBA.

The Compile command is located on the Debug menu in the Visual Basic for Applications IDE.
If the code has not changed since it was last compiled, this option will be grayed out. A change
of one character of code will enable it again. If VBA finds any errors when you try to compile
the code, it will take you directly to the spot that's causing the trouble so that you can fix it.
Remembering to use this one simple menu command whenever you're making changes can
save you a lot of grief later on.

Variables
Now that you know what Visual Basic for Applications (VBA) is and are familiar with the VBA
environment, I want to start introducing you to the elements of the language. One of the basic
elements in VBA is the variable. It serves as a placeholder and identifier for a specific value
that allows the value to be changed when necessary and still retain its meaning and context.

Variables in Real Life


We actually use words in real life that could be considered variables. A good example would
be the word "salary". If you ask one person what their salary is, they are likely to give you a
different answer than if you ask someone else. A person's salary will also vary (hopefully
increasing) from year to year. In this way, the term 'salary' refers to the same thing but a
different value at different times or with different people. The value of the salary (i.e. $45,000)
would have no meaning on its own but when the term "salary" is applied, it starts to make
sense. In this way, the human expression "My salary is $45,000." could be expressed in VBA
like this:
Dim Salary As Currency
Salary = 45000.00

If the person received a raise at the end of the year, it might be expressed like this:
Dim Salary as Currency
Dim Raise as Currency
Salary = $45,000
Raise = Salary * 0.05
Salary = Salary + Raise

Page 123

Microsoft Access for Beginners

In this case, another variable called Raise is declared using the 'Dim' keyword and set to 5% of
the salary (the asterisk is used in VBA to multiply numbers). The resulting value is then added
to the original salary to get the new value.

Using Variables in Code


An example of how VBA uses variables can be seen in this sample.
Public Sub FormOpen(strFormName As String)
'Declare variables
Dim dbsCurrent As CurrentProject
Dim frmCurrent As AccessObject
Dim blnExist As Boolean
blnExist = False
'Reference current project.
Set dbsCurrent = Application.CurrentProject
'Check if requested form exists.
For Each frmCurrent In dbsCurrent.AllForms
If frmCurrent.Name = strFormName Then
blnExist = True
End If
Next
...

This code is a little more complex but demonstrates a few more ideas. It checks to see if a
specific form exists by looping through all the forms in the Access database file and comparing
the name of each one to the value contained in the strFormName variable on the first line.
As you can see in the examples, the Dim keyword is used to declare a variable. This
declaration documents the use of the variable for the code and assigns a specific data type to
the variable (i.e. "as Boolean"). A good practice is to declare all variables at the top of a
procedure in order to keep track of what has been declared. Variables take up memory and
when changing code, it is a good idea to remove variable declarations that are no longer
needed.
At the top of this sample, you can see three variables being declared using the Dim keyword.
The first two, dbsCurrent and frmCurrent, are referred to as object variables because they refer
to objects that have properties and methods, just like forms and reports in Access. The third is
a Boolean variable that refers to a single True or False value.
When a Boolean variable is declared, its initial value is False just as when an Integer is
declared, it initializes to '0'. In the above example, I explicitly set blnExist to False for safety

Page 124

Microsoft Access for Beginners

and clarity. It's also a good habit to have as it's sometimes necessary when looping through
the same operation more than once and reusing variables.
Variables are used in a couple of ways in this sample. The first line of the procedure, also
called its declaration, accepts the strFormName parameter. This is a type of variable that holds
information being passed to the procedure by another section of code. The parameter name
gives the value context within the code, identifying it as "the form name that was passed in".
This particular variable doesn't change within the course of the procedure.
An example of a variable that does change throughout the procedure is frmCurrent. When the
code is iterating through the available forms, it needs a variable to reference the form that it's
working with at any given time. That's where the frmCurrent variable comes in handy. The For
Each ... Next loop uses frmCurrent to hold each form for inspection until it's ready to move to
the next one. Without a variable to hold the form reference, it would be more difficult to run
through a list of objects like this. You'll learn more about For ... Next and other looping
structures later in the chapter.
While frmCurrent is used to hold different items as the code runs, the blnExist variable holds a
single value that might change while the code is running. In this case, it's holding a value
indicating if the specified form has been found. This value remains False unless the specified
form is found and then it becomes True. This indicator will be referenced later in the code to
take further action depending on its value.

Declaring Variables
The Dim keyword (short for "dimension") is used to declare a variable in VBA as a specific
type.
Dim CurrentForm as String

The above variable is declared as a string which holds alphanumeric data such as names, zip
codes and other values that don't need math performed on them. The variable could be
declared without specifying the type which would result in a Variant type that can hold any type
of value. This is to be avoided precisely because anything can be stored in it. Assigning a
specific type to a variable guards against inappropriate values being stored in it which can and
probably will cause errors later when the code references the variable and tries to use it in an
operation.
For example, if you make a mistake as you're writing code and try to store the string value
'Boston' to a variable that is declared as an integer, VBA will catch this and alert you. Not so
with a Variant type because it can store either one. It also makes the code unclear as in the
above example where there's no way to know if the CurrentForm variable is supposed to refer
to a form name or the form object itself.
More than one variable can be declared on a single line in VBA by placing a comma between

Page 125

Microsoft Access for Beginners

the declarations. The Dim keyword does not need to be repeated.


Dim FirstName as String, LastName as String

This example declares two string variables. Again, it's important to specify the type for each
variable or you will end up declaring at least one of them as a Variant.
VBA does not absolutely require you to declare variables. You could just start using a variable
in the code somewhere and VBA would treat it as a Variant. This is very bad programming
practice as it does nothing to track or document the variables being used or define their data
types. The fact that VBA allows it is one of the reasons the language is not regarded very
highly by some professional programmers. VBA can be set to require all variables to be
declared in the option settings or by placing the following statement at the top of a module:
Option Explicit

You'll see some data types in VBA that you'll recognize from table field types in Access but
there are many more available. For more information on the data types that you can use with
variables in VBA, search the Access help files for 'data type'.

Setting Variables
As shown throughout these examples, assigning a value to a variable is as simple as using the
equals operator in a statement.
FirstName = "Andrew"

This works for value type variables such as String, Integer and Boolean variables that hold one
value. The other type of variable is an object variable such as the dbsCurrent variable in the
example above. Object variables contain items such as forms, reports and recordsets that can
have multiple properties of their own. When assigning an object to an object variable, you need
to use the Set command like this:
Set dbsCurrent = Application.CurrentProject

If you don't use the Set keyword with an object variable or you do use it with a non-object,
you'll find out quickly enough when you get errors like these as you try to run the code.
The first error states that an object variable has not been set which means that it does not
equal anything. An object variable that has not been assigned an object is referred to by VBA
as being equal to Nothing. In this case, Nothing is a VBA concept that represents an empty
state of an object variable. The second error results when the Set keyword is used on a value
variable that cannot hold an object and simply states that an object variable is required. Nonobject variables such as integers and strings which simply hold a value are sometimes referred
to as primitive data types.

Page 126

Microsoft Access for Beginners

Figure 9.12 - When assigning values to variables in VBA, be sure to use the Set keyword for
objects variables. Not using it, or using it with non-object variables will result in errors.

In order to avoid memory problems and potential errors, it is important to explicitly destroy
object variables when the code is finished with them, usually at the end of the procedure where
they are used. This is done by setting the object variable to equal Nothing.
Set CustomerForm = Nothing

Naming Variables
There are very few actual rules for naming variables. Variables in VBA must start with an
alphanumeric character (a-z, A-Z or 0-9) and cannot be longer than 255 characters. They also
cannot contain spaces or any of the characters #, !, &, %, $ or @. These are type-declaration
characters that can be used to mark a value as being of a specific data type and are reserved
for use by VBA.
You must also remember to make your variable names unique within their scope. In other
words, you wouldn't give two variables the same name within the same procedure or name a
procedure variable the same as a module-level variable in the same module as the two would
conflict. The main idea is to name it something that will be self-explanatory and not so long that
you're likely to make a mistake when typing it. Variables in VBA are not case-sensitive which
means that newForm, NewForm and NeWfOrM are all the same thing.
There are a couple of naming conventions that you can use as a guide in standardizing your

Page 127

Microsoft Access for Beginners

variable names. Hungarian Notation is an older style of variable naming that attaches a two or
three letter prefix onto the beginning of the variable to indicate the data type, i.e. strName for a
string variable or intAge for an integer. In newer programming technologies, this notation is
discouraged but in VBA, it's still useful. You can find more information on this notation with a
simple online search.
Another type of notation is called CamelCase. In this style, variables with more than one word
have the first letter of each word capitalized. Although VBA is not case-sensitive when it comes
to variables, it will remember the capitalization you use with a variable or procedure name.
Examples of CamelCase would include:
AgeInYears
StreetAddress
LastName

Another practice is to separate multiple words in a variable name with an underscore although
this might be a little tedious when typing a lot of code.
Age_In_Years
Street_Address
Last_Name

Constants
Sometimes when writing code, there is a specific value that you need to use more than once
and you need to ensure that the correct value is used each time. This is when a constant
should be declared. A constant is declared once in code using the Const keyword and then
cannot be changed except by changing the declaration. Some examples might be:
Public Const VALUE_OF_PI As Double = 3.14
Public Const SALES_TAX = As Double = .06
Public Const DRINKING_AGE As Integer = 21

Notice that I've named the constants in all caps and used underscores to separate words. This
is not required but it is one way to distinguish constants referenced in code from ordinary
variables.
Also notice that the constants are all declared as Public. If I were coding these, I would
probably place them in a standalone module named General or something similar and make
them all public. This would mean that they would be available to the entire project. No matter
where I referenced them in the code, VBA would automatically recognize them as the
constants that had been declared and they would supply the correct value.
Using one of the above constants, you could have a function like this:

Page 128

Microsoft Access for Beginners

Public Const SALES_TAX = As Double = .06


Private Function TotalWithTax(Total as Double) As Double
Dim SalesTaxAmount as Double
SalesTaxAmount = Total * SALES_TAX
TotalWithTax = Total + SalesTaxAmount
End Function

In this example, the sale total is passed in and then multiplied by the SALES_TAX constant.
The result is added to the original total to return the result.
In addition to defining standard constants as shown here, constants can be used to supply
custom values such as company names or other values specific to your operation. Another
advantage is that if those values ever do change, you only have to change them in one place
rather than throughout the code.

Variable and Constant Scope


Variables and constants are private by default when declared with the Dim keyword. This
means that the area in which they are recognized by the code is limited to the smallest area
possible. Variables within procedures and functions cannot be public. If you declare a variable
using the Private keyword at the top of a form module, it will not be seen outside that form's
code. If you declare it at the top of a module, it's limited to the procedures within that module.
You can also explicitly make a variable private by declaring it with the Private keyword:
Private TagNumber as String

At module level (at the top of the module, outside of any procedures), you can make a
procedure or constant public by using the Public keyword:
Public MonthlySales as Double

This means that the variable and its value will be available from outside the module and, in this
case, you would need to be careful not to name another variable MonthlySales so as not to
conflict with this one.
Declaring and working with variables is one of the basic aspects of working in VBA and, in a
short time, it will become second nature, especially as you see some of the errors that can be
caused by improperly declaring or setting one or how easy they can accumulate within your
code.

Page 129

Microsoft Access for Beginners

Procedures
VBA code is grouped into procedures that are used to perform one or more tasks or
calculations, either in response to events or when called by other procedures. There are three
types of procedures in VBA, each of which is used for a different purpose.

Subroutines
A subroutine (also called a method) is the most common procedure type. It's a group of
statements intended to perform one or more tasks relating to the program's operation.
Subroutines are used to handle events in Microsoft Access although they can be created
independently of specific events and called as needed. Subroutines are declared with the Sub
keyword.
In code samples like the one below, you'll sometimes see lines preceded by an apostrophe
and usually in green text. These are code comments which are ignored by the compiler and
help to clarify what's being done. Code commenting is a good practice and will be discussed
more later.
Private Sub cmdCredits_Click()
On Error GoTo errHandler
'Open splash screen.
DoCmd.OpenForm "frmSplash", acNormal
Exit Sub
errHandler:
ErrorHandler Err.Number, Err.Description, _
"frmLeadsList.cmdCredits_Click"
End Sub

This example from the demonstration database is a simple procedure used to open a form
when the user clicks on the appropriate command button. On the first line, you can see the
procedure declaration with the Sub keyword and then the name of the procedure. For events,
the name is always the name of the form or report control with an underscore and then the
name of the event (i.e. cmdCredits_Click). In VBA, this is the only way that the system has to
associate a procedure to a specific event.
The last line of the procedure, "End Sub", terminates the procedure's operation. Also notice the
"Exit Sub" command In the middle of the procedure. This is another way of exiting the
procedure. In this case, it's used to leave the procedure before the code reaches a portion that
is only supposed to run if there's an error. It's good practice to have as few exit points as
possible in a procedure and this procedure example is the ideal, with only one exit point other
than the End statement and a clear path through the procedure to the exit. Having too many
exit points makes a procedure difficult to follow when debugging or modifying the code and can
lead to errors that are hard to find.

Page 130

Microsoft Access for Beginners

Going back to the first line, the parentheses at the end of the line indicate where the routine
can accept input parameters for use in calculations. Here's another example from the section
on variables where the name of a form is passed in.
Public Sub FormOpen(strFormName As String)
'Declare variables for use in procedure.
Dim dbsCurrent As CurrentProject
Dim frmCurrent As AccessObject
Dim blnExist As Boolean
blnExist = False
'Reference current project.
Set dbsCurrent = Application.CurrentProject
'Check if requested form exists.
For Each frmCurrent In dbsCurrent.AllForms
If frmCurrent.Name = strFormName Then
blnExist = True
End If
Next
'If form exists, open it. Otherwise, notify
'user.
If blnExist Then
DoCmd.OpenForm strFormName, acNormal
Else
MsgBox "Sorry, that form does not exist.", _
vbOKOnly, "Form not found ..."
End If
End Sub

This procedure is a little longer but still pretty straightforward. It accepts the name of a form as
an input parameter and then matches that parameter against every form in the database in the
For ... Each statement. If it finds a match, it sets the blnExist variable to True. The If .. Then
decision checks the blnExist value. If the variable equals True, the program opens the
requested form. Otherwise, it notifies the user that the form doesn't exist.
You would decide on the name of the input parameter when writing the function and it can be
anything but it should follow the rules for variable names and be something that indicates the
purpose of the value as it will show up as a prompt when you call the function from elsewhere
in the code.
One final note; in some of these code samples, you'll notice lines with and underscore ( _ ) at
the end. In VBA, this is the line continuation character and is used when you want to divide
lines into sections to make the code more readable. When you do this, it's best to indent the
remainder of the line to show that it's part of the same line of code. VBA disregards indents on

Page 131

Microsoft Access for Beginners

code and most other whitespace but they make it easier for humans to read.

Functions
Functions are like subroutines except they are used to calculate and return a value. They can
be placed either in form and report modules (also called class modules) or standalone
modules.
Public Function formLoaded(ByVal strFormName As String) As Integer
'Returns a 0 if form is not open or a -1 if Open
If SysCmd(acSysCmdGetObjectState, acForm, strFormName) <> 0 Then
If Forms(strFormName).CurrentView <> 0 Then
formLoaded = -1
End If
End If
End Function

Although some of the commands in the above example may look complicated, this is actually a
simple function that shows the main features of a function in VBA. The function accepts the
name of a form and determines if it is currently loaded.
The first line declares this as a function rather than a subroutine. It also accepts an
input parameter for use by the function ('ByVal strFormName as String'). In this case, it means
that the function will accept the name of the form in question. Finally, the first line states what
type of value will be returned by the function ('As Integer'). This function is actually used to
return a True / False value (the form is loaded or it isn't) so it could return a Boolean but an
integer of -1 (True) or 0 (False) can be used in place of a Boolean value.
In the body of the function, you can see the decision process that it uses to come to the final
result. The If...Then statements test two different conditions, referencing the form name that
was supplied to the function. If both conditions pass, it returns the result by assigning the result
to the function name itself. Then when calling this function from any other procedure, you
would simply type:
If formLoaded("<InsertFormName>") Then ...

or
If Not formLoaded("<InsertFormName>") Then ...

When a function is used this way in code, the function call represents the value or object it
returns as a result and is treated that way by the code. This is why functions can also be
referenced in Access queries and formulas. In this case, the function name followed by the

Page 132

Microsoft Access for Beginners

form name in parentheses automatically represents either a True or False value to the code.
The Not keyword tests for a False value. It could also be written this way:
If formLoaded("<InsertFormName>") = False Then ...

Using the first method in the case of a True / False value makes for cleaner code.

Properties
The third type of procedure is the Property procedure which is only used in form or report
modules.
The purpose of Property procedures is to create custom properties for forms or reports and to
set and read those values as needed. These property settings can then be used to affect the
program's operation. Properties make use of module-level variables, variables stored at the top
of the module outside of any procedure, to store their values.
Private strReturn As String
Public Property Get ReturnForm() As String
ReturnForm = strReturn
End Property
Public Property Let ReturnForm(vdata As String)
strReturn = vdata
End Property

The example above is from the frmInitialEntry form in the demo database. This form can be
called by more than one form and it's important to know which form did the calling so that the
program can return to it afterward. The ReturnForm property is used to determine this.
In the first line, you see the strReturn variable declared. This is actually done at the top of the
module. This variable is also referred to as a field and is being used by the Return property
below it to store a string value.
After strReturn is declared in the example above, you can see a pair of declarations for the
ReturnForm property. Unlike subroutines and functions, properties can have two declarations;
the Let declaration sets the value of the module field while the Get declaration retrieves it.
Notice that the Let declaration accepts an input parameter for which the type matches the type
of the field and then uses it to set the value of strReturn. When the code sets this property, it
might read as follows:
frmInitialEntry.ReturnForm = frmLeadCentral

There are a couple of reasons for having both a module-level field and a property to set and

Page 133

Microsoft Access for Beginners

read that field. The main reason is to limit access to the field value. You'll remember the Public
and Private keywords in procedure and variable declarations. These keywords affect which
code can access the item and this is referred to as scope. The Private keyword limits access to
the immediate area where the item is declared.
Since strReturn is declared as private in the module header, this means that only procedures
within this module can access the variable's value. If it was declared inside a procedure, then it
would be limited to operations within that procedure. The ShowPicture property is declared as
Public which means that procedures from other forms or modules can access the property.
The property can then act as a gateway to the mblnShowPicture field, controlling conditions
under which the value can be changed. Using the public property and private field
combination, you could also test a value that the property receives before it's actually written to
the field. The public property can also be used to perform additional tasks each time a property
is changed.
Properties don't need to have both declarations. A property that only has a Get declaration is
called read-only, meaning that the property can only be read and not changed from outside the
module. The module in which it's declared can write directly to the private field since the
module is within the scope of that field. Less commonly, you might have a write-only property
that only has a Let statement. It could be written from outside but the module where it's
declared would need to read the private field.
A third type of property declaration is the Set statement. This is the same as the Let statement
in that it accepts a value on behalf of a field. The difference is that the Let statement is used for
value fields (numbers, dates, strings, boolean, etc..) and Set is used for object fields (controls,
forms and other database objects).

Intellisense
One of the features of VBA, along with other programming languages, is that the interface will
detect a call to a function and assist you in entering it properly.
Figure 9.13 shows the formLoaded function from the above example being called from a
subroutine. As soon as I entered the function name and typed the opening parenthesis
(parentheses can be used with all function names, even if there are no variables passed), the
compiler recognized the function name and prompted for the value to be passed in by showing
the function declaration and the current argument needed in bold letters. If there was more
than one argument to be passed in, the values can be entered separated by commas and the
prompt would change as I entered each one. This is a good reason to use self-explanatory
function and argument names when declaring functions.

Page 134

Microsoft Access for Beginners

Figure 9.13 - Intellisense makes coding easier by prompting the programmer with the necessary
options for functions and object properties.

Optional and Default Parameters


In some cases, you might want to include a parameter in a function or subroutine declaration
that has a default value. This means that a specific value will be supplied to the function even if
the parameter is not specified in the call to the function.
Public Function AddTax(Price As Double, Optional taxRate As Double = 0.06)
As Double
AddTax = Price + (Price * taxRate)
End Function

In this example, the first parameter, Price, is required but the second parameter does not need
to be specified. If it isn't, the function will supply a default tax rate of 6%.

Figure 9.14 - Intellisense prompting for a parameter with a default value.

In Figure 9.14, you can see the function being called. The variable TotalSale is supplied for the
first parameter and Intellisense shows that the second parameter has the default value of 0.06
or 6%. This default could be overridden by supplying another value:
TotalWithTax = AddTax(TotalSale, 0.08)

It could also be left as is:

Page 135

Microsoft Access for Beginners

TotalWithTax = AddTax(TotalSale)

There are a couple of rules for optional and default parameters:


1. An optional parameter can be declared without a default value but parameters with
defaults must always use the Optional keyword.
2. If a parameter is declared as optional, all parameters that follow it must be optional as
well. In other words, any optional parameters must be at the end of the declaration.

Parameter Arrays
In the section on variables, I talked about the dangers of using the Variant data type. I stated
that since it will accept any value, it can lead to errors and should be avoided. An exception to
this is the parameter array. Sometimes, you might want to pass a list of items to a function or
procedure but you might not know in advance how many items that list will hold. In that case,
you could use the ParamArray keyword in the procedure declaration. Parameter Arrays are
required by VBA to be of the Variant type.
Public Function AverageItems(ParamArray NumericValues() As Variant)
Dim
Dim
Dim
Dim

varItem As Variant
dblItem As Double
dblTotal As Double
intCount As Integer

dblTotal = 0
intCount = 0
'Iterate through parameter array. Add and count numeric values.
For Each varItem In NumericValues()
If IsNumeric(varItem) Then
dblItem = CDbl(varItem)
dblTotal = dblTotal + dblItem
intCount = intCount + 1
End If
Next
'If numeric values were found, average them for result.
If dblTotal > 0 Then
AverageItems = dblTotal / intCount
Else
AverageItems = 0
End If
End Function

The above example is a function that accepts a parameter array and averages any numeric

Page 136

Microsoft Access for Beginners

values it finds in that array. Notice the use of the ParamArray keyword in the procedure
declaration. If a parameter array is used, it must be the last argument in the declaration to
indicate that it is optional.
In the middle section of the function, you'll notice the For Each loop that iterates through each
item in the array using the varItem variable as a placeholder. I'm using the IsNumeric function
which is native to VBA to verify that each value is a number before using another VBA
function, CDbl, to convert it to a Double value and then adding it to the sum of numeric values.
I also keep a count of the numbers found. In the final section, if any numeric values have been
found, I average them and return the result as the result of the function.
Although I avoid using Variants (or the generic Object type), this is an example of a place
where they would need to be used and the precautions you would need to take when using
them.

MsgBox
One of the internal VBA functions that you'll probably use most is MsgBox() and it's a good
example of how functions can sometimes be used like subroutines and vice-versa.
The MsgBox function displays a message on the screen for the user to see and has five
different arguments to determine its content, title, icon and even its associated help file but at
its simplest, the code looks something like this:
MsgBox "This is a message."

Notice that there are no parentheses around the argument that specifies the content of the
message. When you are calling a method with arguments, you don't actually need the
parentheses unless VBA requires it for a specific method. You can just type the function name,
hit the Space bar and Intellisense will help you fill in the arguments separated by commas. A
longer version might look like this:
MsgBox "This is a message.", vbInformation, "Message "

This one specifies the message, an icon that indicates a purely informational message and a
title for the message box. Still no parentheses and the method just displays the requested
message box.
Sometimes, however, you might want to get input back from the user after you show the
message box and that's when you have to use MsgBox as a function instead of a method
because it actually does return a value whenever the user clicks on the button shown under
the message. When you use MsgBox as a method, that value is tossed away but there's a way
you can retrieve it for your own information.
Dim intResponse As VBMsgBoxResult

Page 137

Microsoft Access for Beginners

intResponse = MsgBox("Are you sure you want to exit Job Search Plus?", _
vbYesNo, "Exit application? ...")
If intResponse = vbYes Then
Application.Quit
End If

In this example, MsgBox is used as a function and the integer it returns is assigned to the
intReponse variable which is actually declared as a VBMsgBoxResult. This is a series of
constant values that correspond to the buttons that might be shown in the message box which
makes the result easier to reference in code. Because of this association, the code can test the
intResponse variable against one of the easy to remember constants below. Because MsgBox
is now being used as a function and is part of an expression, you must enclose the arguments
in parentheses.
vbOK - 1
vbCancel - 2
vbAbort - 3
vbRetry - 4
vbIgnore - 5
vbYes - 6
vbNo - 7

You can find these and other constants by searching the Access help file for information on
MsgBox constants. The constants presented through the MsgBox parameters act a lot like an
enumeration which you'll learn more about in the next section.
When I started programming using an older version of the BASIC language, I learned to write
programs as one long code listing that ran from start to finish. It was quite a different
programming experience from the VBA style of separate procedures and functions. The
advantage of VBA's style is that it encourages you to break the project down into pieces and
analyze each part of the problem. This is an important skill when designing a solution to a reallife problem.

Arrays and Enumerations


Previously, I talked about using variables to store information. Another way to store values in
VBA is the array. A single array can hold multiple values in a way that can be individually
referenced through code. The advantage of using arrays is when you have many values in the
same category, i.e. sales figures or sports scores. Instead of declaring multiple variables, you
can declare a single array variable with enough places to hold all of the information. Functions
can return arrays so a custom function could use an array to return multiple values or even a
set of data from a table.
You declare an array just as you would a variable except that in parentheses after the variable

Page 138

Microsoft Access for Beginners

name, you specify the number of elements to allow.


Dim MonthlySales(11) as Integer

One of the ideas that you'll need to remember in VBA and other types of programming is that
numbered items often start with zero. This is referred to as being zero-based. Arrays are an
example of this; array elements are numbered for reference purposes and by default, the
numbering beginning with zero. Therefore, the above declaration statement actually declares
an array that can hold 12 separate integer values.
If you want the array's lower limit (also called the lower boundary) to start at a number other
than 0, there are two ways to do this.
Use the Option Base statement at the top of the module. This statement can declare the
lower boundary for all arrays in the module as either 0 or 1.
Option Base 1
Option Base 0
To set the lower boundary for a specific array, you can use the declaration itself to set it
to any value. For example:
Dim Months(1 to 12)
Dim Century(1901 to 2000)
Setting or reading information from an array is also the same as working with a standard
variable except that you reference a specific element by number as shown in these examples
which assume the array starts at 1.
MonthlySales(4) = 12000
JanuarySales = MonthlySales(1)

Figure 9.15 shows how Intellisense recognizes MonthlySales as an array variable when the
first parenthesis is typed and requests an element number.

Figure 9.15 - Intellisense recognizing an array variable and prompting for the item index number.

You can use a variable to indicate the element being referenced as in this example which
assumes that the MonthlySales array has already been declared and each element has a

Page 139

Microsoft Access for Beginners

value:
Dim ArrayPlace as Integer
Dim MaxSales as Integer
MaxSales = 0
For ArrayPlace = 1 to 12
If MonthlySales(ArrayPlace) > MaxSales Then
MaxSales = MonthlySales(ArrayPlace)
End If
Next ArrayPlace
MsgBox "The maximum monthly sales is: " & MaxSales & "."

The For ... Next loop in this code uses the ArrayPlace value to cycle through each element in
the MonthlySales array. The code then reads the value of the array element where the element
number matches the value in the ArrayPlace variable. If it's greater than the value in
MaxSales, then the MaxSales value is replaced. At the end, a message box announces the
highest monthly sales.
Using the functions available through VBA, you could also write an expression like this one
with the above array:
CurrentSales = MonthlySales(Month(Date))
The Month() function returns an integer between 1 and 12 representing the month part of the
specified date so the above expression uses this function to fill in the month part of the current
date in a reference to the MonthlySales array.

Multidimensional Arrays
In the examples above, I've shown you how to declare arrays with a single list of values but
sometimes you need the data to go in more than one direction. For this, you need to declare
an array with multiple dimensions. For example, if you wanted an array to hold the monthly
sales for five different sales reps you could do it this way with Option Base 1 stated.
Dim MonthlySalesByRep(5,12)

Although the array is entirely in memory, it may be easiest to think of it in rows and columns.
The above example would therefore be a grid with a row for each of the five sales reps (1 to 5)
and a column for each month (1 to 12). If you wanted the above array to hold five years worth
of data you could add a third dimension like this:
Dim MonthlySalesByRep(5,12,5)

Page 140

Microsoft Access for Beginners

In this case, the third dimension could be seen as a set of pages. So if you were referring to
the sales for the third sales rep in the list during January of the second year represented, the
reference could be:
Sales = MonthlySalesByRep(3,1,2)

The rules for changing the lower boundary on each dimension are the same as with single
dimension. In VBA, you can declare an array with up to 60 dimensions although you'll probably
stick to 2 or 3 most of the time to avoid confusion. If you do need to go beyond three
dimensions, it may help to think of the array references in terms of coordinates rather than a
physical representation of rows and columns.

Resizing Arrays
All of the examples so far have involved fixed arrays where the size is determined when the
array is declared. With this type of array, the declaration requires that a hard number or a
constant be used to specify the number of elements. You may have a situation where you want
to use a variable to specify the number of elements in an array. An example would be if you
read all of the values from a table and wanted an array that would match the number of
records.
To do this, you would declare a dynamic array and use the ReDim keyword to resize it as
needed.
Dim TableValues() as String
Dim RecordCount as Integer
RecordCount = DCount("[Business]", "BusinessTypes")
ReDim TableValues(RecordCount)

The code above declares TableValues() as a dynamic array simply by omitting the number of
elements. It then uses the DCount() VBA function to count the number of records in the
BusinessTypes table and resizes the TableValues array to match that number.
You can use the ReDim statement more than once on an array but be aware that ReDim will
erase all of the information stored in the array unless you use the Preserve keyword with it.
ReDim Preserve TableValues(RecordCount)

If you shrink an array using the Preserve keyword, you will lose the data in the elements that
are removed. You can also resize an array to add or remove dimensions.

Page 141

Microsoft Access for Beginners

Enumerations
Enumerations are groups of constants that you can define within VBA in order to make it
easier to reference a list of values. Enumerations can only be declared at module level (not
within procedures) and use the Enum ... End Enum syntax shown below.
Enum Offices
Boston
Detroit
Toronto
Phoenix
Miami
[Los Angeles]
End Enum

Note that the value for Los Angeles above is enclosed in brackets. This is necessary if there
are any spaces in the enumeration names or VBA will not recognize any of the items from that
item onward. Ideally, it's best not to include spaces in these names and I'll mention more about
that later.
The enumerations themselves are actually treated as custom data types within VBA so to
reference the one above, you would declare a variable as shown in Figure 9.16:

Figure 9.16 - Intellisense also works with enumerations to supply possible values.

As you can see, when you assign a value to the variable you've declared as the enumeration
type, Intellisense kicks in, recognizes the custom type and supplies a list of the possible
values. This is very useful when you're dealing with a list of items that you need to reference
frequently and want to make sure that it's always done correctly.
In the background, the enumeration values are stored as integer values despite being
represented with the strings that you supply. By default, the list starts with 0 and increments by
1 for every value you add but you could supply your own integer values so long as they were
sequential.

Page 142

Microsoft Access for Beginners

Enum Offices
Boston = 100
Detroit = 200
Toronto = 300
Phoenix = 400
Miami = 500
[Los Angeles] = 600
End Enum

In the above example, you can see where the members of the Offices enumeration have been
given custom values. These could represent location codes. In Figure 9.17, the code declares
a variable of the Offices type, sets it to the [Los Angeles] enumeration member and then calls
a message box to display the Integer value of that member which is 600.

Figure 9.17 - Custom integer values can be assigned to enumeration items and returned by using
a function to convert the item to an integer.

Although I've used ordinary names for this example, it's considered good practice to use a
naming convention for enumeration members that makes them recognizable as such. An
example would be something like this:
Enum Offices
eBoston = 100
eDetroit = 200
eToronto = 300
ePhoenix = 400
eMiami = 500
eLosAngeles = 600
End Enum

Remember that when referencing enumeration members, VBA's focus is on the integer value.
The string value is merely used to provide a recognizable reference for each member so the
above names would make it easy enough to work with this enumeration in code.

Page 143

Microsoft Access for Beginners

Enumeration types can be used in procedure arguments just like other data types. In Figure
9.18, you can see a function that is declared with the Offices type as an argument. Then a
subroutine calls this function and Intellisense supplies the list of enumeration members to
complete the function call.

Figure 9.18 - Enumerations can be used as arguments in functions just like any other variable
type.

As a final note, enumerations can contain both positive and negative values.
Enum ConnectStatus
eError = -1
eClosed = 0
eOpen = 1
End Enum

Enumerations are a very useful tool whether you need to reference a list of items as shown
above or supply a short list of possible values for a custom form property as I do in the this
example from another database with the FormModes enumeration.
Public Enum FormModes
eAdd
eEdit
eRead
End Enum
Private menmMode As FormModes
Public Property Let CurrentMode(vdata As FormModes)

Page 144

Microsoft Access for Beginners

menmMode = vdata
End Property
Public Property Get CurrentMode() As FormModes
CurrentMode = menmMode
End Property

In this example, the FormModes enumeration contains only three members and I don't even
worry about their integer values. VBA can take care of that in the background. The
enumeration is used as the type for the Form property that the rest of the code uses to
determine the editing mode of the form.

Operators
Whether you're programming a method or a function, there's an excellent chance you're going
to be using formulas of some kind to get the results you need. In order to construct these
formulas and perform the right calculations, you need to be familiar with the operators
available in Visual Basic for Applications.
The operators in VBA are mostly the same as the ones that you used back in your school math
class (+, -, =, etc..) with a few extra that are specific to the programming environment. Here's a
small example of how operators could be used in VBA. I've numbered the lines here for
reference.
Public Function IsPrime(Candidate As Long) As Boolean
'Determine if the number passed in is a prime number.
'Declare the variables.
1: Dim TestLimit As Long, TestValue As Long
'Assume it is prime until proven otherwise.
2: IsPrime = True
'If the number is higher than 3, test against every integer up to
'the square root of the number.
3: If Candidate > 3 Then
4: TestLimit = Int(Sqr(Candidate))
5: For TestValue = 2 To TestLimit
6:
If Candidate Mod TestValue = 0 Then
7:
IsPrime = False
8:
Exit For
9:
End If
10: Next
13: Else

Page 145

Microsoft Access for Beginners

12: IsPrime = False


13: End If
End Function

As the comments indicate, this function accepts a long integer (a data type capable of holding
numbers between - 2,147,483,648 and 2,147,483,647) and determines if it's a prime number
(a number only divisible by 1 and itself).
The function returns a Boolean value and on Line 2, you can see where the code uses the
assignment operator (=) to set the return value to True. In VBA, like other forms of BASIC, the
equals sign doubles as the operator used to assign a value to a variable and to test for equality
between two values.
On Line 3, the function uses the greater than operator (>) to find out if the number passed in is
greater than 3. Then on Line 6, it uses the Mod (modulus) operator which returns the
remainder when one number is divided into another. In this case, it's looking for a value of 0
indicating that there is no remainder. If the For Next loop is able to cleanly divide the
candidate number by another number, a False result is returned.
The Access help files contain notes on all the different operators available and their behavior
when used with different data types but here is a short listing of those you might use.
Operator
Description
Sign

Example

Arithmetic
+

Addition

Price + Tax = Total

Subtraction

Price - Discount = Total

* (asterisk) Multiplication

Price * .06 = Tax

Division with floating


point result

Hours / 24 = Days

Division with integer


result

Months \ 12 = YearValue

Mod

Division remainder

26 Mod 12 = 2

Exponent

10 ^ 3 = 1000

Page 146

Microsoft Access for Beginners

Comparison
<

Less than

Month < Year

<=

Less than or equal to

364 Days <= Year


365 Days <= Year

>

Greater than

Decade > Year

>=

Greater than or equal to

10 Years >= Decade


20 Years >= Decade

<>

Not equal to

Decade <> Century

Concatenation
&

Combine two string


values

Addition of two numbers Total = Price + Tax

FullName = First & Last

Logical (comparison of conditions)


Value = 14. Therefore:
AND

Both conditions are


True.

EQV

(Year = Day * 7) EQV


Both conditions evaluate (Hour = Minute * 12)
to the same result,
either True or False.
(Both are False so the
operator returns True)

NOT

Condition does not


evaluate to specified
result.

Page 147

Value < 25 AND Value >


10

IF NOT(24 > 100)


(This would evaluate to
True since 24 is not

Microsoft Access for Beginners

greater than 100.)


IF Price > 10 OR Price <
5
OR

Either of two conditions


(The values 11 and 4
is True
would both pass the test
but values 5 through 10
would not.)
IF Year = 2010 XOR
Month = 2

XOR

(Will return False in


One, but not both, of the February 2010 as both
conditions is True.
conditions would be True.
Returns True during the
rest of 2010 or during
February of any other
year.)

Using DoCmd
One of the unique features of VBA is the DoCmd object which you can use to run many
actions such as opening and closing forms and reports, manipulating data and even running
other code or applications.
DoCmd has a collection of methods that act like subroutines you can call to perform the
various actions. Each of these methods has a definition that accepts one or more parameters
to define the action you want to perform. When you call one of the methods, Intellisense will
prompt you to enter the parameters, some of which are limited to a list of specific values.
You can perform many of these methods in VBA in other ways than using DoCmd and, in
some cases as you write more advanced programs, DoCmd might not be the best way to go. It
is, however, a valuable shortcut, especially as you become more familiar with VBA and the
things you can do with the language. Exploring the DoCmd methods is a great way to become
more comfortable working with VBA.
Private Sub cmdCancel_Click()
On Error GoTo errHandler

Page 148

Microsoft Access for Beginners

'Cancel the record entry by clearing the values and close the form.
Me.Undo
DoCmd.Close acForm, Me.Name, acSavePrompt
errHandler:
ErrorHandler Err.Number, Err.Description, _
"frmActivity.cmdCancel_Click"
End Sub

The above example shows a form event that is using DoCmd to carry out a form close action.
The button, cmdCancel, is designed to close the job lead activity entry form of the application
and cancel any entry that's in progress. The Close method of the DoCmd object is called to
close the form. The Close method uses three arguments to:
1. Specify that it's closing a form
2. Specify the form name
3. Require that the program prompt the user to save any design changes that have been
made to the form before closing it.
Often, just like with other functions, the DoCmd methods include optional and default
parameters. In the case of the Close method, the defaults would have enabled this command
to be written in this case as:
DoCmd.Close

This would have assumed that the active window, or the form where the button was being
clicked, was to be closed and that the program should prompt to save any changes. It's also
possible to accept the defaults for some parameters and specify others like so:
DoCmd.Close , , acSaveYes

In this case, the command closes the current window and automatically saves any design
changes without prompting. When accepting the default values in this way, the commas are
only required if you want to specify the value for a parameter later in the declaration statement.
For example:
DoCmd.Close , "Welcome"

The comma acts as a placeholder for the first argument and accepts the default for the object
type being closed. The form name is then specified here but no further placeholders are
needed at the end of the statement even though there are additional parameters that could be
used.
In Figure 9.19, you can see another example of DoCmd being used to open a form in Access.
Note that for a number of the parameters of the OpenForm method, Intellisense supplies a list
of possible values to choose from.

Page 149

Microsoft Access for Beginners

Figure 9.19 - Intellisense supplying possible values for the parameters in a DoCmd statement.

Also notice that after the FormName parameter in the first screenshot, the rest of the
parameters are optional and have default values. The command could be left at:
DoCmd.OpenForm "mnuReference"

This would open the form with the default and most common options. Having the extra options,
however, gives you more control if you need it.

Other Methods
There are a lot of methods available through DoCmd but here are a few that you might use
more often.
Method

Description

Close

Close a object such as a form or


report.

DeleteObject Delete an Access object (table,

Page 150

Microsoft Access for Beginners

query, form, etc.).


Minimize

Minimize a form or report to a tab at


the bottom of the screen.

FindRecord

Search form records for a specific


value.

OpenForm
Opens a form or report in Access.
OpenReport
GoToControl

Moves the focus to a specific


control on the form.

Quit

Close current database and exit


Microsoft Access.

Beep

Play a beep sound through the


speaker.

For a complete list, look up the DoCmd object in the Access help file. You can also get help on
a specific method by positioning the cursor on the command in VBA code and pressing F1.

Decision Structures
Prior to the introduction of advanced macros in Access 2010, one of the advantages of using
VBA rather than macros was the ability to control the order in which actions are performed and
allow the code to make decisions based on the conditions it finds as it runs. This is partially
done through the event-driven programming structure of VBA. Within procedures, it's done
through the use of decision structures.

IF ... THEN ... ELSE


The most basic structure is the If ... Then ... Else statement. This statement controls the
actions of the code depending on one or more conditions. Its basic syntax is:

Page 151

Microsoft Access for Beginners

If <boolean condition> Then


<action>
ElseIf
<action>
Else
<action>
End If

The Else and ElseIf statements are optional but the If ... Then and End If statements are
required. Here's an example of If ... Then in action:
Public Function StrongPassword (Password as String) as Boolean
If Len(Password) > 7 Then
StrongPassword = True
Else
StrongPassword = False
End If
End Sub

The example above tests the length of the password entered, returns True if it's more than
seven characters and False otherwise, thus making it an example of a boolean condition.
Obviously, more than size matters when it comes to password strength but this is a start.
The If .. Then statement can also support multiple conditions:
If Len(Password) > 7 AND IsNumeric(Left(Password, 1)) Then
StrongPassword = True
Else
StrongPassword = False
End If

This is a variation on the password example where the length must be greater than seven
characters and the first character must be a number. In this case, if both conditions are true,
the function will return True. Otherwise it will return False. Aside from the logical AND operator
used above, you could also use one of the other logical operators such as OR or XOR to
govern the decision made by an If ... Then statement.
If I wanted to add a third test for the password, I could write this:
If Len(Password) > 7 AND IsNumeric(Left(Password, 1)) AND NOT
IsNumeric(Password) Then ...

Writing it this way is considered bad practice, though, because it's unwieldy (a.k.a. ugly) code
and causes VBA to do unnecessary calculations. If the first condition fails, the other two still
have to be tested. A better way to write this is to nest the If ... Then statements like so:

Page 152

Microsoft Access for Beginners

If Len(Password) > 7 Then


If IsNumeric(Left(Password, 1)) Then
If Not IsNumeric(Password) Then
StrongPassword = True
End If
End If
End If

The three conditions are now split into three decision statements and nested within each other.
If the password fails the first test, the others don't even execute and StrongPassword is not set
to True unless all three pass.
With nesting, it's still best not to get carried away with too many levels because it can be hard
to read and support later but this does allow for more operations. It's also important not to get
the levels of nesting tangled by accident. Close the most recently opened decision statement
first.
As a final example, If ... Then can also test for multiple results from the same condition.
Public Function DayMessage(TestDate As Date) As String
If Weekday(TestDate) = vbSunday Then
DayMessage = "It's a brand new week!"
ElseIf Weekday(TestDate) = vbMonday Then
DayMessage = "Back to work ..."
ElseIf Weekday(TestDate) = vbFriday Then
DayMessage = "T.G.I.F!!!"
Else
DayMessage = "Have a great day!"
End If
End Function

In this example, the function accepts a date value that's passed in and uses the VBA Weekday
function to determine the day of the week that it represents and provides the appropriate
message. The ElseIf statements tests the date against the VBA weekday constants one at a
time until a match is found. If no match is found, the final Else statement acts as a catchall.
You can find more information on VBA functions like Weekday, Len and others used in these
examples online in the Access help system.

Optimizing Code
When you're writing code, you can often find ways to make the code more efficient, just as you
might find better ways of saying something as you're writing a letter or e-mail. In programming,
this is referred to as "optimizing" the code. After writing this example, I remembered there was

Page 153

Microsoft Access for Beginners

a better way to write it:


Public Function DayMessage(TestDate As Date) As String
Dim DayValue As Integer
DayValue = Weekday(TestDate)
If DayValue = vbSunday Then
DayMessage = "It's a brand new week!"
ElseIf DayValue = vbMonday Then
DayMessage = "Back to work ..."
ElseIf DayValue = vbFriday Then
DayMessage = "T.G.I.F!!!"
Else
DayMessage = "Have a great day!"
End If
End Function

In this variation, notice that the WeekDay function is only called once and the result is
assigned to the Integer variable DayValue. Instead of running the Weekday function over and
over again, the DayValue variable is tested against the weekday constants which, although
they are named, correspond to the numbers 1 through 7. In this case, the change won't make
any noticeable difference but if the Weekday function was a large function that took even a
couple seconds to run or accessed data tables, the time and resource difference could be very
noticeable, especially if the function or method calling it ran repeatedly.
Another advantage would be if the result of the function being called could change from one
moment to the next. In this case, you might want to capture the result at a given moment in
time and then refer to that result instead of calling the function again. This is where
programming goes beyond knowing the commands and syntax and involves design decisions
and an understanding of how the system works. I'll talk about this more in the section on
algorithms.

SELECT CASE
While the above example for the If ... Then statement is acceptable and works perfectly well,
the ElseIf statement isn't always appropriate for testing all the possible values of a given
condition. If there are more than three possible values to test against or you need to carry out
the same action for a range of values, a Select Case statement might be the better choice.
Here's the basic syntax:
Select Case <statement>
Case <value>
<action>
Case <value>

Page 154

Microsoft Access for Beginners

<action>
..
Case Else
<action>
End Select

Here's the previous If ... Then example rewritten in Case statements and expanded with more
options.
Public Function DayMessage(TestDate As Date) As String
Select Case Weekday(TestDate)
Case vbSunday
DayMessage = "It's a brand new week!"
Case vbMonday
DayMessage = "Wake me when Monday's over."
Case vbWednesday
DayMessage = "Halfway there!"
Case vbFriday
DayMessage = "T.G.I.F.!!!!"
Case vbSaturday
DayMessage = "Sleep in today. It's Saturday!!"
Case Else
DayMessage = "Have a great day!"
End Select
End Function

Notice how much cleaner the code looks. It's easier to read and understand. Another
advantage is that it evaluates the expression once at the top of the Case statement rather than
multiple times. This eliminates extra processing and the need for the proxy variable that I
declared in the If...Then statement. There is still a catchall statement at the end where Case
Else handles any result that doesn't match any of the other statements. It's best to get in the
habit of using an Else statement since it's possible to leave conditions unhandled without one
and this can lead to errors, the causes of which aren't immediately obvious.
As with the If...Then statement, only the first matching Case statement is used and the code
then continues after the End Select statement. You can put any number of lines for execution
after each Case statement. You could even have Case statements with no code to execute if
you wanted to take no action for a particular result.
The Case statements also have flexibility in specifying groups or ranges of values. The
following statements are all valid assuming that any variables used have been declared.
Case 100 to 199
Case 5, 10, 15, 20, 25 To 30

Page 155

Microsoft Access for Beginners

Case Is < 21, Is > 45


Case "Red", "Yellow", "Blue"
Case #1/1/2010# To #1/31/2010#

Note the use of the Is keyword with the greater/less than operators and the # around the date
values. The # is a type declaration character which signals to the code that the value should be
treated as a date rather than a division formula. It's used just as the quotation mark is used for
strings.

Program Loops
Sometimes, when writing a procedure, you might want to perform a certain operation
repeatedly, such as if you had a group of records or other objects on which you wanted to
carry out the same tasks or if you wanted to give the user a set number of chances to enter the
correct password. Languages like Visual Basic for Applications include keywords that enable
an operation to run in a loop for a given number of times. In this section, I'll explain two of
these structures in VBA.

FOR ... NEXT


You would use the For Next loop if you knew how many times you wanted an operation to run
or if it could be determined through a formula. In VBA, it uses a counter variable to track which
iteration of the loop is currently running. Here's the basic syntax and an example:
For <Counter> = <Start Value> to <End Value>
<actions>
Next <Counter>
Dim Properties(1 To 10, 1 To 5) as Variant
Dim Counter as Integer
For Counter = 1 to 10
Properties(Counter,1) = Counter
Next Counter

The above example creates a Properties array with 10 rows and 5 columns. It then uses the
For ... Next loop to count from 1 to 10. For each loop, it populates the matching position in the
array's first column with the current value of the Counter variable, effectively numbering the
rows in the array. In this way the Counter variable can be used for other things in addition to
regulating the loop.
It is not absolutely necessary to specify the Counter variable in the Next statement at the end

Page 156

Microsoft Access for Beginners

of the loop but it does make the code easier to read. For ... Next loops can also be nested just
like If ... Then statements and if you were to do this, you would want to specify which loop you
were closing.
The loop can count forwards and backwards as needed, i.e.
For Counter = 10 to 1

As I said earlier, you can also use a variable or formula to specify the start and end values for
the counter variable. The above example also could have been written this way:
For Counter = 1 to UBound(Properties, 1)

This would start at 1 and set the end value to the upper boundary of the Properties array's first
dimension.
For...Next loops can also count forwards and backwards by values other than 1 by using the
Step keyword on the first line:
For Counter = 0 to 500 Step 5
For Year = 2000 to 1900 Step -10

If needed, you can also exit from the loop before the counter reaches its end value as shown in
the following function that accepts a full path reference and returns the file name.
Public Function GetFileName(PathReference As String) As String
'Declare and set variables
Dim PathLength As Integer
Dim Counter As Integer
Dim NameOfFile As String, FileChar As String
NameOfFile = ""
PathLength = Len(PathReference)
'Parse PathReference and return file name at the end.
For Counter = PathLength To 1 Step -1
FileChar = Mid(PathReference, Counter, 1)
If FileChar <> "\" Then
NameOfFile = FileChar & NameOfFile
Else
Exit For
End If
Next Counter
GetFileName = NameOfFile

Page 157

Microsoft Access for Beginners

End Function

This function uses the loop to count its way backward through the PathReference string
passed into the function, using the length of the string in characters as the starting value of the
For loop. It looks at each character and so long as that character is not "\", the function adds
the character to the beginning of the NameOfFile string that it's building. If the character does
equal "\", the code exits the loop. Either way, after the end of the loop, the code returns the
NameOfFile variable as the result.
There are often many ways to do something in VBA and you can often find ways to optimize
the code. As it stands, the code above uses more variables and steps than necessary so let's
try something different.
Dim PathLength As Integer
Dim Counter As Integer
Dim NameOfFile As String
PathLength = Len(PathReference)
For Counter = PathLength To 1 Step -1
If Mid(PathReference, Counter, 1) = "\" Then
NameOfFile = Right(PathReference, (PathLength - Counter))
Exit For
End If
Next Counter
GetFileName = NameOfFile

This change eliminates one of the variables and the string concatenation steps. The Mid()
function which inspects a character at a specified location in the string now uses a positive test
rather than a negative test to check for the "\" character. If it finds it, everything after that point
is treated as the file name by the Right() function and the loop exits. Otherwise, it keeps going.

FOR EACH ... NEXT


The For Each loop is useful when you want to iterate through a collection of objects or an array
without regard to the number. The statement is limited to items that can be treated as a
collection such as forms and array elements and you will probably not use it much until you are
more familiar with the concepts of object-oriented programming. Here's a simple example that
demonstrates the syntax with an array:
Dim BusinessTypes(25) as String
Dim Business as String
For Each Business in BusinessTypes
<statements>
Exit For

Page 158

Microsoft Access for Beginners

<statements>
Next Business

The above is a stripped down example of the statement which is very similar to the For...Next
loop of the previous section. You can also use the Exit For statement to get out of a For Each
statement if a condition is met.
Another use for the For...Each statement is with objects in a collection. The below example
references the controls collection on a form which includes text boxes, command buttons,
check boxes and all the other elements of the form that are used to work with data.
Dim ctrl As Control
Dim btnCommand As CommandButton
For Each ctrl In Me.Controls
If ctrl.ControlType = acCommandButton Then
Set btnCommand = ctrl
btnCommand.Enabled = False
End If
Next ctrl

This example iterates through all the controls on the form, selects those that are command
buttons and disables them one by one. This might be useful if you wanted to lock down a form
under certain conditions.
For another example of the For ... Each loop, refer back to the section on procedures which
includes example code of For ... Each being used to iterate through all the available forms in
an Access application.

Do Loops
While the loops explained in the last section were based on numbered iterations or collections
of items, the Do Loop repeats a section of code based on whether a condition is True or False.
This removes the necessity for declaring counter or object variables but it also introduces a
certain amount of risk. When creating a conditional loop, you must be certain that the condition
you specify in the loop will actually enable the loop to exit at some point. Otherwise, you will
have an endless loop that causes the program to become unresponsive or crash.
There are two types of Do loops; Do While and Do Until. The first would repeat an action while
a certain condition is met and the second until a condition is reached.
To try the following example, type the method and function shown below into a new module in
VBA, position the cursor within the TestPrime method, press CTRL-G to show the Immediate
window (or select Immediate Window from the View menu) and press F5 to run the code.
Public Sub TestPrime()

Page 159

Microsoft Access for Beginners

Dim TestValue as Long


TestValue = 1
'Test every value up to 10000 to
'determine if it's a prime number.
Do While TestValue <= 10000
If IsPrime(TestValue) Then
Debug.Print TestValue
EndIf
TestValue = TestValue + 1
Loop
End Sub
Public Function IsPrime(Candidate As Long) As Boolean
'Determine if the number passed in is a prime number.
Dim TestLimit As Long, TestValue As Long
'Assume it is prime until proven otherwise.
IsPrime = True
'If the number is higher than 3, test against every integer up to
'the square root of the number.
If Candidate > 3 Then
TestLimit = Int(Sqr(Candidate))
For TestValue = 2 To TestLimit
If Candidate Mod TestValue = 0 Then
IsPrime = False
Exit For
End If
Next
Else
IsPrime = False
End If
End Function

After you run the program a couple times, I would recommend that you use this code to get
familiar with the Access help system. Click on a keyword such as Int, Sqr or Mod and press
F1. If the help files are properly installed on your machine, you should see more information on
these functions.
In the TestPrime() method, the code uses a Do While loop in order to test all values up to
10,000 to find prime numbers. If the IsPrime function returns a True result, the code prints the

Page 160

Microsoft Access for Beginners

value in the Immediate window in the VBA environment which is used to display information
while debugging the code. (If you don't see this window, press CTRL-G to show it or select it
from the View menu in VBA.) This window is scrollable so you'll be able to see the entire list of
prime numbers that result.
After the If ... Then statement, the code increments the number to be tested and loops back to
run the code again with the new value. Updating the condition being tested or using one that
changes automatically is also an important part of using Do loops as testing the same
condition over and over again would result in an endless loop and a hung program. To show
the flexibility of the Do loop, the statement in the TestPrime() method could be written multiple
ways:
Do
TestValue = TestValue + 1
Loop While TestValue <= 10000

In this variation, the looping decision is placed at the end of the loop, after the incrementing of
the variable. The decision of whether to test the condition at the beginning or end of the loop
depends on the actions being performed in the loop and how the condition might change
between the Do and the Loop.
Do Until TestValue >= 10000
TestValue = TestValue + 1
Loop
Do
TestValue = TestValue + 1
Loop Until TestValue >= 10000

In the Do Until / Loop Until variations, the code tests the changing condition until it reaches a
certain state. Again, it's important to test for a condition that actually can occur or else you'll
have an endless loop. Where I'm incrementing by 1 in these examples, I'm comfortable that
the value will actually hit the exact value of 10000 but for the sake of form and good habits, I've
changed the formula to greater than or equal to 10000
Public Sub Pause(Seconds as Integer)
Dim CurrentTime As Date
CurrentTime = Now()
Debug.Print CurrentTime
Do Until Now >= DateAdd("s", Seconds, CurrentTime)
DoEvents
Loop
Debug.Print Now()

Page 161

Microsoft Access for Beginners

End Sub

The example above is just what the name implies; a method that pauses the execution of code
for the requested number of seconds. It could be inserted before carrying out an action. It uses
the Now() function from VBA to assign the current date and time to a date variable and then
uses Do Until to loop until the Now function returns a value greater than or equal to the
specified number of seconds after the time that was stored. The method uses Debug.Print to
show the start and end times. The DoEvents command allows any background tasks such as
screen refreshes to complete while this loop is running. Without it, the loop would bog down
your system.
You can also use the Exit Do command to exit a Do loop before it finds the specified condition.
Do Until <condition>
If <condition> Then
Exit Do
End If
Loop

While ... Wend


A simpler form of While loop is While ... Wend which loops until a condition is found. This is an
older syntax that has even more potential for endless loops and is not as flexible as Do loops.
Public Sub Pause(SpecTime as Date)
While Now() < SpecTime
DoEvents
Wend

Error Handling
Sometimes, errors happen in programs and the advantage with VBA is that you have some
very flexible options for responding to them and making sure that they don't disrupt the user's
work any more than they have to. With proper error handling, the program can recover and
move on from an error or at least keep the program from crashing, notify the user in a clear
manner and provide enough information so that you can know what went wrong.
Error handling in any language is divided into catching the errors and determining how to
respond to them. You've already seen the basic syntax for catching an error in VBA in some of
my previous examples and it's simple enough that there's little reason not to use it.

Page 162

Microsoft Access for Beginners

On Error and the Err Object


In an earlier section, I wrote about object variables which store items that can have their own
properties and methods. One of the native objects in VBA is the Err object which stores
information on any errors that occur at runtime. This object enables you to see what happened
and deal with it appropriately.
Private Sub cmdView_Click()
On Error GoTo errHandler
'Open Lead Detail report.
If Not IsNull(Me!LeadID) Then
LeadDetail (Me!LeadID)
End If
Exit Sub
errHandler:
'Ignore report cancellation error.
If Err.Number <> 2501 Then
MsgBox "The program has encountered an error. " _
& "Please contact support. " _
vbCrLf & "frmLeadsList.cmdView_Click" _
& Err.Number & " - " _
& Err.Description, vbExclamation, _
"Error - " & "Error"
End If
End Sub

In the code example above, you can see an example of the Err object being referenced by a
Click event from one of the buttons on the main job lead listing from the Job Search Plus
demonstration database. At the top of the event code, notice the On Error GoTo statement
which directs the method that, in case of error, it should jump to another part of the method.
Halfway down the method, you see 'errHandler:'. The colon marks errHandler as a line label
which you can use to redirect the program flow to a specific place in the method. In this case, it
redirects the label that marks the beginning of the error handling routine.
Incidentally, while Goto is one of the oldest keywords in any version of the BASIC language, in
VBA and other advanced versions of BASIC it has fallen far out of favor because overuse of
the word can result in what's called spaghetti code. This is code where the flow of execution
has been redirected so much that it's error prone and difficult for a programmer to follow and is
therefore hard to support. With the ability to create short methods and functions that respond
to specific events, it's also no longer needed as much. For these reasons, the On Error
statement is one of the only times that you'll see GoTo used by professional programmers.
Note the Exit Sub statement just before the errHandler line label. This command stops the
code execution before it reaches the error handler. This way, the error handler is only run if

Page 163

Microsoft Access for Beginners

there is an actual error and execution is redirected there by the On Error statement. Without
the Exit Sub statement, the code would continue on and cause problems.
The error handler shows two properties of the Err object that you'll use most; Number and
Description. VBA has a collection of numbered errors that can be returned under various
circumstances and knowing which one has occurred can go a long way toward solving the
problem. In Figure 9.20, you can see an example of an unhandled error that occurred when an
object variable was referenced without being assigned an object first. This type of dialog would
end the program's operation and result in an unhappy user.

Figure 9.20 - VBA uses a collection of numbered error descriptions to communicate an error to
the user.

In the following code sample, you can see where these numbers are used to distinguish
between various errors in order to take the correct action.
errHandler:
'Ignore report cancellation error.
If Err.Number <> 2501 Then
MsgBox "The program has encountered an error. " _
Please contact support. " & vbCrLf _
& "frmLeadsList.cmdView_Click" _
& Err.Number & " - " & Err.Description, _
vbExclamation, "Error - " & "Error"
End If

The MsgBox function above might look complicated but it's actually just another VBA function
with parameters that Intellisense will prompt you for. It even returns a numeric value that
corresponds to an enumeration you can use in your code.
In most error handlers, I don't actually test for specific errors but this particular code uses the
IF statement to test for error number 2501 which occurs when a form or report fails to open.
Because there's no ELSE statement here, this code effectively ignores the error. For all other
errors, it generates a message box like the one in Figure 9.21 which gives the programmer a
lot more information to work with and directs them to support.

Page 164

Microsoft Access for Beginners

There are hundreds of possible error codes in VBA and they tend to change somewhat from
one version of Access to the next so if you're looking for the definition of a particular code, it's
best to search MSDN or Google for Access VBA error code and include the number of the
error.

Figure 9.21 - By using an error handling routine, the program can generate an error message that
is a bit more user-friendly and doesn't crash the application.

As I said earlier, trapping the error is only half the battle. The next step is to decide what to do
about it. The example in Figure 9.21 is the result of a programming error that's probably going
to stop the program from doing what the user wants it to until the programmer can fix it so the
notification is about all that can be done. The problem is that if it's just showing up on the
user's screen, you as the programmer might not get to see it before the user clicks it away.
Another option is to save it somewhere. In the Job Search Plus program, I opted for a text file
that would reside in the same directory as the database itself. I could save it to an Access table
but what if the error denies access to the database tables? A text file is the simplest, most
readable solution in this case.
The result is the ErrorHandler subroutine in the mdlFunctions module of the sample database.
This routine is declared as Public so the entire database has access to it. It accepts the error
number, description and the name of the function or subroutine that threw the error.
Dim strError As String
Dim strErrorLog As String
strErrorLog = CurrentProject.Path & "\JobSearchErrorLog.txt"
strError = strError & CStr(errNum)
strError = strError & " - " & errDesc
strError = strError & vbCrLf & vbCrLf
strError = strError & "To report errors"
strError = strError & vbCrLf & vbCrLf
Open strErrorLog For Append As #1
Print #1, CStr(Now) & ": " & errLocation & " threw error " _
& Str(errNum) & " - '" & errDesc & "'"
Close #1

The above code is the heart of the subroutine and it constructs a message that can be written

Page 165

Microsoft Access for Beginners

to the end of the error text file, the Open function opens the text file in Append mode as shown,
prints the message to it and then closes the file. You can find out more about the Open, Print
and Close file functions in the Access help files.
Once the error is written, you have a record of what happened that you can look up in the
same directory as the database. Again, since the procedure is public, it can be called from any
error handling code within the database. Using the previous example, the call would look
something like this:
errHandler:
'Ignore report cancellation error.
If Err.Number <> 2501 Then
ErrorHandler Err.Number, Err.Description, "frmLeadsList.cmdView_Click"
End If

The call can pass the Err object properties directly to the ErrorHandler subroutine along with
the name of the event that's throwing the error. This call can simply be copied to every event
and function where error handling is performed. This effectively creates a central error
handling routine.

Error Handling On the Spot


The approach I've shown above is to have all the error handling at the bottom of the
subroutine. Another method is to use the following line at the top of the procedure instead:
On Error Resume Next

This means that, in case of an error, VBA will continue execution of the code on the line
following the one that resulted in the error. This approach would be most appropriate in code
that is accessing resources outside the program or where you're otherwise reasonably sure of
where an error is likely to occur. One advantage is that it specifically targets the line of code
that poses a risk. An example would be if you were importing an Excel spreadsheet into an
Access table. Since this involves an outside file that is independent of the database, there is
always the chance that the spreadsheet is inaccessible at the time the import is attempted so
it's best to plan for this possibility.
Public Sub OpenExcelSheet()
On Error Resume Next
DoCmd.TransferSpreadsheet acImport, _
acSpreadsheetTypeExcel12, _
"Customers", "C:\Data\Customers.xls", True
If Err.Number > 0 Then
MsgBox "There was an error " _
opening the Excel spreadsheet.", _

Page 166

Microsoft Access for Beginners

vbOKOnly, "Error ..."


Err.Clear
End If
End Sub

In this example, the TransferSpreadsheet function attempts to import an Excel file.


Immediately afterward, the code checks for an error. The Err object's number property is 0 if
there is no error. If it's greater than 0, that means there is an error. The Resume Next
command will prevent the code from crashing and a simple message box is shown. As before,
you could use the properties of the Err object to populate a more detailed message if needed.
Also note the Err.Clear command which clears the last error out of the error object including
the error code and description. After this, you could go on with other operations.
You could actually mix the 'On Error GoTo' and 'Resume Next' approaches in the same
procedure as one will override the other. If you start with the GoTo statement and then get to a
section of code that might cause a specific error you want to check for, you could start the
section with an 'On Error Resume Next', insert the error check as shown above and then
repeat the 'On Error GoTo ' line to re-activate the original error handler. I wouldn't actually
recommend this, however. It's a good idea to write a separate method or function for a
dependency operation that could throw its own error.
The Excel file named in the function above is an example of what's called a dependency.
That's an outside resource such as a data file or a software component that is outside of your
program's control and yet supplies necessary data or functions for your program's operation.
Dependencies are sometimes necessary but they should always be used with caution and you
should assume that they are likely to fail at some point. In order to prepare for this, you start by
deciding whether you really need this outside resource or if there is another way to get the
information or functionality. If you do decide to use them, it's always wise to write in the
appropriate error handling so that when the dependencies do fail, your program is ready to
handle it.
When deciding on how to handle errors in your code, there are two basic things you need to
accomplish; making sure the right people know what error occurred and enabling the program
to recover, if possible, so that the user can at least continue working in another area of the
program. With Access, this might be as simple as doing nothing after displaying and recording
the error since the error hasn't caused the user to leave the form they're on. Having said that,
always try to be aware of how any data the user is working with might be affected by whatever
subroutine to which you're adding error handling. You should also avoid doing anything in the
error handler that might itself cause an error. Notice that the central ErrorHandler method
shown earlier has its own error handler that displays a message box to the user in case it can't
write the original error to the text file.
Finally, don't let error handlers deal with things that you can prevent. It is always better to write
error free code and reserve the error handling for things that you cannot prevent or anticipate.

Page 167

Microsoft Access for Beginners

Algorithms
It's good to know the commands that you can use in Visual Basic for Applications and after
you've worked with the language for awhile, you'll have a decent number of them memorized
to the point where you won't have to rely on Intellisense. Keywords can be looked up in the
help file or online, however, and after the basics that I've mentioned here, you pretty much
learn them as you need them. As with most other things, it's about practice.
The other half of programming is knowing how to approach a problem and break it down into
steps that can be coded with the right commands. That series of steps is called an algorithm.
It's the instructions that a method, a function or a combination of procedures will use in order to
accomplish a task. You could compare it to a home repair project. The keywords and
commands are the tools you will use and the algorithm is the instructions for installing a lock or
replacing a light fixture.
The tricky thing about algorithms is that, as I've mentioned before, there often is no one correct
or obvious set of instructions. Very often, it's up to the programmer to analyze the problem and
find a good way to solve it in code. This applies on a small scale for individual tasks that
involve one or two methods as well as on a large scale for entire projects where the developer
must determine the best way he or she can to store data or translate a company's workflow
into a series of entry forms and reports. This is why I consider programming to be an
engineering discipline. Theoretical projects that you take on to see if something can be done or
just to try out a new function are fun but the real challenges and substance come when have to
apply your wealth of technical knowledge and experience to design a practical solution to meet
someone's needs - often by a deadline.
I'm avoiding referring to 'the best' or 'the most efficient' solution because you probably won't
find such a thing at first or even for awhile after you've been programming. Even after you have
years of experience at this, there's always someone with more experience or a fresh
perspective who can come along and say "Why don't we do it this way?" and when you
honestly look at their solution, you realize they're right. Programmers are also just as likely to
second-guess each other as anybody else and there are as many egos among programmers
as in any other field even though there's just as little room for them.
After you know the basics of VBA syntax; keywords, commands, structures, etc., and
understand some of the best practices such as commenting and error handling, the rest comes
with the patience to approach a problem logically, the willingness to make a few mistakes and
the understanding that things seldom work right the first time.
As for determining the algorithms for your code, it's an individual practice that can't be taught
beyond looking at many examples of what works and what doesn't and lots of practice. In
programming, as in many other fields such as writing, photography and music, it's important to
sample the work of others to see how they do things.
I've shared a number of examples throughout this chapter which I would encourage you to

Page 168

Microsoft Access for Beginners

analyze to see how I did things. Certainly, don't take this as the last word, though. The more
sources you find for programming advice, the more you'll learn. Reading someone else's code
can be an intimidating thing and I know at one time it was the last thing I wanted to do until I
took a job where I had to do it all the time. Eventually I learned to do just what is done when
solving a problem; break it down into pieces and take it a piece at a time.
In an earlier section, I included an example function that parsed the filename from a path
reference supplied to it and I thought this would be a good example with which to show the
basic steps of developing an algorithm.
1. Determine the need.
You have to understand what the need is before you can code for it. Sometimes, that means
getting through layers of distractions and asking a lot of questions in order to help the users
define it. In the filename function, it's simple In Windows and DOS, path references include folders and subfolders as well as the filename.
For this exercise, we only want the filename and need a way to separate it from the rest of the
string.
2. What are the rules?
As a programmer, you will often deal with business rules. These are rules that define how the
business must operate or the structure that the data must follow in order to satisfy the
customer's needs. Issues addressed by business rules include:

How often or how many times product can be ordered by a specific business customer
Under what conditions a discount can be applied
How long data must be retained
What type of notifications must be sent to a customer
What type of payments can be accepted and what data is required for payment

The business rules for a project can affect all aspects of the application, from what tools are
used to design it and the type of security that's applied down to the design of specific methods
and functions.
Determining the filename in the above example is a smaller task so the rules are simple.
1. Everything to the right of the last backslash in the path reference is to be treated as the
filename.
2. The code must make this filename available for use by other code.
Notice there's no mention here of how the code is supposed to do that or how it is to make the

Page 169

Microsoft Access for Beginners

value available. Business rules are supposed to specify what is to be done, not how to do it.
The second rule actually teeters on the edge of this limitation but from the perspective of this
project, I'm allowing it. This is an important issue and the line between those two things can get
fuzzy sometimes but remembering this can save a lot of confusion between the programmer
and the business.
3. Determine the steps.
Now we're getting to the fun part. For different projects, you might ask some of these
questions:
Where is the data coming from and in what format?
Do I need to store or transmit the data? How?
What type of user entry might be needed to satisfy the rules and what type of controls
would work best?
What queries will I need to create to get the information I need?
What tasks can be broken out into their own functions and should those functions be
available to other projects?
These are just a few of the questions you will learn to ask as you work on projects and, when
programming professionally, you could even have the task of writing the answers in the form of
a technical specification for review prior to coding.
In this case, we're just parsing a string so here are the basic rules:
High-level (summary):
Create a function that will accept the path reference as a string parameter, extract the filename
from it and return the filename as a string.
Low-level (algorithm):
Determine the length of the string.
Use the length as the limit in a For ... Next loop with which to examine each character starting
at the end of the string.
When a folder indicator ("\") is found, return the portion of the string after that point as the
filename.
This is actually an extremely low-level algorithm for a single function that you would not
normally see in a technical spec for an application. An application technical spec might simply
say to write a function to parse the filename from the path string if it mentioned it at all. The
level of detail in a technical spec will depend on the preferences of the programming team that

Page 170

Microsoft Access for Beginners

you're on and the nature of the application. More commonly, a spec will talk about things like
how the tables are to be designed and normalized, what standalone queries might be created,
what forms and reports will be designed and what outside dependencies will be referenced.
4. Write the code and test.
Public Function GetFileName(PathReference As String) As String
'Declare and set variables
Dim PathLength As Integer
Dim Counter As Integer
Dim NameOfFile As String, FileChar As String
NameOfFile = ""
PathLength = Len(PathReference)
'Parse PathReference and return file name at the end.
For Counter = PathLength To 1 Step -1
FileChar = Mid(PathReference, Counter, 1)
If FileChar <> "\" Then
NameOfFile = FileChar & NameOfFile
Else
Exit For
End If
Next Counter
GetFileName = NameOfFile
End Function

Even after years of programming, I do not write code from top to bottom. In this example, I
remember starting with the most obvious feature, the For loop and then remembering "Oh
yeah, I'll need a counter variable for that." and going back up a few lines to declare the variable
and while I was there I might have thought to declare an integer variable to hold the path
length. After I'd set down the first draft of the function, I remembered to insert a line setting a
string variable to a blank string for safety before anything else was done to it. Then there were
error corrections, ad hoc changes, etc...
After I finished writing and testing the code and found it to work, I decided to change a few
things to make it more efficient.
Public Function GetFileName(PathReference As String) As String
'Declare and set variables
Dim PathLength As Integer
Dim Counter As Integer
Dim NameOfFile As String

Page 171

Microsoft Access for Beginners

PathLength = Len(PathReference)
'Parse PathReference and return file name at the end.
For Counter = PathLength To 1 Step -1
If Mid(PathReference, Counter, 1) = "\" Then
'Take everything to the right of the character
'as the filename.
NameOfFile = Right(PathReference, (PathLength - Counter))
Exit For
End If
Next Counter
GetFileName = NameOfFile
End Function

You can see more about this function in the section on For ... Next loops. After I wrote the first
draft, tested it and found it to work, I looked at the code and thought "I really made that a lot
harder than it needed to be." and went back to simplify it. There's no shame in admitting that
your code can be optimized further. This goes back to what I said about solutions rarely being
right the first time.
If you'd like an exercise that will demonstrate how many ways there are to do one thing in VBA,
you could redesign this function yourself. There's another way to find the last backslash in the
string using VBAs InStr() function which you can find more information on in the Access help
files. Have fun!
5. Test some more.
Seriously - throw everything you can at your code and try every way you can imagine to break
it. I know it's tedious and it looks like it works so why tempt fate, right? Trust me; finding a bug
in your code and fixing it before it goes to the customer is a lot less embarrassing than letting
the customer find the bug. VBA also offers some good tools for testing code so there's really
no good reason not to do it.
There have also been times when I've spent hours, or even a day or three, trying to find the
right approach to a problem. Sometimes, it happens because you don't understand something
as well as you think you do or because you've gotten so wrapped up in the problem that you
can't see straight anymore and need to walk away from it for a bit. Sometimes, showing it to
another programmer and asking for advice helps because programming, like other fields where
knowledge is the main tool, is best when done through collaboration with others.

Page 172

Microsoft Access for Beginners

Appendix I - "Where do I go from here?"


I wouldn't have been inspired to write the series this book was based on if I hadn't talked to
people who were just starting out with Microsoft Access and wanting to learn more. Since
writing it, I've received many e-mails from beginners who have discovered just how useful
Access can be. Some want to become experts and design professional applications that will
help them to earn a bit more acknowledgment and respect at work. Maybe they just want to
program for the fun of it or make their own work a little easier.
Whatever benefit you get from your database work, it's important to realize that the ability to
design normalized tables and a user-friendly interface is only the beginning of application
design and programming. Microsoft Access, despite being the leader in desktop database
software and a great training tool, is only one of many applications that you need to be familiar
with if you truly want to become a database administrator or programmer of one type or
another. There are people who assume these titles when they only know Access but they're at
a loss when the serious problems arise that require a perspective that only experience can
bring.
So I decided to add a few notes here on some of the things you need to learn if you really want
to become an expert with Access and perhaps move beyond it to other technologies.
Pay special attention to concepts that work with systems other than Access such as
database normalization and data security. While Access is only a starting point, it does
serve as a great introduction to database concepts in general and you can transfer a lot
of the knowledge you gain from it to other software.
Learn to work with Visual Basic for Applications (VBA) as soon as you can. Once you
have a solid grasp on VBA, it can be a gateway to more advanced environments like the
.NET languages and web design.
Learn how to write SQL code so you're not dependent on the query builder in Access.
There are also types of queries such as UNION queries that must be written manually.
This is related to the advice I give elsewhere against using wizards. The query builder is
helpful but you won't truly understand queries until you know how to write them yourself.
SQL is another technology that is used by many other systems besides Microsoft
Access. Understanding it will give you a foothold when you want to move on to other
systems.
After you become an expert with Access, look into more advanced databases like
Microsoft SQL Server. This is Microsoft's network database system that offers tighter
security and better handling of large database systems. You can download a free
version of the product from Microsoft along with free versions of VB.NET and other
programming tools.

Page 173

Microsoft Access for Beginners

Remember that no matter how much you know, there is always more to learn. The
technology is always changing and if you want to stay current, you have to keep up with
it. If you want to provide the best solutions to your employer, your clients or whatever
problems you encounter yourself, you need to have a wide base of knowledge in order
to make the best recommendations. There is no one tool that is appropriate in every
situation.
Remember that there will always be people who know more than you. Seek these
people out and learn from them whether it's through participation in Internet forums,
local user groups or even a team project that stretches your abilities. Being the most
computer-literate person in the office can be fun but it can also lead to complacency. As
long as you're willing to learn, you never have to be afraid to admit what you don't know.
In their book, The Pragmatic Programmer, Andrew Hunt and David Thomas use the
investment portfolio as a metaphor for a person's collection of knowledge and
experience. The development of your 'knowledge portfolio' is essential to your success
as a programmer or DBA. Adding to your portfolio often requires little more than an
investment of your time. The state of your portfolio will affect such things as your salary,
the respect your get at work and even where you are able to live.
In your spare time, don't forget to learn what you can about networking and hardware.
It's another part of the perspective that you need to be a true expert.
A final piece of advice: every day that you put off learning increases the chance that the
knowledge won't be there when you need it. That time might come when you have to admit to
not knowing something that you realize you should have learned a year ago or when you don't
meet the requirements for that great job you really want and you know you could have if you'd
been more attentive. This is a lesson I've learned the hard way more than once.
Once you get a good perspective on database operations and administration and have a
decent knowledge of programming concepts, you'll have a foundation for building a rewarding
I.T. career.
Have fun learning!

For more information:


Getting Started in Software Development - AndrewComeau.com
http://www.andrewcomeau.com/Indexes/getting-started-software-development.aspx
A series of articles with technical and professional advice for pursuing a career in computer
programming or software development.

Page 174

Microsoft Access for Beginners

Appendix II - Using Lookup Fields


Microsoft Access uses lookup fields to provide a selection of possible values for data entry.
This selection can be obtained from another table or from a list of values manually entered into
the field settings. Depending on the type of data, the field can be limited to that selection of
values or it can learn from the values that the user enters and build the list as new data is
entered. This not only speeds up data entry but helps reduce errors and is part of a userfriendly interface.
A good example from the sample database is the CompanyID field in the Leads table. The
table stores a number for the company which references one of the records in the Companies
table. As shown in Figures A2.1 and A2.2, the Leads table uses a lookup field to display the
actual company name from the Companies table although it only stores the ID number.

Figure A2.1 - Lookup fields are used to pull values from another source.

Without the lookup, the numeric CompanyID value would appear like it does in Figure A2.1
which is less than intuitive when viewing the data. Because of the lookup function added to the
CompanyID field for this example, the table displays the appropriate title even though only its
number is stored.

Page 175

Microsoft Access for Beginners

Figure A2.2 - One benefit of lookup fields that a full name can be displayed in the field while only
storing an ID number.

The settings for lookup fields are found in the Lookup tab under the individual field settings of
the table design screen. These settings allow for a lot of flexibility in the way the data is
displayed in the table view. These lookup settings are also inherited by form fields created
from the table field.

Figure A2.3 - The lookup settings for a combo box

Display Control
The Display Control setting for a lookup field has three options; Text Box, Combo Box and List
Box. Setting it to Text Box removes any lookup function from the field. In a table view, there
isn't much difference between a combo and list box. On a form, however, the combo box
provides a drop down list which takes up less room than a list box as shown in the comparison
from Figure A2.4.

Page 176

Microsoft Access for Beginners

Figure A2.4 - Depending on the number of lookup values, either a combo box or list view might
be appropriate.

Row Source Type


The Row Source Type setting determines what type of lookup will be performed.
A Table / Query lookup is exactly that, with the data coming from either a table or query in the
database or an SQL query added to the control itself. This is a good option for the example
shown above where the data is coming from the Companies table. A field can also reference
itself when doing a lookup. This might be done if you have a field where you want the lookup to
remember values that the user has already entered. Every time a new value is entered into the
table, it's added to the lookup because the field is looking up its own values.
A Value List lookup is appropriate when there are only a few items that you want the lookup to
present and it's not likely that the list will change. The ActivityType field in Activities is a good
example of this. There is a small number of activity descriptions that can be used. Presenting
them in a lookup simplifies data entry and ensures that the descriptions are entered the same
way every time without misspellings.
The Field List lookup is a way in which you can list the field names from a specific table in the
lookup. This might be used in constructing advanced search forms.

Row Source
This setting specifies the actual source of the lookup data by referencing a table or query,
creating a new query or manually entering values. The CompanyID field in the Leads table has
a very simple query behind it that pulls the CompanyID, Company Name and Location from the
Companies table. The link between the tables does the rest and the company name and
location is shown in the lookup.
A value list is used in the ActivityType field from the Activities table. The values are entered
manually with a semi-colon between each one in the Row Source setting and this allows
Access to recognize the separate values.

Page 177

Microsoft Access for Beginners

A Field List lookup will accept the name of any table or query in the database.

Bound Column / Column Count


As you can see by the Company lookup, the Row Source can have more than one column so
it's necessary to specify which of the columns supplies the value that's actually saved to the
field performing the lookup. In this case, it's the first column since it's the Company ID that's
being saved. The company name is only displayed and the location is only shown in the drop
down to help the user select a company if there's more than one company with the same
name.
The Column Count setting enables Access to correctly read the Row Source and is especially
important when using a Value List lookup. Remember that in this lookup, you supply the values
manually, placing semi-colons between them. Since there's nothing in the value list to indicate
columns, specifying the column count tells Access how many columns of data this actually
represents. For example, if you had a field named Location and needed to show company
locations and IDs in the dropdown, you would enter something like this under Row Source:
"100";"Seattle";"200";"Denver";"300";"Boston";"400";"Chicago"

You would want this in two columns so entering 2 under the column count tells the database to
show two columns, using the available values to fill in the columns from left to right and adding
rows as needed. You would then see something like the list in Figure A2.5.

Figure A2.5 - A lookup field can accommodate more than one column of information.

Depending on which column you chose as the bound column, the table would then save either
the location ID on the left (Column 1) or the city name on the right (Column 2) when a user
chose a value from the lookup.

Column Heads
This option specifies if a header row should be shown in the lookup. Depending on the source
type you specify, this could be field names or, in the example in Figure A2.6, the first row of the
Value List would be used as headers. In this case, you would want the Row Source to read
something like the example in Figure A2.6.
"Location ID";"City";"100";"Seattle";"200";"Denver";"300";"Boston";"400";"Chicago"

Page 178

Microsoft Access for Beginners

Figure A2.6 - Column headers in the lookup field clarify the display.

By specifying that the list contains column headers and setting the column count to 2, Access
reads the list and uses the first two values as the column headers and distributes the rest of
the values between the two columns.

Column Widths / List Width / List Rows


The width of the columns in the drop down or list box and the total width of the list itself can be
changed with these settings to accommodate headers and content. The Location ID column
shown in Figure A2.6 is set at 0.75".
The List Rows setting specifies the number of rows that will be displayed in the drop-down list
when it is expanded. This can be useful in adjusting the amount of space taken up by the
lookup on a form or in a table view.

Limit to List
This setting determines if the user can enter new values or is limited to the choices offered by
the lookup. In the example above, you probably would not want the user adding new locations
and you would want to make sure the available locations were entered correctly for reporting
purposes so you would probably set this to No. On the other hand, if you're entering a large
number of addresses, you might put a lookup on the City field and allow the user to enter new
cities as needed. This way, the user would be presented with a list of cities already used which
would speed up data entry and cut down on error but would still be able to add new ones as
needed.

Form Lookups
Combo and list boxes can be added to forms independently of the tables although if they are
added to the table when it is designed, form fields based on the table fields will inherit the
lookup settings and this saves time when designing. Still, if you decide when designing the
form that a combo box is just what you need, the designer makes it easy to change between a
text box and combo box just by right-clicking on the control and selecting Change To from the
menu. In some cases, on a read-only form, you might want to have a text box rather than a
lookup field that would imply that the field could be changed. The properties that the form
combo and list boxes use are also identical to the ones described here.

Page 179

Microsoft Access for Beginners

Appendix III - Glossary


Aggregate - A group of totaling functions within Access queries including COUNT, SUM and
AVG that enable the user to analyze chunks of data.
Algorithm - The series of steps that a computer program uses in order to accomplish a given
task. These steps are determined before writing the actual code. They can be expressed as a
set of directions, sometimes in the code comments, for accomplishing the task and are
decided upon before coding begins.
Alias - In a Microsoft Access query, a short name or abbreviation applied to a table name that
makes the query language easier to read.
Alphanumeric - Data that can contain both letters and numeric digits such as license
numbers, names, and serial numbers. The term is often used to distinguish these types of
values from numeric values such as sales figures on which math operations might be
performed.
Application - In Microsoft Access, a database designed to provide a specific solution which
includes a combination of objects such as queries, forms, reports and functions.
Array - In Visual Basic for Applications, a variable that is able to hold multiple values so that
they can be individually referenced as needed. The array is declared with one or more
dimensions of various sizes as needed.
Atomicity - The conditions under which data has been broken down into separate values to
the point where it cannot be broken down any further and still remain useful. This is done for
the purpose of optimizing the design of tables within a relational database and enables the
data to be searched on and sorted as needed. For example, a person's full name would be
broken down into first, last and middle name so that a list of names could be sorted by any one
of these elements while an address would be broken down into address lines, city, state and
zip. Atomicity is a requirement for the First Normal Form in Database Normalization.
Attachment - A feature introduced in Access 2007 where external files such as Word and
Acrobat files can be stored in a field within the database.
Autoexec - A Microsoft Access macro that automatically starts as soon as the database is
opened in Access. Simply naming the macro autoexec signals to Access that this is the macro
to be run at startup.

Page 180

Microsoft Access for Beginners

Auto Expand - A feature in Microsoft Access and other software which automatically
completes entry of information into a field based on previous entries or other criteria.
AutoNumber - A database field type which automatically generates a random or sequential
unique value for a field when a new record is entered.
Boolean - As a data field type, this indicates a value that can be either True or False. These
two conditions can be represented in the field either by those words or through values such as
0 and 1 or Y and N.
CamelCase - A naming convention for variables in VBA in which multiple words are strung
together to form a recognizable name and the initial letter of each word is capitalized.
Class Module - In VBA, a code module that is attached to a form or report and supplies
programming functions for that object.
Column - In a database table, this is a collection of cells that represents one element of data
across all the rows such as a name or a city value. See Field.
Command Button - A control available on Access forms which mimics a real-life button. When
the user clicks on the command button with the mouse, a macro or VBA event is fired.
Compiler - A computer program that translates high-level programming instructions into a form
usable by the computer and performs a limited amount of error checking on the code.
Composite Key - A primary index in a table that consists of more than one field so that no two
records within the table can have the same combination of values in these fields. An example
would be a table of contacts where the composite key combined the name and phone number
fields. More than one record may exist with the same name or the same phone number but not
the same combination of both.
Concatenate - To combine multiple text values that are either specified or generated by
functions into a single string using the "&" character, i.e. with the Date() function representing
the current date, "Printed on: " & Date() would result in "Printed on April 30, 2008". This would
be used to provide values for labels and text boxes, especially on reports.
Constant - In Visual Basic for Applications, this is a type of variable that is defined once during
the program's operation and cannot be changed. An example would be a local sales tax or a
mathematical constant such as the value of Pi.
Control - Part of a program interface that provides functionality to the user and can be
designed to respond to events and user actions. Examples include command buttons and
toolbars.
Database - In general terms, a database is any collection of formatted data such as an

Page 181

Microsoft Access for Beginners

address book or any other list of items that share a set of common characteristics. In a
relational database, data is grouped into tables by subject or object type with columns that
contain the specific attributes (i.e. name, address, city) and rows for each item stored.
Database applications designed in Microsoft Access include objects such as queries for
retrieving specific data, forms for entering and displaying data and reports for compiling the
data into a presentable format.
Database Normalization - The process of organizing data into tables or other groupings by
subject so as to eliminate redundancy and ensure the integrity of the data. See Normal Forms.
Data Type - A format used by a database to store different kinds of data. Data types are
defined by the properties and limits of the data being stored. Examples include the Text or
String data type which stores alphanumeric data such as city and state names and the Integer
type which stores whole numbers within a given range. Data types also differ in the functions
that can be performed on them and the amount of space that is used to store them. A number
such as 33325 could be stored as a numeric type (integer, single, double, etc.) so that
mathematical functions could be performed on it. It could also be stored as text or string data if
part of an address or other text field.
Datasheet - A display of rows and columns that represent the data held in a data table or
generated by a query.
DBA - Database Administrator; a person who designs and maintains database systems,
usually for an organization and often as part of a larger I.T. department.
Declaration - In VBA, a line of code that indicates a new variable, constant or procedure to the
compiler.
Dependency - A resource that exists outside the control of an application and on which the
application is dependent for data or functionality. An example would be a data file from which
the program must obtain necessary data.
Developer - A person who develops software or database products. Aside from coding and
final construction of the product, this can include a range of tasks covering the development
life-cycle including gathering of business requirements, specification writing, testing and
deployment.
Dialog - In Access and VBA, a dialog is a screen form used to present and gather information.
It can include various types of controls that respond to specific events.
DoCmd - A VBA object that contains numerous methods which act as shortcuts, enabling the
user to perform various tasks with a single command.
Enumeration - In VBA, this is a list of items such as office locations or product categories that
is maintained as a collection of constants by the application. This list can be declared as a

Page 182

Microsoft Access for Beginners

variable type in VBA and the individual items can then be referenced through Intellisense.
Each item in the collection is assigned either a default or specific value so that items are stored
as numeric values while maintaining the name assigned to them for reference.
Event - In programming, an event is a condition which the program can respond to such as the
click of a command button or the change in a specific value. Events can be generated either by
user action or by a change in program conditions. Multiple events might occur or "fire" in rapid
succession as part of a larger task such as the display of a form.
Event-Driven Programming - A programming model in which instructions are issued to the
computer in response to actions by the user such as the click of a command button or the
opening of a form. Programming instructions are broken up into procedures that run when the
events fire. Event-driven programming is distinct from other forms of programming where the
entire program is contained in a single listing and run sequentially.
Field - In database terms, a table element that holds a specific piece of data. A field can be
represented by a column within a table or a box on a form where the user can enter or view the
data.
Field Validation - The process of applying certain rules to data within a field. This might be a
requirement on the number of characters that can be entered for a password, or the assurance
that a date entered falls within a certain range.
Filter - A set of rules that are applied when selecting information from a database. The filter
limits the amount of information returned thereby enabling the user to see only the relevant
data.
Foreign Key - A column in a database table that is used to match records with data in another
table. One example would be a Customer ID field used as the primary key in the main
Customer table and then as a foreign key in a table which lists the customer orders. The
foreign key identifies which orders belong to a specific customer by using the appropriate
customer ID value for each order.
Formula - A set of mathematical instructions used to achieve a result. In Microsoft Access, this
formula can include variables and constants pulled from the database.
Footer - A repeating section in a form or report that is displayed at the bottom of each page or
of the document itself. It can contain titles and controls such as page numbers and date
displays.
Form - An object within a Microsoft Access application which is used to display and enter
information. Forms may include multiple controls such as text fields and even other forms that
are used to group and enter data. The forms can also contain a large amount of programming
that is used to provide various functions to the user or to manage the operation of the
interface.

Page 183

Microsoft Access for Beginners

Function - See Procedure


Grouping - Within a query, data can be grouped on one or more fields in order to provide
results on groups of records. An example would be a grouping by city or department used to
report information or subtotals of different values based on these groupings of data. Groups
are also used in forms and reports to create custom headers and footers based on specific
fields.
HTML - HTML (HyperText Markup Language) is a text markup language used to create web
pages that can be displayed on the Internet and read by web browsers. It uses plain text which
is marked up with standard formatting codes that can be translated to format and arrange the
text on the screen. It is the primary language used for the construction of websites.
Header - A repeating section in a form or report that is displayed at the top of each page or of
the document itself. It can contain titles and controls such as page numbers and date displays.
Index - A structure in a database table that assists in the sorting and retrieval of data from the
table. Indexes may be placed on single fields or combinations of fields and may apply
restrictions such as the requirement of a unique value.
Inheritance - In Microsoft Access, the ability of a form field to inherit certain properties from
the table field that it references. This often includes functions such as a data lookup on the
field, providing pre-selected values for entry.
Integrated Development Environment (IDE) - A program that contains a combination of tools
for writing, debugging and compiling code.
Intellisense - A function of the Visual Basic for Applications IDE that assists in the completion
of commands as they are being typed and prompts for the necessary parameters for
referenced functions.
Immediate Window - A window within the Visual Basic for Applications IDE that is used for
testing formulas and displaying messages from the code in real time.
Integer - In Access, this is a data type that stores a whole number, a number with no fraction
or decimal places to the right of the zero. There are two types of integers in Access; regular
Integers store values from -32,768 to 32,767 while Long Integers store values from
-2,147,483,648 to 2,147,483,647. The difference is in the number of bytes used to store the
value.
Interface - A collection of controls that enable the user of a program to use its various
functions. This can be in the form of commands entered on a command line or graphical
controls on a form.
Join - The link between two related tables. A join specifies how the data is related and which

Page 184

Microsoft Access for Beginners

table is to take precedence in the relationship. The joins between tables affect the way that
data is retrieved by queries and other elements in the database.
Lookup Field - A field that references a list of values from which the user can select the
correct choice. This list may be a short list of values programmed into the field or a dynamic list
drawn from a database table.
Macro - A set of commands intended to run in order to carry out a specific task.
Margin - The areas at the top, bottom and sides of the report where data is not printed. In
Microsoft Access, The margins are set for a report in the Page Setup dialog.
Menu - A list of options from which a user selects the necessary function.
Method - See Procedure.
Microsoft Access - A relational database management system (RDBMS) designed for use on
personal computers. The software provides a system for designing database applications for
use by a small number of users. These applications can include data entry forms, queries and
reports in order to provide for all phases of data collection and analysis.
Module - A grouping of procedures and other code in Microsoft Access. It may be attached to
a form or report or be a standalone object within the database.
Normal Forms - A set of rules for organizing data which ensures that it meets specific
requirements of database normalization. The normal forms are applied in order with each
building upon the last in order to eliminate various types of redundancy from the data. Normal
forms are referred to by the order in which they are applied (i.e. First Normal Form or 1NF).
There are three basic forms which are most commonly applied with additional forms for
specific situations.
Object (VBA) - In VBA, an item which can have its own properties and methods and can be
referenced and manipulated in code. Forms, reports and the controls that they contain are all
considered objects. Custom objects can also be created in order to represent business related
entities such as customer orders or inventory items as well as items that the program must
interact with such as printers, files and database connections.
Operator - A symbol used to indicate a specific mathematical or logical operation in a formula.
In VBA, operators include standard math symbols such as + and - as well as logical and
comparison operators.
Parameter - A value accepted by a procedure or function for use in its calculations. In VBA,
parameters are included in the procedure declaration and are also called input variables.
Primary Key - The main index on a data table which contains a unique value to identify the

Page 185

Microsoft Access for Beginners

item stored in each row of the table.


Procedure - A unit of VBA code that can be called to perform a given function or return a
result. There are three types of procedures in VBA. Methods (subroutines) are the primary type
of procedure and are used to perform general operations and respond to events. Functions are
used to calculate and return values. Property procedures are used to store and return custom
property values on forms, reports and other values.
Programming Language - An artificial language used to issue instructions to a computer.
Some languages are designed for specific purposes such as business or scientific
programming while others are general purpose. Higher-level languages such as VBA and C#
contain commands that resemble human language and use compilers or interpreters to
translate the instructions into commands usable by the computer. While the syntax varies,
languages often have features such as decision loops, variables and error handling structures
in common.
Project Explorer - The section of the Visual Basic for Applications IDE that displays objects
containing editable code.
Property Procedure - In VBA, this is a type of procedure that controls access to a custom
property on a form or report. The property procedure can include functions to read and write to
the property. One of these functions can also be omitted to make the property read-only or
write-only.
Query - A set of instructions which retrieves data from a database table. In Microsoft Access
queries are designed using Structured Query Language (SQL).
Record - A collection of fields or values which combine to describe a single item. In Microsoft
Access, a record is represented by a single row within a table.
Recordset - A collection of data records. This term most often refers to records that have been
retrieved using a query or stored procedure and may have been pulled from a combination of
tables.
Record Validation - The process of applying certain rules to the data within an entire row.
These rules often involve the way in which different fields relate to each other. An example
would be an employee table where the employee's start date could not occur before the hire
date.
Recursive Programming - A programming technique in which a method or subroutine calls
itself in order to perform repeating operations on objects such as subdirectories that are
arranged in a hierarchy and therefore cannot be listed in a linear fashion.
Referential Integrity - The process by which relationships between tables are enforced. Most
commonly, this ensures that a record cannot exist in one table without a related record in

Page 186

Microsoft Access for Beginners

another table. For example, an order cannot exist in the Orders table without a corresponding
customer record in the Customers table which is required to supply a CustomerID value for the
order. It also ensures that data cannot be altered in a way that would defeat the established
relationships. Again, a record in the Customer table could not be deleted without considering
all of the records in other tables that referenced its CustomerID value. Access allows for
cascading updates and deletions of related records in tables to maintain referential integrity.
Relational Database - A database in which data is arranged into tables by subject or object
represented which are then related or joined by common fields. A common example is a
customer orders database in which one table contains information specific to the customer
such as contact information and another table contains the orders. A Customer ID would be
used to link these tables. This allows for organized and flexible entry and storage of the data
without the limitations of a flat file.
Relational Database Management System (RDBMS) - Software that enables the creation
and management of relational database systems. This software can be desktop or network
based and may allow for databases of varying sizes. An RDBMS must enforce the necessary
rules to keep the database in conformance with the relational database model designed by
E.F. Codd.
Relationship - Relationships specify how one set of data corresponds to another and are
expressed in terms of the number of members on each side of a relationship. For example, the
relationship between a Customer table and an Orders table would be a one-to-many
relationship with many orders for each customer. Relationships are defined within the
database in order to enable querying of data between tables for reporting and display on
forms.
Report - A database object that compiles database information in a format suited for printing
and analysis. The report design contains fields that pull data directly from the database and
can manipulate or perform calculations on that data as needed.
Row - In a database table or query, this is a collection of cells across multiple columns that
represent one data record.
Runtime - Refers to actions and decisions that happen during the operation of the program as
opposed to design time or during the compilation of the program. More specifically, it might
refer to an error that is not caught until the program runs that specific code. The Microsoft
Access Runtime also refers to the software which enables an Access database to be opened
and used on a specific machine. Starting with Access 2007, this software is available as a free
download from Microsoft with the limitation that design changes to the database are disabled.
Schema - The schema describes the way the data will be organized and represented. This
might be as general as an outline of objects represented by the database (i.e. employee,
customer, order, product) and the way in which they relate or as specific as the collection of
tables representing each object and the relationships drawn between them.

Page 187

Microsoft Access for Beginners

Scope - In VBA, the scope is the area of the code from which a specific variable or procedure
can be accessed. This might be limited to the specific procedure in which a variable is
declared or might encompass the entire application.
SQL - Structured Query Language - A scripting language that is used with relational databases
to provide an interface for the retrieval and storage of information in the tables. The language
provides keywords such as SELECT, INSERT and ORDER BY to specify actions to be
performed on specified fields and tables.
Subform / Subreport - In Microsoft Access, a form or report that is contained within another
form or report, usually displaying a related set of data. For example, an employee form might
contain a subform that would display a list of skills and certifications held by the employee
which would be stored in a separate table. The subform or subreport is related to the parent
object by a query that joins their respective tables.
Subroutine - See Procedure.
Tab Order - The order in which the TAB key will move the focus between various fields on a
form in Microsoft Access. This order can be set by the designer of the form to assist in proper
data entry.
Table - A database object that holds data in the form of rows and columns. This can be a
stored object within the database file or an abstract recordset that is held in memory during an
operation.
Template - An object which defines a pattern according to which data will be entered. This can
be a collection of symbols that specifies what type of characters will be allowed in each
position within a field.
Toolbar - A program bar which includes a collection of buttons that can be clicked to perform
various functions. In Microsoft Access, pre-defined and custom toolbars can be used with
forms as part of the user interface.
Unicode - An expanded character set used by Microsoft Office and other programs to
represent a wide range of characters from different languages including Arabic, Hebrew,
Chinese, Japanese and others.
Value List - A list of values made available to a control for selection by the user. In Microsoft
Access, this typically refers to a short list of values that are entered into the property sheet of a
drop-down style form control.
Variable - A placeholder and identifier for a specific value or item within VBA code which
allows that item to be changed when necessary and still retain its meaning and context.
Variant - A variable or object in VBA that is declared without a specific type and can then be

Page 188

Microsoft Access for Beginners

converted to the correct type as needed.


Visual Basic for Applications (VBA) - A version of Microsoft Visual Basic that is used with
the Microsoft Office Applications, most notably Access. VBA is used in conjunction with forms,
reports and other controls to perform functions beyond what is possible through standard
macros. The language offers many of the features of Visual Basic including error handling,
conditional operations and debugging tools.
Wizard - A section of a program which uses a series of dialog boxes to guide the user through
the choices involved in the creation of a project. In Microsoft Access, wizards can be used for
everything from creating simple controls such as command buttons to entire database
applications.
Zero-based - In VBA and other programming languages numbered lists such as arrays and
numbered collection items often start at 0 by default instead of 1.

Page 189

Microsoft Access for Beginners

Suggested Reading and References


Books
Microsoft Access 2010 Step by Step (Step By Step (Microsoft)) - Joan Lambert III, Joyce Cox
(Microsoft Press)
Published July 20, 2010, 448 pages (Kindle version available)
Access 2010: The Missing Manual - Matthew McDonald (Pogue Press)
Published: June 29, 2010, 832 pages
Access 2007: The Missing Manual - Matthew McDonald (Pogue Press)
Published: January 5, 2007, 752 pages (Kindle version available)
Microsoft Office Access 2007: The Complete Reference (Complete Reference Series)
(McGraw-Hill Osborne Media)
Published: January 26, 2007, 1024 pages (Kindle version available)

Links
Description of the Database Normalization Basics
http://support.microsoft.com/kb/283878
From Microsoft's support site. This is another resource for the basics of database
normalization with links to additional materials.
Microsoft Access Blog: Access 2010: Design More Maintainable Apps with Calculated
Columns
http://blogs.msdn.com/b/access/archive/2010/01/22/access-2010-design-more-maintainableapps-with-calculated-columns.aspx
Microsoft's explanation of the decision to introduce calculated fields into Microsoft Access
tables.
Microsoft Access Tips for Casual Users: Calculated Fields
http://allenbrowne.com/casu-14.html
An opposing view on calculated fields from Allen Browne's Database and Training website.
Customize the Ribbon in Microsoft Access 2007

Page 190

Microsoft Access for Beginners

http://www.databasedev.co.uk/access2007ribbon.html
A starting point for learning how to create a customized Office ribbon for your Access 2007
application.
Security Considerations and Guidance for Access 2007
http://msdn.microsoft.com/en-us/library/bb421308.aspx
Introduction to Macros
http://office.microsoft.com/en-us/access-help/introduction-to-macros-HA001214202.aspx
More information on creating and using macros in Access 2007
Get Started with Access Programming
http://office.microsoft.com/en-us/access-help/get-started-with-access-programmingHA001214213.aspx
An introduction to Microsoft Access programming with a comparison of macros and Visual
Basic for Applications (VBA)
Meet the Access 2010 Macro Designer
http://blogs.office.com/b/microsoft-access/archive/2009/07/28/meet-the-access-2010-macrodesigner.aspx
An introduction to the changes in the Microsoft Access 2010 macro designer. Includes a
demonstration video.
Working with Macros and Expressions in Access 2010
http://msdn.microsoft.com/en-us/library/gg435977.aspx

Page 191

About the Author


Andrew Comeau is a Microsoft-certified programmer based in Ocala, Florida. He has been working
with Microsoft Access since 1997 and provides independent consulting with that and other
technologies. He has also authored the book Your First Guide to Database Design, a beginner's
guide to database design principles. More information is available on his websites at Drewslair.com
and AndrewComeau.com.

Potrebbero piacerti anche