Вы находитесь на странице: 1из 60

Add a calculated field to a table

In Access 2010, you can create table fields that calculate values. The calculations can include
values from fields in the same table as well as built-in Access functions.

Notes: 

 The calculation cannot include fields from other tables or queries.


 The results of the calculation are read-only.

In this article
Create a calculated field

Modify a calculated field

Create a calculated field


1. Open the table by double-clicking it in the Navigation Pane.
2. Scroll horizontally to the rightmost column in the table, and click the Click to Add
column heading.
3. In the list that appears, click Calculated Field, and then click the data type that you want
for the result.

Access displays the Expression Builder.

4. Begin typing the calculation that you want for this field, for example:

[Quantity] * [Unit Price]

Note:  It is not necessary to precede the expression with an equal sign (=).

5. Click OK.

Access adds the calculated field, and then highlights the field header so that you can type
a field name.

6. Type a name for the calculated field, and then press ENTER.

For more information about creating expressions, see the article Create an expression.

Modify a calculated field


1. Open the table by double-clicking it in the Navigation Pane.
1
2. Click on the calculated field that you want to modify.
3. On the Fields tab, in the Properties group, click Modify Expression.

Access displays the Expression Builder.

4. In the expression box, make the necessary modifications to the calculation.

Note:  It is not necessary to precede the expression with an equal sign (=).

5. Click OK.

Create a simple select query


A select query is used to create subsets of data that you can use to answer specific questions. It
can also be used to supply data to other database objects. Once you create a select query, you can
use it whenever you need.

This topic explains how to create a simple select query that searches the data in a single table.
You will also learn how to enhance the query by defining record criteria and adding calculated
values.

In this article
Introduction

Create a query

Add criteria to the query

Add calculations to the query

Summarize query values

Introduction
A select query is a type of database object that shows information in Datasheet view. A query
can get its data from one or more tables, from existing queries, or from a combination of the two.
The tables or queries from which a query gets its data are referred to as its recordsource.

Whether you create simple select queries by using a wizard or by working in Design view, the
steps are essentially the same. You choose the recordsource that you want to use and the fields
that you want to include in the query — and, optionally, you specify criteria to refine the results.

2
ID Company Address City State PostalCode Country Phone Contact BirthDate
New (202) Steve
1 Baldwin Museum 1 Main St. NY 12345 USA 03-Dec-45
York 555-0122 Riley
Blue Yonder (201) Waleed
2 52 1st St. Boston MA 01234 USA 21-Mar-59
Airways 555-0123 Heloo
3122 75th (206) Guido
3 Coho Winery Seattle WA 98100 USA 01-Apr-73
Ave. S.W. 555-0042 Pica
Contoso 1 Contoso (171) Zoltan
4 London NS1 EW2 UK 16-Jun-67
Pharmaceuticals Blvd. 555-0125 Harmuth
(171) Julian
5 Fourth Coffee London W1J 8QB UK 09-Aug-71
555-0165 Price
Consolidated 3123 75th (206) Christine
6 Seattle WA 98100 USA 27-May-48
Messenger St. S 555-0007 Hughes
Graphic Design (171) Dana
7 151 Strand London WC2R 0ZA UK 12-Aug-61
Institute 555-0178 Birkby
3 Macrofirm (503) Jesper
8 Litware, Inc. Portland OR 97200 USA 01-Sep-75
Parkway 555-0086 Aaberg
22 Wicklow Phil
9 Tailspin Toys London WC1 0AC UK 15-Feb-53
Street Gibbins
(171) Tom
10 Woodgrove Bank 37 Lothbury London EC2R 7ED UK 25-Sep-38
555-0101 Perham

After you have created a select query, you run it to see the results. Running a select query is
simple — you just open it in Datasheet view. You can then reuse it whenever you need, for
example, as a recordsource for a form, report, or another query.

Note: For more information about using a query as a recordsource for a form or report, see the
article Use a query as a recordsource for a form or report.

There are several types of query, each serving a different purpose. For example, a select query
displays data. An action query changes the data in its datasource, or creates a new table. A
parameter query prompts you to supply criteria when you run it. This topic only covers select
queries.

Note: This topic describes how to create select queries that return data from a single table. If you
want to create queries that return data from two or more tables, see the article Create a query
based on multiple tables.

Create a query
In this exercise, you will create the London Contacts select query. You can create this query
either in Design view or by using a wizard. In addition, if you are familiar with writing SQL

3
statements, you can create a query while working in SQL view by writing a simple SELECT
statement.

Before you begin, you need to have a table that contains data. Sample data is provided below in
HTML table form.

You can either enter the data in this sample table manually, or you can copy this table to a
spreadsheet program, such as Microsoft Office Excel 2007, and then import the resulting
worksheet into a table in Microsoft Office Access 2007.

Enter the sample data manually

1. On the Create tab, in the Tables group, click Table.

Office Access 2007 adds a new, blank table to your database.

Note: You do not need to follow this step if you open a new, blank database, but you will
need to follow it whenever you need to add a table to the database.

2. Double-click the first cell in the header row and type the name of the field in the sample
table. By default, Access denotes blank fields in the header row with the text Add New
Field, like so:

3. Use the arrow keys to move to the next blank header cell and then type the second field
name (you can also press TAB or double-click the new cell). Repeat this step until you
enter all field names.

4. Enter the data in the sample table.

As you enter the data, Access infers a data type for each field. Each field in a table has a
specific data type, such as Number, Text, or Date/Time. Data types help ensure accurate
data entry and help to prevent mistakes, such as using a telephone number in a
calculation. You can specify the data type for each field in a table, and can change a
field's data type under certain circumstances. For this sample table, you should let Access
infer the data type.

5. When you finish entering the data, click Save or Keyboard shortcut Press CTRL+S.

The Save As dialog box appears.

6. In the Table Name box, enter Customers, and then click OK.

Copy the table to a spreadsheet program and then import it into Access

1. Start your spreadsheet program and create a new, blank file. If you use Excel, a new,
blank workbook is created by default.

4
2. Copy the sample table that provided in the previous section and paste it into the first cell
of the first worksheet.

3. Using the technique provided by your spreadsheet program, name the worksheet
Customers.

4. Save the spreadsheet file to a convenient location and go to the next steps.

Import the table into Access

1. In a new or existing database: On the External Data tab, in the Import group, click
Excel. -or-

Click More, and then select a spreadsheet program from the list.

The Get External Data - Program Name Spreadsheet dialog box appears.

2. Click Browse, open the spreadsheet file that you created in the previous steps, and then
click OK.

The Import Spreadsheet Wizard starts.

3. By default, the wizard selects the first worksheet in the workbook (Customers, if you
followed the steps in the previous section), and data from the worksheet appears in the
lower section of the wizard page. Click Next.

4. On the next page of the wizard, select First row contains column headings, and then
click Next.

5. The next page of the wizard offers you an opportunity to change field names and data
types or to omit fields from the import operation, by using the text boxes and lists under
Field Options. You should not do this for this example. Click Next.

6. On the next page of the wizard, in the Field Options box, select Yes (No Duplicates)
from the Indexed list, and select Long Integer from the Data Type list. Click Next to
continue.

7. On the next page of the wizard, select the Choose my own primary key option, choose
CustomerID from the list, and then click Next.

8. By default, Access applies the name of the worksheet to your new table. Make sure that
the table is named Customers, and then click Finish.

9. On the last page of the wizard, you have the option of saving the import steps for later
reuse. Because you are importing a sample table, it is not recommended that you save the
import steps.

5
Note: If you don't have a spreadsheet program, you can copy the sample data to a text editor,
such as Notepad. For more information about importing text data, see the article Import or link to
data in a text file.

Build the query

First, you will use a wizard to create the query, based on the sample table that you just created.
Then, you will enhance the query in Design view. At each step, you can review the SQL
statement that is automatically generated by the steps that you take.

1. On the Create tab, in the Other group, click Query Wizard.

2. In the New Query dialog box, click Simple Query Wizard, and then click OK.

3. Under Tables/Queries, click the table that has the data that you want to use. In this case,
click Table: Customers. Note that a query can also use another query as a recordsource.

4. Under Available Fields, double-click the Contact, Address, Phone, and City fields.
This adds them to the Selected Fields list. When you have added all four fields, click
Next.

5. Name the query London Contacts, and then click Finish.

Access displays all of the contact records in Datasheet view. The results show all of the
records, but show only the four fields that you specified in the query wizard.

Review the initial SQL statement

Click SQL View on the Access status bar; or, right-click the query object tab, and then
click SQL View. Access opens the query in SQL view, and displays the following:

SELECT Customers.[Contact], Customers.[Address], Customers.[Phone],


Customers.[City]
FROM Customers;

As you can see, in SQL the query has two basic parts: the SELECT clause, which lists the
fields that are included in the query, and the FROM clause, which lists the tables that
contain those fields.

Note: If you added the fields in a different order from the preceding procedure, the order
that you used will be reflected in the SELECT clause.

6. Close the query, and note that your query is automatically saved.

Add criteria to the query

6
To restrict the records that are returned in the query results, you can specify one or more criteria.

You can think of a query criterion as a condition that you specify for a field. The criterion
specifies a condition, based on field values, that expresses what you want to include in the query,
such as "show only those records where the value of City is London".

Open the query in Design view. You will add a criterion to the City field so that you see only
those contacts who are from London in the query results. You will also add criteria to the
Address field and the Phone field, to further refine your query results.

1. In the Criteria row of the City field, type london.

Now, add two more criteria to make the results even more meaningful. Suppose that you
only want to see the records in which both the address and the phone number are present.

2. In the Criteria row of the Address field, type Is Not Null AND <>"". Do the same in
the Criteria row of the Phone field.

Note: The criterion, Is Not Null AND <>"", is true whenever there is any known, non-
empty value for the field for which it is a criterion. It is false whenever there is no known
value (Null), or when the value is known to be empty (""). You can use this expression to
check a field for a known, non-empty value.

3. Switch to Datasheet view to see the results.

Review the SQL statement with criteria

Click SQL View on the Access status bar, or right-click the query document tab and then click
SQL View. Access displays the following SQL code:

SELECT Customers.[Contact], Customers.[Address], Customers.[Phone], Customers.


[City]
FROM Customers
WHERE (((Customers.[Address]) Is Not Null And (Customer.[Address])<>"")
AND ((Customer.[Phone]) Is Not Null And (Customer.[Phone])<>"")
AND ((Customer.[City])="london"));

You will note that the SQL statement now has a WHERE clause. The criteria that you specify for
query fields appear in SQL in the WHERE clause. In this case, they are combined by using the
AND operator.

What if you don't want the conditions to get combined by using the AND operator? In other
words, how do you specify two or more criteria but include the records that satisfy one or both
of them?

7
Specify alternate criteria sets by using OR

Suppose you want to see all the records where City equals London and where at least one kind of
contact information — either the address or the phone number — is available. You want to
combine the criteria by using the OR operator, like this:

To specify alternate criteria, use both the Criteria and Or rows in the design grid. All records
that meet the criteria defined either in the Criteria row or in the Or row are included in the
result.

Now you will modify the query by entering alternate criteria in the Criteria and Or rows.

1. Switch back to Design view.

2. Remove the Is Not Null AND <>"" string from the Criteria row of the Phone field.

3. In the Or row of the Phone field, type Is Not Null AND <>"".

4. In the Or row of the City field, type london.

5. Switch to Datasheet view to see the results. All records that include either an address, a
phone number, or both, and where City is London, are displayed in the query results.

Note: To specify more than two alternate criteria sets, use the rows below the Or row.
Each row represents an independent set of criteria.

Review the SQL statement with revised criteria

Click SQL View on the Access status bar, or right-click the query document tab and then click
SQL View. Access displays the following SQL code:

SELECT Customers.[Contact], Customers.[Address], Customers.[Phone], Customers.


[City]
FROM Customers
WHERE (((Customers.[Address]) Is Not Null And (Customer.[Address])<>"") AND
((Customer.[City])="london"))
OR (((Customers.[Phone]) Is Not Null And (Customers.[Phone])<>"") AND
((Customers.[City])="london"));

You will note that two things have changed: the criterion that specifies that City is London now
appears twice, and the criteria in the WHERE clause are now combined by using the OR
operator.

To learn more about how to specify criteria for various types of fields, see Examples of query
criteria.

Top of Page

8
Add calculations to the query
A well designed database does not store simple calculated values in tables. For example, a table
might store a person's date of birth but not their current age. If you know both today's date and
the person's date of birth, you can always calculate their current age, so there is no need to store
that in the table. Instead, you create a query that calculates and displays the pertinent value. The
calculations are made every time you run the query, so if the underlying data changes, so do your
calculated results.

In this exercise, you will modify the London Contacts query so that it displays each contact's
date of birth and current age.

1. Open the query in Design view.

2. From the Customers table window, drag the BirthDate field to the first blank column in
the design grid. You can also double-click the field name to automatically add it in the
first blank column.

3. In the next column, in the Field row, type the expression that will calculate the age for
each record. Type Age: DateDiff ("yyyy", [BirthDate], Date()).

Age is the name you are using for the calculated field. If you do not supply a name,
Access will use a generic name for the field, for example, EXPR1. The string following
the colon (:) is the expression that supplies the values for each record. The DateDiff
function calculates the difference between any two dates, and returns that difference in
the specified format. The format, yyyy, returns the difference in years, and the
[BirthDate] and Date() elements of the expression supply the two date values. Date is a
function that returns the current date, and [BirthDate] refers to the BirthDate field in the
underlying table.

Note: The calculation used for Age in this example is an approximation that may be
slightly inaccurate, depending on the current month.

Switch to Datasheet view. You see two additional fields, BirthDate and Age, in the result.

Review the SQL statement with calculations

Click SQL View on the Access status bar, or right-click the query document tab and then click
SQL View. Access displays the following SQL code:

SELECT Customers.[Contact], Customers.[Address], Customers.[Phone], Customers.


[City], Customers.[BirthDate],
DateDiff("yyyy",[BirthDate],Date()) AS Age
FROM Customers
WHERE (((Customers.[Address]) Is Not Null And (Customer.[Address])<>"") AND
((Customer.[City])="london"))

9
OR (((Customers.[Phone]) Is Not Null And (Customers.[Phone])<>"") AND
((Customers.[City])="london"));

Note that Customers.[BirthDate], and the calculated field, Age, now appear in the SELECT
clause. The AS keyword is used to designate the name of the calculated field.

For more information about how to write expressions that calculate values in a query, see the
article Create an expression.

Top of Page

Summarize query values


Summarizing the columns in a query is easier in Office Access 2007, compared to the same task
in earlier versions of Access. You can add, count, or calculate other aggregate values, and
display them in a special row (called the Total row) that appears below the asterisk (*) row in
Datasheet view.

You can use a different aggregate function for each column. You can also choose not to
summarize a column.

In this exercise, you will modify the London Contacts query so that it displays the Total row.

1. Open the query in Datasheet view.

2. On the Home tab, in the Records group, click Totals.

3. Click the Total row in the Contact column.

In the drop-down list, you can choose between None and Count. Because the Contact
column displays text values, other functions, such as Sum and Average, are not relevant,
and are therefore not available.

4. Select Count to count the number of contacts that are displayed in the result.

The number 5 is displayed in the Total row.

5. In the Age field, select Average. Because the Age field evaluates to a number, it supports
the Sum,Average, Count, Maximum, Minimum, Standard Deviation and Variance
functions.

Access displays the average age in the Total row.

To clear the total for a column, click in the Total row under that column, then select None from
the drop-down list. To hide the Total row, on the Home tab, in the Data Type & Formatting
group, click Totals.

10
Note: Using the Total row does not change the underlying SQL statement.

Microsoft Access Query Tips and Techniques (SQL and


VBA)
Microsoft Access is the most popular Windows database program. A primary reason for its
success is its interactive query interface. Once data is collected in a database, analysis and
updates need to be performed. Queries offer the ability to retrieve and filter data, calculate
summaries (totals), and update, move and delete records in bulk. Mastering Microsoft Access
queries will improve your ability to manage and understand your data and simplify application
development.

Examples are for Microsoft Access 2016, 2013, 2010 and 2007. Also applies to Microsoft
Access 2003 and earlier.

Queries Hide the Complexity of Microsoft Access SQL Syntax

The visual representation of tables and the graphical links between them makes Microsoft
Access queries extremely easy to use and hides the complexity of writing the raw Microsoft
Access SQL. Fortunately, the nice user interface still allows very powerful and advanced
analysis. The entire query engine is modeled on SQL systems and can switch between the
graphical query design and SQL syntax. Many Microsoft Access users and developers learned
SQL from this feature.

Knowing the many features of Microsoft Access queries allows you to perform advanced
analysis quickly without programming. This presentation covers the basics of queries revealing a
variety of subtleties. It quickly moves to more advanced topics with hints and techniques for
creating sophisticated queries. Finally, programmatic use of queries is presented:

 Query Types
 Basic Select Queries
 Setting Criteria
 Advanced Select Queries
o Using Parameters
o Using Access Functions
o Using Custom Functions
o Other Advanced Queries
o Percent of Total
o Frequency Distribution
o Union Queries to Combine Queries
 Action Queries
 Using Queries in Forms, Reports, and Macros
 Using and Running Queries with VBA Code
 Additional Resources

11
Download Sample Microsoft Access Query Database (155K)

Query Types
Microsoft Access supports many types of queries. Here is a description of the major categories:

 Select Queries
Retrieve records or summaries (totals) across records. Also includes cross-tabulations.
 Make Table Queries
Similar to Select queries but results are placed in a new table.
 Append Queries
Similar to Select queries but results are added to an existing table.
 Update Queries
Modify data in the records.
 Delete Queries
Records are deleted from a table.

Select queries are the most common queries and can be used for viewing and a data source for
forms, reports, controls, and other queries. The other queries create or change data and are
known collectively as Action queries.

Basic Select Queries


The most basic Select queries retrieve the records you specify from a table. You can choose the
fields from a table to display, and specify the criteria for selecting records. In the most cases,
while viewing the query results you can modify the data and update the original records. These
updateable views are extremely powerful.

Selecting Table and Fields

The first step in creating a query is to specify the table or tables to use and the fields to display.
Selecting tables is simple. Just choose the table from the list when the query is first created or
use the Add Table command from the Query menu. The selected table is placed on the upper
portion of the query design window. From there you can select the fields for the query by double
clicking on them or selecting several fields (using Shift-Click or Ctrl-Click) and dragging them
to the bottom portion: the query by example (QBE) grid. Make sure the Show option is checked
to display the field.

12
Sorting and Reordering Fields

Once the fields are placed on the QBE grid, you can reorder the fields by clicking on the column
and dragging it to the place you want. To sort the results, specify the Sort option under the fields
to sort. You can choose Ascending or Descending order. Note that you can turn off the Show
setting and sort on a field that does not appear in the display.

Renaming Fields

A very nice feature of Microsoft Access queries is the ability to rename fields. You may have
your data stored in field names that are not easily understood by users. By using a query
expression, you can change the field name the user sees. For instance, a field named "CustID"
could be changed to "Customer ID" by placing the new name followed by a colon and the
original name in the QBE field cell: Customer ID:[CustID].

Using Calculated Fields (Expressions)

In addition to retrieving fields from a table, a Select query can also display calculations
(expressions). Of course, expressions cannot be updated since they do not exist in the original
table. Expressions are extremely powerful and allow you to easily display complex calculations.
There is an Expression Builder that simplifies the selection of fields and functions. By default,
expression fields are named "Expr1", "Expr2", etc.; therefore, you usually want to rename them
to something more understandable.

Expression fields are also useful for sorting your records. Here's an example of using a calculated
field to Sort on Multiple Date (or Numeric) Fields with Blank Values in a Microsoft Access
Query.

Setting Query Properties

While designing a query, you can choose View | Properties or right click on the top portion of the
query and choose Properties to see and modify the query properties.

13
Description

This property lets you provide a description for the query to help you remember its purpose.

Default View

Show the results in a datasheet like a table, or a pivot chart or pivot table.

Output All Fields

This option is usually set to No. If it is changed to Yes, all the fields of all the tables in the query
are shown. In general, you should leave this property alone and specify the fields desired in the
QBE grid.

Top Values

Rather than retrieving all records, you can specify the top n records or n percent, where n is the
value specified here.

14
Unique Values

By default this is set to No and all records are retrieved. If this is changed to Yes, every record
retrieved contains unique values (SQL uses the SELECT DISTINCT command). That is, no
retrieved records are identical.

For instance, you can run a query for the State field of the Patient table. With this set to No, the
result is a record for each patient. When set to Yes, only the list of unique states is displayed.
When set to Yes, the query is not updateable.

Unique Records

By default this is set to No and all records are retrieved. For one table queries, this property is
ignored.

For multi-table queries, if it is set to Yes, (similar to using a DISTINCTROW in a SQL


statement) only unique records in the underlying tables are retrieved.

The Unique Records and Unique Values properties are linked and only one can be set to Yes
(both can be No). When Unique Records is Yes, Unique Values is automatically set to No. When
both properties are set to No, all records are returned.

Difference between DISTINCT vs. DISTINCTROW

These options sometimes appear to provide the same results, but there are significant differences.

DISTINCT checks the results of query and eliminates duplicate rows. These queries (Unique
Values = Yes) are not updateable. They are a snapshot of your data and don't reflect subsequent
data modifications by users. This is similar to running a Totals Query (e.g. using a Group By
clause).

DISTINCTROW checks all the fields in the table and then eliminates the duplicate rows. The
results of a query with DISTINCTROW (Unique Records = Yes) are updateable and reflect
changes to retrieved records (but the query does not automatically run again if the data changes
to retrieve different rows).

So the difference is that DISTINCT only checks the fields in the results, while DISTINCTROW
checks all the fields in the underlying tables. If your query joins several tables and only displays
records from one, the DISTINCTROW option lets you view and edit the results.

For more information, visit Distinct versus DistinctRow in Microsoft Access Queries.

15
Non-Updateable Queries

Some queries are not updateable. For more information, read our paper addressing the warning
message you see: This Recordset is not updateable: Dealing with non-updateable queries in
Microsoft Access

SQL Server Properties

There are several properties related to SQL Server tables and are more technical and rarely need
to be modified. For more information refer to Microsoft Access' on-line help system.

Filter, Order By, Filter On Load, Order By On Load

Like a form, you can specify the Filter and Order By settings for a query. However, this is
usually part of the query's SQL statement. By using the Filter and Order By properties, you have
the extra advantage of specifying the Filter On Load and Order By On Load properties to apply
them or not.

Subdatasheet Name, Link Fields, and Size

If you want to display a subdatasheet to show a one-to-many relationship between the results in
this query with data from another table, you can specify them here. There is a significant
performance cost for having subdatasheets, so only add them if you want them.

Setting Field Properties

In addition to query properties, each field also has properties that can be set. Move to a
field in the QBE grid and right click. Depending on the field type, different properties are
available. The most important properties are for numeric and date fields. You can specify
how the fields are formatted when the query is run.

Viewing Results and SQL Equivalent

Once the query is completed, you can view its results by switching from Design to DataSheet
view. You can also view the SQL equivalent. You can even edit the SQL syntax directly and
view the results and/or switch to Design view.

Setting Criteria
The bottom section of the QBE grid is several rows for Criteria. These are optional entries to
specify which records are retrieved. If you want all the Patients from the state of Virginia, just
enter "VA" in the State's criteria. To further narrow the scope, you can enter criteria for several
fields.

16
Multi-Field Query Criteria

Entering criteria on the same row for several fields performs an AND query between the fields.
That is, records that match the criteria in field 1 AND the criteria in field 2, etc. are retrieved. If
criteria is placed in different rows, an OR query is performed: retrieve all records matching
criteria in field 1 OR criteria in field 2, etc.

Criteria Types

The simplest criteria is the exact match. Just enter the value desired in the field's criteria section.
Remember that by using the Show option to eliminate the field from the display, you can specify
criteria in fields the user never sees.

<>, <, >, Between .. And ..

You can also retrieve records where a field does not have a particular value by using "< >"
followed by the value you don't want. Similarly, you can use >, <, >=, or <= for ranges. To select
records with values between two values, use the BETWEEN .. AND .. syntax.

Nulls

To select records with Null values, enter Is Null. The opposite is Is Not Null. For text fields,
remember that zero length strings ("") are not nulls.

OR and IN(.., .., ..)

To select records where a field can have one of several values, use the OR command. You can
simply say: "MD" or "DC" or "VA". Alternatively, the IN command performs the same function:
IN("MD", "DC", "VA"). The second syntax is easier if you have many values. Of course, if you
have a very large number of values, it is better to keep those values in a table and link your query
to it. That is easier to maintain than OR or IN clauses inside queries.

Wildcard Searches

Sometimes, you need to search for a particular letter or digit. Combined with the Like command,
wildcards let you specify such criteria. These are the wildcard characters Microsoft Access uses:

 ? Single Character
 * Any number of Characters
 # Single Digit
 [..] Character List
 [!..] not in Character List

For instance, if you are interested in a text field where the second letter is "a", the criteria would
be: Like "?a*". If you were seeking values where the second letter could be an "a" or "e", the
criteria would be: Like "?[ae]*". The opposite of this (all values that do not have "a" or "e" as the

17
second letter) is performed by adding an "!": Like "?[!ae]*". Finally, to select a range of letters
(say "a" through "e"), add a dash between the letters: Like "?[a-e]*".

To search for a wildcard character, enclose the value in brackets. For instance, to find values that
end in a question mark, use this: Like "*[?]"

Advanced Select Queries


 Using Parameters
 Using Access Functions
 Using Custom Functions
 Other Advanced Queries
Top Records, Total Queries, Crosstabs, Multi-table Queries, Basing queries on queries
 Percent of Total
 Frequency Distribution
 Union Queries to Combine Queries

Using Parameters
Often it is not possible to know in advance the criteria for a query field. In such cases, where the
filter values are not known until runtime, a variable (parameter) can be used. When these queries
are run, the user is prompted for the value of each parameter. (The parameters can also be
assigned programmatically). Using parameters in queries is extremely powerful and converts
static "hard-coded" queries to flexible, dynamic ones. The use of parameters can significantly
reduce the number of queries you need, makes queries more useful, and simplifies database
maintenance.

Parameters can be added very easily. Rather than entering the value of a criteria, enter between
brackets the prompt you want the user to see when the query is run. The value the user enters
replaces the parameter in the query. In the following example, a parameter [Enter State Name:] is
the criteria in the [State] field, and [Enter Minimum Age:] is the parameter in the [Age] field.
When this query is run, the user is prompted for the state desired and minimum age, and the
records matching that value are retrieved.

18
Parameters work provided the parameter definition does not conflict with the field name among
the query's tables.

To better define a parameter, you should specify it in the list of parameters. This is an optional
step, but there are good reasons to do so. Right mouse click on the top part of the query and
choose Parameters. This form appears to let you list each parameter name and its type:

19
By explicitly defining parameters, users are forced to enter values conforming to the type. While
it may not matter for text fields, it is useful for numeric and date fields. This minimizes data
entry errors that cause a "Can't evaluate expression" error message to appear.

Using Access Functions


One of the most powerful features of Microsoft Access queries is their support for Access
functions. This is most useful in Update queries, but can also be used in Select queries. The
Advanced: Access Functions query is an example of this feature:

20
This query selects the Country names in descending order of name length. The second field
renames itself to [Length], uses the LEN function to calculate the length of each country name,
sorts the length in descending order, and excludes any records with 10 letters or fewer.

While this may not seem particularly useful, there are many situations where using Access
functions is extremely useful and eliminates the need to program. The string functions in
particular (Left$, Right$, Trim$, Mid$, UCase$, LCase$ etc.) are useful for manipulating
portions of strings and changing case.

Using Custom Functions


In addition to using Microsoft Access functions, queries also support user defined functions.
Functions defined in VBA modules must return an appropriate value and can be used to
manipulate each record. You can reference field values by passing the field name in brackets.

Here is an example where a function (StripLead) is used to remove the leading word of a phrase
if it starts with "The", "An", or "A". This is useful for sorting phrases such as book titles on
"real" words:

21
This is the code for the StripLead function. It is passed a string and returns the string without the
leading word (if any):

Public Function StripLead(pstrPhrase As String) As String


' Comments: Get rid of leading A, An, or The in a phrase.
' Used for card catalog sorting.
' Params : pstrPhrase Phrase to examine
' Returns : The input phrase without the "useless" first word.
' Returns the same phrase if the first word isn't an issue

Dim strFirstWord As String


Dim strReturn As String
Dim intPos As Integer

strReturn = pstrPhrase
intPos = InStr(pstrPhrase, " ")
If intPos > 0 Then
strFirstWord = Left$(pstrPhrase, intPos - 1)
Select Case strFirstWord
Case "A", "An", "The"
strReturn = Right$(pstrPhrase, Len(pstrPhrase) - intPos)
End Select
End If

StripLead = strReturn
End Function

And this is the result. Notice how the sorting of the [Adjusted] field differs from the [Original]
field:

22
Other Types of Select Queries
 Top Records (number and percent)
 Total Queries
 Crosstab Queries
 Multi-table Queries
 Basing Queries on Other Queries

Top Records (number and percent)


Select queries retrieve all the records that meet your criteria. There are occasions where you only
want a subset: the top or bottom number of records. Similarly, you may just want the top or
bottom percent of records.

This is easy to do. Just change the query's Top Values property (right mouse click on the top
portion of the query), you can specify the number of records to display. The example below
(query: Other: Top 10 Auto Companies) has this set to 10:

23
Notice the query is retrieving records in Descending order so the Top Values option retrieves the
largest values. It simply runs the query and displays the specified number of records in the query
output's order.

To display the lowest values, the query should retrieve records in Ascending order.

Top Percent of Records

Sometimes, you want a percentage of records and not a fixed number. To retrieve the top n% of
the query records, enter a percentage (e.g. 10%) rather than just a value in the Top Value option.
Similarly but sorting in the opposite direction, you get the bottom percentage of records.

24
Total Queries
Up to now, we have only retrieved records. With lots of data, it is important to calculate
summaries for groups of records or totals on the entire table. This is possible by specifying
Totals from the Show/Hide ribbon in Access 2007 or the View menu in Access 2003 or earlier.

Microsoft Access 2007 and Later

This performs calculations across all the records and creates a summary result. For instance, you
can Sum on a numeric field to determine the total for the entire table. Additionally, you can
group on fields to calculate totals for each unique combination of values across the group fields.

When Totals is selected, a new "Total" row appears in the query design. You can specify the type
of calculation you want in that section:

25
For this query, the result shows average Age, Weight and Cholesterol for patients by State and
Gender.

Crosstab Queries
Crosstabs are a powerful analysis tool that lets you quickly see the relationship of data between
two fields. The view is a spreadsheet like display with unique values of one field as rows, unique
values of another field as columns, and the summary of another field as the cells in the matrix.

For instance, with the previous example, a crosstab can clearly show the average Cholesterol
between State (rows) and Sex (columns):

26
The easiest way to create a crosstab is to use the Crosstab Wizard. When creating a new query,
select Query Wizard and follow the Crosstab Query steps:

Crosstab queries can also be manually created by selecting Crosstab from the Query menu and
specifying the Row and Column Headings:

27
Multi-table Queries
To this point, all the queries shown were for one table only. Microsoft Access queries allow very
sophisticated multi-table queries. Criteria and field selections can be from any of the query's
tables. Linking tables on fields is done visually by dragging a line between the fields to link.

For our previous example, we may want to show the full name of each state rather than its
abbreviation. With a State table that contains the abbreviation and full names, this can be easily
performed:

28
Notice the link on the [State] fields and the [Name] field from the States table in the query. To
create multi-table queries, the Table row should be displayed. This can be activated from the
View | Table Names menu. Even better, the default query options should set Show Table Names
to Yes.

There are several ways to join tables in a query. The previous example was the most common
which is an exact match between fields, sometimes called an INNER JOIN. Another join
includes retrieving all records from one table regardless of whether there are matches in the
second table. This is called a LEFT JOIN. If the logic is reversed (all records from the second
table and matching records from the first) it is called a RIGHT JOIN. These options can be
selected by double clicking on the linking line and choose among the three options.

Left Join Between Tables

Here is an example of a query with a left join and the results.

Notice how States that do not have patient data are shown with no value in the [MaxOfAge] and
[AvgOfCholesterol] fields:

29
No Joins Between Tables

Queries with multiple tables do not even require a line between the tables. If no lines are
specified, a record by record link is assumed. That is every record in the first table is linked to
every record in the second table. This is most useful when one of the tables only has one record.
Finally, tables may be linked through an expression that establishes a partial match or match
based on a range of values. Examples are shown later.

Basing Queries on Other Queries


So far, the queries presented are only based on tables. However, Microsoft Access lets you also
base queries on other queries. This ability to filter and analyze data across several levels is
extremely powerful. The queries themselves behave identically whether the data comes from
tables or queries.

Basing queries on other queries can also simplify maintenance of your database by letting you
create standard queries that other queries can use. This can be particularly useful in reports. Of
course, you need to be careful modifying the "core" queries.

30
Additionally, when generating reports in multi-user databases, make sure you don't use queries
when you should be using temporary tables generated by Make Table and Append queries.
Queries always retrieve the most current data. If you are printing many reports while others are
modifying the data, and consistency between reports is important (the numbers need to tie), you
must create temporary tables with the data you need prior to printing. You can then base your
queries on those "static" tables.

Percent of Total
For a field, calculating the percent of each record to the total for an entire table is useful for
determining the relative size of each group. This can be achieved by creating a summary query
and using that in another query with the original table. In this example, we use the Fortune100
table containing sales and profits data for 100 large corporations; and two queries ("Fortune 100
Totals" and "Fortune 100 PercentOfTotals"). Here's how they work:

Step 1: Create a Query calculating the Totals

This is a simple query that sums the values in the two fields: [Sales] and [Profits]. For clarity, the
resulting fields are named [TotalSales] and [TotalProfits].

Step 2: Create a Query with the Totals and the Original Table

This is a simple select query that retrieves fields from the Fortune100 table and creates new
fields for the Percent of Total calculations. Notice the two tables are not linked with lines

31
between them. They only interact in the Percent of Total calculations where the values in the
calculated fields using TotalSales and TotalProfits as divisors:

Step 3: Run the Query

Running the query provides the desired results:

32
Notice how the [Profit%] field shows data nicely formatted (unlike [Sales%]). The difference is
due to formatting settings on the [Profit%] field. While designing the query, right click on the
[Profit%] field and notice its format is set to Percent. For the [Sales%] field, it's a standard
number. This is the reason that the formula for [Sales%] includes a 100 factor that is not in the
[Profit%] column.

Percent of Total in Microsoft Access Reports

Calculating percent of total in Microsoft Access reports is even simpler because queries don't
need to be created. The first step is to create a control with the summary (total). Place the text
box control in the grouping or report footer and set its control source to "=Sum([FieldName])"
where FieldName is the same of the field you want to sum. The value can be the total for the
entire report or just the group. Give the text box control a name (e.g. txtTotal). You can then
reference that control for the value of the total. In the Details section, you can calculate the

33
percent of total in a text box by setting the control source to "=[FieldName]/[txtTotal]" and set
the format to Percent.

Frequency Distributions
Frequency distributions reveal the number of records that contain values within numeric ranges.
By using the VBA function, Partition, you can group on that for intervals of identical widths.

In this example, we show how you can define your own groupings of different size ranges, give
them your own label and sort the results in the order you expect. All without writing any code!

In this example, we want to know how many patients fall into different age categories (under 25,
25 to 40, 40 to 50, 50 to 60, and 60+).

A simple two table query calculates these results even when the size of the numeric ranges are
not identical. In this example, we use two tables (Age Groups and Patients), and one query
(Frequency: Age Distribution). Just follow these simple steps:

Step 1: Create a table defining the


groups and numeric ranges

Simply create a table with four fields: Group ID (counter), Group Name (text), Minimum
(number), and Maximum (number). For each record, define the groups and its low and high
values:

Notice how the [Maximum] value of one record is smaller than the [Minimum] value of the next
record. They cannot be identical or else such values would fall into two groups. In our example,
the Age data are integers so using integers in this table is okay. Otherwise, you can use numbers
very close to each other (e.g. 24.9999999). You can name and specify as many groups as you
like.

Step 2: Create multi-table Select query

Create a Totals Select query with the data table and the Group definition table defined above:

34
Notice that the two tables boxes are not linked to each other. The first and third fields in the
query come from the group table: the [Group Name] description and the [Group ID] field
controlling the sort order. The second field is the count of the Patient (data) table's [ID] field
(this field is used since it is not null for every record). The final field defines the link between the
two tables. Using the Patient table's [Age] field, the criteria is "Between [Minimum] And
[Maximum]". This "bins" the Patient data into the age groups defined by the Group table.

Step 3: Run the Query

Running the query provides the desired results:

If the Group table's [Group ID] field is not used in the query, the results would be shown in
Ascending order by [Group Name] ("Under 25" would be the last record).

Combining Queries: Union Queries

35
Sometimes you may want to show the results of multiple select queries as one. While we would
normally suggest using a temporary table to store results from multiple queries just for clarity
and maintainability, there are situations where that's excessive.

For instance, some combo boxes (for lookups) need to show a blank value when the user is not
required to make a selection. Here's a example of how to show a list of states with an initial
blank row by combining a dummy record:

SELECT "" AS State, "" AS Name


FROM States
WHERE (States.State)="VA")

UNION

SELECT States.State, States.Name


FROM States;

See the query "Union Query State List with Blank" in the sample database to see how this works.
The first SELECT statement just creates a dummy record using criteria that only returns one
record (State = "VA" for Virginia). Rather than showing the value from the Virginia record, it
returns blank values for both the State and Name fields. Open the query "Union Query Blank
State" to see this.

For more information on union queries, read our paper on Union vs. Union All SQL Query
Syntax.

36
Action Queries
To this point, we have only covered Select queries. These queries take existing data and display
it to you either record for record or in a summarized manner. Action queries actually change
data. These queries can modify fields, add records to tables, delete records, and even create
tables. To specify the query type, select among the options presented under the Query menu
while designing a query:

These queries are similar to creating Select queries:

Make Table Queries

Make Table queries are identical to Select queries except rather than creating a datasheet display
of the results, a new table is created containing the results. These are particularly useful for
creating temporary tables. For instance, if you are generating a series of reports while other
people are changing the data, a Make Table query can create a snapshot of your data and allow
your reports to work off that table. This lets you create a consistent set of reports.

37
Append Queries

An Append Query in Microsoft Access is similar to a Select query, but the results are inserted as
new records into another table. The field names do not need to match and expressions can also be
used. The other table may or may not be empty before records are inserted.

Update Queries

An Update Query in Microsoft Access allows you to modify the data in your records. This is
often used to update a field with an expression or data from another table.

Delete Queries

A Delete Query in Microsoft Access lets you specify the records to remove from a table. You
can empty the entire table, remove records based on criteria in its fields or values in other tables.

Queries in Forms, Reports, and Macros


Using Queries in Forms and Reports

Queries can be used in forms and reports in a variety of ways. The most common is the Record
Source of the form or report. Another useful place is the RowSource of a ComboBox.

Running Queries through Macros

38
Running a query with a macro is very simple. Just use the OpenQuery command and specify the
query name to run. If the query has parameters, the user is prompted for the values.

If you are running an Action query, you can do the same thing; however, Action queries usually
display warning messages prior to changing data. To eliminate such messages, use the
SetWarnings command to turn this off and on before and after the query.

Using and Running Queries in VBA Code


There are many ways to run queries through modules. Here are a few examples:

 Creating and using a RecordSet based on a saved Select query


 Assigning Parameters in Queries
 Using a SQL string to open a Recordset
 Running a stored Action query
 Creating a table with a MakeTable Query SQL string

Creating and using a RecordSet based on a saved Select query

RecordSets let you programmatically move through a table or query. By assigning a Select query
to a RecordSet, you can move through the table. Commands such as MoveNext, MoveFirst,
MoveLast, MovePrevious, let you control where you are in the query. By checking the EOF
status, you can make sure you stop at the end of the table. Field values are referenced with a !
then field name.

Public Sub BrowseQuery_DAO()


' Comments: Browse a query and display its fields in the Immediate Window
using DAO

Const cstrQueryName = "Basics: Top 10 Most Profitable Companies"


Dim dbs As DAO.Database
Dim rst As DAO.Recordset

' Open pointer to current database


Set dbs = CurrentDb

' Open recordset on saved query


Set rst = dbs.OpenRecordset(cstrQueryName)

' Display data from one record and move to the next record until finished
Do While Not rst.EOF
Debug.Print "Company: " & rst![Company] & " Sales: " & rst![Sales] & "
Sales: " & rst![Profits]
rst.MoveNext
Loop

rst.Close
dbs.Close
End Sub

39
This example prints the company name and sales in the Immediate Window.

Assigning Parameters in Queries

Earlier we showed how to use parameters in queries. If you want to run from code a query which
has parameters you need to specify the parameters in your code. Otherwise, the user is prompted
for the parameter value when the query is executed.

To pass a parameter value to a query, you need to create a QueryDef and reference its parameters
collection. From there you can specify each of the query's parameters. When you are finished,
you can create a recordset from it (if it is a Select query) or execute it if it is an Action query. To
learn more about QueryDefs and the parameters collection, refer to the on-line help section under
QueryDefs.

Public Sub RunParameterQuery_DAO(pstrState As String)


' Comments: Runs a query containing parameters
' Params : pstrState Name of state to select records

Const cstrQueryName As String = "Basics: Parameters"


Dim dbs As DAO.Database
Dim qdf As DAO.QueryDef
Dim rst As DAO.Recordset

Set dbs = CurrentDb()


Set qdf = dbs.QueryDefs(cstrQueryName)
qdf.Parameters("State Abbreviation") = pstrState

' Open recordset on the query


Set rst = qdf.OpenRecordset()
Do While Not rst.EOF
Debug.Print ("ID: " & rst![ID] & " State: " & rst![State])
rst.MoveNext
Loop

rst.Close
qdf.Close
dbs.Close
End Sub

Using a SQL string to open a Recordset

Often it is not possible to know a query's specifications in advance. In these situations, the query
needs to be programmatically created. This is done be creating a SQL string containing the query
to run. The example below shows a simple case, but one can easily create a more complex
example where the query string (strSQL) is based on other situations (field values, user
selections, etc.).

Public Sub RecordsetFromSQL_DAO()


' Comments: Browse the results of a SQL string and display it in the
Immediate Window

Dim dbs As DAO.Database

40
Dim rst As DAO.Recordset
Dim strSQL As String

strSQL = "SELECT Left([Company],1) AS Letter, Count(Company) AS [Count], " &


_
"Avg(Sales) AS AvgOfSales, Avg(Profits) AS AvgOfProfits " & _
"FROM Fortune100 " & _
"GROUP BY Left([Company],1)"

' Open pointer to current database


Set dbs = CurrentDb()

' Create recordset based on SQL


Set rst = dbs.OpenRecordset(strSQL)

Do While Not rst.EOF


Debug.Print "Company Letter: " & rst![Letter] & _
" Sales: " & rst![AvgOfSales] & _
" Profits: " & rst![AvgOfProfits]
rst.MoveNext
Loop

rst.Close
dbs.Close

End Sub

Running your own query string is identical to the previous examples. Just base a RecordSet on
the query string.

Running A Stored Action Query

To run a saved Action query like an Update Query, use the query Execute command. The simple
procedure below lets you easily run a saved query. Just pass the name of the query and it is
performed:

Public Sub RunActionQuery_DAO(pstrQueryName As String)


' Comments: Sample code of running a stored (action) query
' Params : pstrQueryName Name of the query to run

DoCmd.SetWarnings False
CurrentDb.Execute pstrQueryName
DoCmd.SetWarnings True

End Sub

This procedure sets up a database variable referencing the current database, and creates a
QueryDef based on the query name. The Warning message is temporarily turned off before
executing the query and reset afterwards. DoEvents and DBEngine.Idle commands are used to
make sure the Jet Engine has completed its tasks and releases its locks.

41
Creating a table with a MakeTable Query SQL string

A MakeTable query is an Action query and can be run with the Action Query example shown
earlier. The only wrinkle here is to make sure the new table is deleted prior to the Make Table
query's execution. Also, the example below shows another way to execute a query without using
a QueryDef.

Public Sub MakeTableFromSQL_DAO()


' Comments: Sample code running an action query created in a SQL string
' Includes simple error trapping to handle problems creating table

Const cstrNewTableName As String = "Fortune100 LetterSummary"


Dim strSQL As String
Dim strError As String

' SQL string to create a new table


strSQL = "SELECT Left([Company],1) AS Letter, Count(Company) AS [Count], " &
_
"Avg(Sales) AS AvgOfSales, Avg(Profits) AS AvgOfProfits " & _
"INTO [" & cstrNewTableName & "] " & _
"FROM Fortune100 " & _
"GROUP BY Left([Company],1)"

' Delete table if it exists


On Error Resume Next
DoCmd.DeleteObject acTable, cstrNewTableName

Err.Clear

' Execute (run) the query


CurrentDb.Execute strSQL
If Err.Number <> 0 Then
strError = Err.Description
End If

On Error GoTo 0

If strError = "" Then


MsgBox "Table: [" & cstrNewTableName & "] created"
DoCmd.OpenTable cstrNewTableName
Else
MsgBox "Error creating table: " & strError
End If

End Sub

Additional code is provided in the sample database with this paper.

Calculated Fields
How do you get Access to store the result of a calculation?

42
For example, if you have fields named Quantity and UnitPrice, how do you get Access to write
Quantity * UnitPrice to another field called Amount?

The best answer is, "Don't!"

Calculated fields belong in queries, not tables.


Calculated columns are part of life on a spreadsheet, but do not belong in a database table. Never
store a value that is dependent on other fields: it's a basic rule of normalization. Break the rule,
and you have to worry about how to maintain the calculation correctly in every possible
circumstance.

Ask yourself, "Would it be wrong if my field contained a value different from the
calculation?" If you answer Yes, you must not store the field. If the difference would be
meaningful, you do need the field.

So, how do you get the calculated field if you do not store it in a table? Use a query:

1. Create a query based on your table.


2. Type your expression into the Field row of the query design grid:
    Amount: [Quantity] * [UnitPrice]

This creates a field named Amount. Any form or report based on this query treats the calculated
field like any other, so you can easily sum the results. It is simple, efficient, and foolproof.

Well, almost foolproof: It is possible to have your calculated fields misinterpreted.

You want to store a calculated result anyway?


There are circumstances where storing a calculated result makes sense - typically where you
need the flexibility to store a different value sometimes.

Say you charge a construction fee that is normally an additional 10%, but to win some quotes
you may want to waive the fee. The calculated field will not work. In this case it makes perfect
sense to have a record where the fee is $0 instead of 10%, so you must store this as a field in the
table.

To achieve this, use the After Update event of the controls on your form to automatically
calculate the fee:

1. Set the After Update property of the Quantity text box to [Event Procedure].
2. Click the Build button (...) beside this. Access opens the Code window.
3. Enter this line between the Private Sub... and End Sub lines:
4. Private Sub Quantity_AfterUpdate()
5. Me.Fee = Round(Me.Quantity * Me.UnitPrice * 0.1, 2)
End Sub

43
6. Set the After Update property of the UnitPrice text box to [Event Procedure], and click
the Build button.
7. Enter this line:
8. Private Sub UnitPrice_AfterUpdate()
9. Call Quantity_AfterUpdate
End Sub

Now whenever the Quantity or UnitPrice changes, Access automatically calculates the new fee,
but the user can override the calculation and enter a different fee when necessary.

If you are concerned about how a user could enter the calculated total with this arrangement, see
Enter text in calculated controls.

What about Calculated fields in Access 2010?


Access 2010 allows you to put a calculated field into a table, like this:

Just choose Calculated in the data type, and Expression appears below it. Type the expression.
Access will then calculate it each time you enter your record.

This may seem simple, but it creates more problems that it solves. You will quickly find that the
expressions are limited. You will also find it makes your database useless for anyone who needs
to use it in Access 2007. Instead of reading the data, they will get a message like this:

44
Even more serious, the calculated results are not reliable. If you change the Expression after data
has been entered into the table, the existing results may not be updated correctly (through new
records are edits are updated), so you cannot rely on the results. A compact/repair does not
recalculate, so there is no obvious way to repair the bad results.

Since you cannot index calculated fields anyway, there is no performance benefit to be gained
from using them. You are violating fundamental rules of data normalization for no good purpose.
We recommend you use queries for calculated fields, just as in previous versions. 

10 tips for securing a Microsoft Access database


A few best practices can go a long way toward protecting your Access data from careless or
overly curious users. Here are some simple ways to add a few layers of security to a database.

A few best practices can go a long way toward protecting your Access data from careless or
overly curious users. Here are some simple ways to add a few layers of security to a database.

Data is an asset. Therefore, data is money. Even if the data isn't directly involved in the exchange
of goods or services, it still has value. That's why it's so important to protect it. The operating
system employs the best security, but it's not always practical, especially on a stand-alone
system. In the Access world, the next best thing is the user-level model (which Access 2007
doesn't even support). User-level security is complicated and deploying it takes time and special
knowledge.

When the best security measures aren't possible (or necessary), you can implement less robust
security measures to protect your data and design. Just keep in mind that the following tips
prevent accidents by honest users and the mildly curious with enough knowledge to be
dangerous. These tips don't offer reliable security, in and of themselves. But by combining a
number of them, you can get a level of security that's better than no security at all.

Note: This article is also available as a PDF download.

1: Check and reset settings using the AutoExec macro

45
Use the AutoExec macro to check and reset security options that processes might have changed during
the last work session. AutoExec is a special macro that executes when the database opens. To create an
AutoExec macro, simply name a new macro AutoExec. For instance, the macro in Figure A runs a user-
defined function named Startup(), which does the real work of checking and setting security properties
before the user can go to work. The macro just executes it.

Figure A

Use the AutoExec macro to initiate important security settings.

2: Hide the Database window


Startup options, shown in Figure B, let you determine specific behaviors when the database opens. Two
of these features lend a hand toward securing your database a bit:

 Display Database Window: Deselect this option, and the next time someone opens the
database, Access will hide the Database window. Users won't have immediate access to any
objects.
 Use Access Special Keys: Deselect this option to inhibit the use of F11 to unhide the Database
Window.

46
Figure B

Set startup options to hide the Database window.

Both settings work together. If you don't deselect the Use Access Special Keys option, users can
press F11 to unhide the Database window.

To access the Startup options, choose Startup from the Tools menu. In Access 2007, click the
Office button and then click the Access Options button. Select Current Database in the left pane
and you'll find these options in the Application Options section. Access 2007 doesn't have a
Database window, but you can hide the Navigation Pane in a similar manor. That option is in the
Navigation section just below the Application Options section.

Deselecting the Display Database Window option will also disable the Startup command. Users
can bypass all these options by holding down the [Shift] key while opening the database. That
trick's handy for you, but leaves the database vulnerable to anyone else who knows about it. A
user can also import objects into a blank database to bypass startup settings.

3: Bypass the bypass


You can use the interface to hide the Database window, but the [Shift] key bypass renders the
database vulnerable to anyone who knows about it. That's why there's a bypass to the bypass...
seriously. To close the bypass crack, set the AllowBypassKey property to False when the
database closes. Automate this process by calling the following code from a close task — just
which task is up to you:

Public Sub SetStartupOptions(propname As String, _


propdb As Variant, prop As Variant)
  'Set passed startup property.
  Dim dbs As Object
  Dim prp As Object
  Set dbs = CurrentDb

47
  On Error Resume Next
  dbs.Properties(propname) = prop
  If Err.Number = 3270 Then
    Set prp = dbs.CreateProperty(propname, _
     propdb, prop)
    dbs.Properties.Append prp
  End If
  Set dbs = Nothing
  Set prp = Nothing
End Sub

When you call the procedure, be sure to pass the appropriate startup option text, as follows:

Call SetStartupOptions("AllowBypassKey", dbBoolean, False)

After setting this property during the close process, the database will ignore the [Shift] key
bypass if one of your users is wily enough to try it.

Use this to set any of the startup properties. For instance, this call hides the Database window:

Call SetStartupOptions("StartupShowDBWindow", dbBoolean, False)

You can set options when you close or open the database with one exception. The
AllowBypassKey property must be set when you close the database. Be sure to set a reference to
the Data Access Objects library (DAO). Otherwise, this procedure will generate a reference
error. (There's bound to be an ADO alternative, but DAO is efficient in this area.)

It makes sense that anyone who knows about the [Shift] key bypass (#2) might also know how to
enabling the [Shift] bypass by resetting the AllowBypassKey property to True. If this is the case,
you'll have to apply workgroup security to restrict access to this property to the administrator.
Someone can try to reset the property, but the effort will fail unless that person is working
through the administrator login.

4: Split the database


A split database is easier to protect than a single database that contains the data and the interface
objects. By split, I mean having a database that stores tables and relationships in one database,
known as the backend, and the interface objects in a second database, known as the front end.
The two databases communicate through linked tables. Here's why all that's important: Users in
the front end can't alter the design of tables in the backend. (There are many reasons to split a
database, but this discussion is about just security.)

To split a database, choose Database Utilities from the Tools menu. Then, select Database
Splitter. The wizard will walk you through the process. In Access 2007, click Access Database in
the Move Data group on the Database Tools tab.

5: Avoid Compact On Close

48
Anybody who uses Access knows that compacting regularly can mean the difference between a
successful application and a bomb. Compacting makes a copy of the file, overhauls its objects,
deletes temporary data, and rearranges the fragmented pieces on your disk. In short, compacting
keeps a database in good working order.

Starting with Access 2000, Access offers the Compact On Close option, which compacts the
database automatically when the last person closes it. Unfortunately, the process sometimes
forgets to clean up after itself. If you find temporary files, with names like db1.mdb, db2.mdb,
and so on, in the same folder as your database, they're most likely a byproduct of the compact
feature.

Those leftover files can be a problem. Anyone who has access to the folder has access to the
temporary files, and that's a breach in security. There are two ways to protect your database:

 Check regularly and delete any temporary files (but this isn't really a practical or even effective
solution).
 Don't use the Compact On Close feature. This is the best way to protect a database from this
particular vulnerability. Compact the database manually. You can even train someone to do it.

6: Hide objects — a subtle form of protection


It's a good idea to hide objects — tables, queries, forms, and so on — from users. Doing so won't
protect these objects in the traditional sense, because if the user can find them, the user can alter
them. However, if the user doesn't know the objects exist, chances are the object will be safe
enough from users who have no wish to break the database or steal data. Hiding objects simply
keeps them safe from the mistakes an honest user might make, without malice or intent. To hide
an object in the Database window (or Navigation pane), right-click it and choose Properties.
Then, check the Hidden Attribute option.

Now, let me stress one more time (to save you the time of complaining) that someone who
understands Access can unhide these objects just as easily as you can hide them. To view all
hidden objects, you simply choose Options from the Tools menu, click the View tab, and then
select the Hidden Objects option in the Show section. (If you select an object's Hidden attribute,
but the Database window still lists it, the Hidden Objects option is probably selected.) In Access
2007, right-click the Navigation pane's menu bar, select Navigation Options, select Show Hidden
Objects, and click OK.

As you can see, hiding an object doesn't secure it; it just stores it out of sight (and out of mind).
If you use this technique, remember that hidden modules are still visible in the Visual Basic
Editor (VBE). In addition, consider hiding only the most important objects. A snoopy user who
finds an empty Database window is apt to go looking. You can't import hidden objects, which
can be problematic if the import process is legitimate.

You can programmatically hide an object using VBA code, as follows

CurrentDb.TableDefs(tablename).Attributes = dbHiddenObject

49
In older versions (through 2000), assigning the hidden attribute to a table via code is problematic
because Access flags the table as temporary. Then, during the next compact, Access deletes it,
along with your data! Avoid this option if you're working with an older version.

7: Use error handling to protect code


When code generates an error, VBA displays an error message similar to the one shown in Figure C. If a
user gets that form and clicks Debug, he or she will be staring right into the heart of your application —
the module that contains the error-generating code in the VBE. At this point, the user has full access to
your code. Most likely, the user won't know what to do and will call you for help. On the other hand, in a
panic (or with a little mischief) the user could wipe out all of your code.

Figure C

Users can access your code by clicking Debug.

During the development stage, the ability to access code quickly is a timesaving feature. In a
production database, it's a disaster waiting to happen. As a matter of good practice, all
procedures should have some level of error handling to inhibit the generic message and its
Debug button.

8: Password-protect the database


A password is like a pin number — without it, you can't access the database. Once you've
password-protected a database, any user who wants access must know the password. There are
third-party products that can crack a password-protected database, so this protection isn't
foolproof, but it's an adequate tool nonetheless. To password-protect a database, do the
following:

1. Open the database in Exclusive mode by choosing Open Exclusive in the Open dialog box, as
shown in Figure D.

50
2. Choose Security from the Tools menu and then select Set Database Password.
3. Enter the password twice.
4. Click OK.

Figure D

Open the database exclusively to password-protect it.

The owner of the database can remove the password as follows:

1. Open the database in Exclusive mode.


2. Choose Security from the Tools menu and select Unset Database Password.
3. Enter the password.
4. Click OK.

You can also password-protect your VBA modules (code) as follows:

1. Choose project Properties from the Tools menu (in the VBE).
2. Click the Protection tab.
3. Check the Lock Project For Viewing option.
4. Fill in the two password fields (using the same password, of course).
5. Click OK.

Password protection is better than no password at all, but it won't stop someone with the right
tools and a little time.

9: Convert to mde or accde format


Access offers a security feature in the guise of a file format: mde and accde (in Access 2007).
This format is an execute-only version of the database. That means users don't have access to the

51
code via the VBE, nor can they make design changes to objects. This format protects the validity
of your design (mostly) but it doesn't protect the data. (Be sure to keep a copy of the original
mdb/accdb file for upgrades and other modifications.)

This format has it issues, as you might suspect:

 Use this format for the front end of a split database. Don't use it to secure the backend or a
stand-alone database. If you do, you'll have to transfer all the data into a new database every
time you upgrade the front end.
 This format doesn't protect tables, queries, macros, relationships, database properties, or
startup options. <groan>

To convert a front-end database to the mde or accde format, do the following:

1. In Access XP and earlier, choose Database Utilities from the Tools menu and then select Make
MDE File. In Access 2007, click Make ACCDE in the Database Tools group on the Database Tools
tab. (You can't convert Access 2000 format or earlier.)
2. In the resulting dialog box, specify a folder and name for the new database and click Save.

10: Password-protect the system


You can't expect users to never leave their system. And while the system's unattended, your
database is vulnerable — especially if users tend to leave the database open during breaks, lunch,
and so on. You can set rules, but users forget.

One way to protect against intrusion is to password-protect the system's screensaver feature.
Windows' screensaver kicks in when the system sits idle. If you password-protect the feature, the
user must enter a login password to regain access to the system. Under Windows XP, you can
password-protect the system's screensaver, as follows:

1. Click Start and choose Control Panel.


2. Double-click Display.
3. Click the Screen Saver tab.
4. Select a screensaver (if necessary).
5. Set a Wait time — that's up to you.
6. Check the On Resume, Password Protect option.
7. Click OK.

After the screensaver kicks in (step 5), a user must enter a login password to regain access to the
system. If the database is networked, the administrator can set up this protection for everyone
who uses the database, saving you the trouble of visiting individual computers.

52
Save a calculated result in a table using a query (Access 2007)?
I have a form of multiple project sites where one of the fields is labelled "Project
Start Date". I have another field in the form labelled "Projected Project Finish Date".
Both fields are stored in a table labelled "General Project Info" (well, at least that's
the source of the information for the form come from).

I could manually fill in the Proposed Project Finish Date by adding 10 days to the
Project Start Date, but I would like to make it a calculated field, i.e once someone
puts in the Project Start Date Access automatically calculates the Proposed Project
Finished Date.

I am aware you can use a query to calculate this: New Query-->Include Project ID
up vote 1 and Project Start Date fields, then make the third field--> Proposed Finish Date:
down vote DateAdd("d",10,[Project Start Date]). This produces a query result which has a
favorite column with all the sites, a column with the Project Start Date and a column with a
date that is 10 days later. Perfect. But, how do I store those new results in my existed
General Project Info table and have them appear in the form? I'm obviously a
beginner and am missing something.

Thanks for any help in this matter.

Oh, I am using Access 2007.

ms-access-2007
asked Jan 8 '13 at 17:23
shareimprove this question
user1958930
add a comment

1 Answer
active oldest votes
up You can use the After Update event for Project Start Date on your form to update the
vote 2 Project End Date control to Project Start Date + 10, but if the answer is always + 10, why
down store the date at all? Just use your query to show the end date.
vote
Private Sub StartDate_AfterUpdate()
Me.EndDate = Me.StartDate + 10
End Sub

Or

SELECT StartDate, StartDate + 10 As EndDate FROM ATable

Edit

53
To add an After Update event, use the property sheet in form design view. Select [Event
Procedure] and then click the three little dots. It will open up the code window and you
can add code into the event. You will need to use the proper names for you controls, but if
you type Me., intellisense will help you along with names of properties, methods and
controls.

How do I use the query results to display the proposed date? I can't create a text box
     on the form and use the query as my control source, can I? – user1958930 Jan 8 '13
at 19:40
No, but does the user need to interact with the EndDate? If so, use option 1 above, if
not, just display the startdate + 10 in a textbox by setting the control source to
    
=StartDate+10. A textbox set in this way is not editable by the user. It all depends on
whether the date is always startdate + 10, or not. – Fionnuala Jan 8 '13 at 19:43
Thanks for the help by the way, if forgot to mention that in my last message. Back to
the issue: The user doesn't necessarily interact with the proposed finished date. It's
merely a guideline for the user to plan and schedule other things. So, I might just use
     the textbox solution with StartDate+10. I am actually not sure what the other solution
means. Where am I suppose to enter the "Private Sub StartDate_AfterUpdate()...."
and how is this different from the first solution? Clearly a beginner here, sorry.
– user1958930 Jan 8 '13 at 20:23
We all start somewhere. You can look at you form in design view and select the
    
property sheet for the start date control. See above. – Fionnuala Jan 8 '13 at 21:09

How to create calculated fields and totals rows in tables

Calculated fields and totals rows let you perform calculations with the data in your tables.
Calculated fields perform calculations using data within one record, while totals rows perform a
calculation on an entire field of data.

54
Calculated fields

When you create a calculated field, you are adding a new field in which every row contains a
calculation involving other numerical fields in this row. To do this, you must enter a
mathematical expression, which is made up of field names in your table and mathematical
symbols. You don't need to know too much about math or expression-building to create a useful
calculated field. In fact, you can write robust expressions using only grade-school math. For
instance, you could:

 Use + to find the sum of the contents of two fields or to add a constant value (such as +2 or +5)
to a field
 Use * to multiply the contents of two fields, or to multiply fields by a constant value
 Use - to subtract one field from other, or to subtract a constant value from a field

In our example, we'll use a table containing a month's worth of orders. The table contains items
listed by sales unit: single, half-dozen, and dozen. One column lets us know the number sold of
each sales unit. Another lets us know the actual numerical value of each of these units. For
instance, in the top row you can see that seven dozen fudge brownies have been sold, and that a
dozen equals 12 brownies.

To find the total number of brownies that have been sold, we'd have to multiply the number of
units sold by the numerical value of that unit—here, 7*12, which equals 84. This was a simple
problem, but making this calculation for each row of the table would be tedious and time
consuming. Instead, we can create a calculated field that shows the product of these two fields
multiplied together on each row.

To create a calculated field:

1. Select the Fields tab, locate the Add & Delete group, and click the More Fields drop-down
command.

55
2. Hover your mouse over Calculated Field, and select the desired data type. We want our
calculation to be a number, so we'll select Number.

3. Build your expression. To select fields to include in your expression, double-click the field name
in the Expression Categories box. Remember to include mathematical operators like + or -.
Because we want to multiply our two fields, we put the multiplication symbol (*) between the
two field names, which we selected from the Expression Categories box.

56
4. Click OK. The calculated field will be added to your table. If you want, you can now sort or filter
it like any other field.

For more examples of mathematical expressions that can be used to create calculated fields,
review the Arithmetic Expressions in the Expression Builder dialog box.

57
Totals rows

The totals row lets you add up an entire column of numbers, just like in a ledger or on a receipt.
The resulting sum appears in a special row at the bottom of your table.

For our example, we'll add a totals row to our calculated field. This will let us know the total
number of items sold.

To create a totals row:

1. Select the Home tab, then locate the Data group.


2. Click the Totals command.

3. Scroll down to the last row of your table.

58
4. Locate the field you want to create a totals row for, then select the second empty cell below it.
When a drop-down arrow appears, click it.

5. Select the function you want to be performed on the field data.

6. Your field total will appear.

59
60

Вам также может понравиться