Anda di halaman 1dari 155

http://www.tech.dmu.ac.

uk/Access/Example%20datab
ases.htm#Creating%20custom%20primary%20keys

MS Access and VBA


Last updated 26/03/11

Please email the site owner with any comments, errors that you have found here, ideas
for new items, etc.

This page is an attempt to bring together various things that may be of interest and help
to students studying on modules that use MS Access and VBA as the implementation
and programming software, and to students using MS Access and VBA for Project work
or on Placements.

Many of the items here have arisen from Project and Placement work.

Please note that I am no longer able to provide one-to-one help for Project or
Placement students.
If you hit technical problems during these activities then you should turn to your Project
Supervisor or your Visiting Tutor for help and advice.

List of contents
Retirement!
Using Access 2010

Using Access 2007

Textbooks

VBA Trainers and other Documents

Table Planning Sheet


Frequently Asked Questions

New features for Access 2000

Example databases

Advice for Report Design

Links to other websites

Crash Course in Access Basics

VBA Trainers and other Documents


There are two VBA Trainers available for students to obtain free of charge. These were
written due to an apparent lack of textbooks taking a 'problem solving' approach to
database programming. At DMU Leicester these are available from the CSE Student
Advice Centre. Students at Associate College Centres should enquire of their tutors.
Electronic copies are now available as PDF files, following a request from a student, so
that students who have left, are on placement or have simply lost their copy of the
Trainer can access the documents from outside DMU.

New (and improved, I hope) versions of both Trainers are now (August 2005)
available from the Student Advice Centre at LE.
These have more detailed explanations and increased content from the previous
versions, plus exercises and suggested test plans, and have both been upgraded to
Access 2002 from Access 97 (and DMU now has Access 2003, but all code appears to
work just as well in 2003).

I have no plans to produce versions for Access 2007 or Access 2010. You may find the
information on the Using Access 2007 and/or Using Access 2010 pages useful for some
of the differences between the old and new versions of Access.

Click here for a starter database: Chelmer Leisure with tables, data and three forms.
This may save you some time setting up to use the Trainer.
If you are using Access 2010 then use this version of the database instead. The
original version will give a 'missing or broken reference' error - see VBA FAQ 43.

Items covered are summarised in the table below.

click on these links for details of additions, error corrections, Access 2007 problems,
etc:
Getting Started with VBA latest entry 4th August 2008, section 7.6.2.
Further VBA latest entry 4th August 2008, section 1.

See also:
Differences between VBA in Access 97 and Access 2000
Different ways of doing things in VBA
Trainer content
Getting Started with VBA (v5.1) Further VBA (v5.0)
Various basics and the two Help systems. Password protection (Access simple
Creating and using a simple function. method; setting-up your own login table;
Using the Debugger; compiling code. accessing network log-in ID)

Creating and using message and question


Error trapping and custom error messages
procedures.
Documenting your code. Using Data Access Objects [DAO]
Viewing, Editing, Saving, Adding and (Database and Recordset Objects; various
Deleting records (data maintenance) via a methods; adding to a combo box at run-
form, using event code behind command time; creating own Domain Aggregate
buttons. Functions).
Using labels to simulate raised/sunken
command buttons, or using labels to look Worked example showing a further method
like hyperlinks. of making bookings for the Chelmer Leisure
database, via a 'diary day page' form. This
Automatic calculations on forms (using a uses DAO code and arrays. The form
formula in a textbox; highlighting items; a shows the Booking No for each booked
procedure to calculate a person's age from slot.
their date of birth).
Field, form (record) and parameter
validations.
Searching for, and filtering, records, with
counts.
using Combo and List boxes on forms
(properties, changing contents at run-time,
etc).
Using main and sub menus for data
maintenance etc. Dynamic date and time
on forms.
Reports (events; changing fonts; totals,
'empty' reports; changing the sort order at
run-time; using query criteria; suppressing
detail lines).
Embedded SQL, showing how to use
embedded SQL to add, update and delete
rows from a table, and how to create and
drop tables.
Using tab controls on forms.
Importing and exporting spreadsheet data.
Backups; compacting; linking to an external
database; MDE files, Startup options, etc.
Using the WITH statement.
Worked examples of booking procedures
(member booking for a single court; class
bookings for a fixed day/time over a period
of several weeks; using a 'diary page' grid
with a Crosstab query). All these examples
use Outer Join queries.
Appendices, giving information on: events
overview; basic programming concepts;
SQL overview; The Forms Collection; built-
in functions overview; list of useful DoCmd
methods, etc.

Electronic Copies:

Getting Started with VBA - Cover


Document

Further VBA - Cover


Document

List of errors, extras, etc.

Getting Started with VBA version 5.1, July 2005

25th October 2005 - extra


Section 1.8 Documenting your code.
I have just been playing around with JPadPro and have discovered that this looks as
though it will print the code in colour (assuming that you have a colour printer, of
course).
Do the following:
1) In your Access database, open your code window for the module that you wish to
print, highlight all the VBA code and copy it.
2) In JPadPro, open a new VBScript file and paste your VBA code in.
The blue (keywords) and green (comments) font colours appear to be used in the same
way as with VBA in Access.
String literals are shown in red font.
The rest is in black font.

7th February 2006 - extra (and reference to section 6.3 added 4th July 2008)
Section 3.3 Validations
The examples shown here are all for textbox fields. However, it may be that the field
you want to validate is a combo box. If you set the combo box LimitToList property to
Yes then Access will validate the user entry against the list and will respond with an
error message of its own if the user enters some other value. If you want to replace this
Access message with a message of your own, and/or do something else (such as
disable a command button) then use the NotInList event for the combo box; control is
only passed to this event if the user has not chosen a valid entry from the list. The
BeforeUpdate event is not invoked if the entry is invalid, but is invoked if the entry is
valid or null.
Look at Exercise 4.2(c) on Crash Course in Access Basics for an example of using the
NotInList event to provide your own message etc. Note that the code to drop the list
down is not strictly necessary as Access will do that anyway.
Section 6.3 of the 'Getting Started' VBA Trainer shows how to use this event to add a
row to a lookup table, and there is further information about this lower down on this
page.

12th January 2007 - extra


Section 3.6 Using a list box to select records and change contents at run-time
The VBA Trainer shows how to do this after the user has entered all the search
characters into a textbox; the list box is requeried in the textbox AfterUpdate event.
The example database List Box Filter shows to change the list box contents with each
character entered into the textbox; this is much neater HCI.

10th November 2010 - extra


Section 5.6 Using a query criteria parameter at run time
If you are using Access 2010 then you need to be aware that the Calendar Control
object is no longer supported in Access. See VBA FAQ 43.

7th February 2006 - extra


Section 5.8 Suppressing Detail Lines
A better example than the one shown here could be for a report that is based on an
Outer Join query. Queries like this can result in blank entries for groups where there is
no data to be printed. See Exercise 6.5(c) on Crash Course in Access Basics for an
example of suppressing blank report detail lines for such a report.

4th June 2008 - extra


Section 6.3 Adding a row to a table
The simple example shown in this section is for a lookup table with just one field.
Many lookup tables have ID fields as well, to reduce space in the main data table and to
make changes to the lookup text simpler and easier to reflect throughout the main data
table; for example, a table for a list of company department names.
Section 6.6 (fig 6.6.2) shows how to add a row to a table with an AutoNumber key, but
many students miss the relevance of this for lookup tables with IDs.
So - suppose your Title lookup table is called tblTitle, and has an AutoNumber Primary
Key ID plus a field called Title. The only code change that needs to be made here is to
the SQL itself, which should now read:
strSQL = "INSERT INTO tblTitle (Title) VALUES ('" & NewData & "')"
This now specifies the name of the field of the table into which the value in NewData is
to be put. Access will work out the AutoNumber key value automatically.
The combo box RowSource SQL should be changed to ensure that the entries are
sorted in Title order (the default will be ID order).
For further information on the format of the SQL INSERT statement see Appendix G.4.
If you don't specify the target field names, then the statement should have data values
listed for every field in the same order as they occur on the table. If you want to put data
values in just some of the fields, then the field names need to be listed (comma-
separated) before the VALUES clause, with the data values in the same order.
The code for processing adding to lookup tables is the same in each case, so this would
suggest that a common procedure could (should?) be used. A suggestion is to code the
following in an Access module:
Public Function myComboNotInList(prmNewData As String, _
prmID As Boolean, prmTableName As String, _
prmFieldName As String, prmfieldDescription As String) _
As Byte
'add to a lookup table via a combo box
' the table can consist of just a single field, or a field plus an AutoNumber PK
'prmNewData = the value passed by Access to the combo box NotInList event
'prmID = True if the lookup table has an AutoNumber PK. False otherwise.
'the function then returns a value for the Response to be passed back to Access

Dim strSQL As String 'for the SQL INSERT statement

'first ask if the new data is to be added


If myYesNoQuestion("'" & prmNewData & "' is not in the list" _
& vbCrLf _
& "Do you want to add this " & prmfieldDescription & " to the list?") _
= vbNo Then 'not to be added
myComboNotInList = acDataErrContinue 'do nothing - user must choose again

Else 'new entry for table - prepare to add


If prmID = True Then 'table has an AutoNumber PK
strSQL = "INSERT INTO " & prmTableName & "(" & prmFieldName & ") VALUES ('" &
prmNewData & "')"
Else 'table has just the one field
strSQL = "INSERT INTO " & prmTableName & " VALUES ('" & prmNewData & "')"
End If
'now add the row to the table
DoCmd.SetWarnings False
DoCmd.RunSQL strSQL
DoCmd.SetWarnings True
myComboNotInList = acDataErrAdded 'tell Access new value now added to table
End If

End Function
Then all you need to do for the Title combo box is to code:
Private Sub cboTitle_NotInList(NewData As String, Response As Integer)
'see if new title needs to be added to the list
'uses common public function myCombo_NotInList
' which returns the response value to pass back to Access

Response = myComboNotInList(NewData, True, "tblTitle", "Title", "Title")

End Sub
And this makes it very easy to process any other lookups, as you have already done
most of the work! (Reusable procedures take a little more effort initially, but can save a
lot of time in the long run).

12th June 2008 - extra


Section 7.3 Importing/Exporting spreadsheet data
There is now an example database demonstrating this on the Example Databases
page.

13th October 2005 - clarification


Section 7.3.6 (d) Run-time error '2391': Field 'Fn' doesn't exist in destination table
'<name>'
If the message references 'Fn' (F1, F2 etc) then the spreadsheet column in error
may not have a name.
If the message references a name such as 'Course1' (instead of Fn), then this
could mean one of two things: (i) there is a column in the spreadsheet called
Course1 but no such column in the table; or (ii) there are two columns called
Course in the spreadsheet.
If you really can't work out where these extra columns are coming from, then
simply adding columns of the appropriate names to the table may allow the
spreadsheet to be read in OK. (Probably not the best way round the problem, but
it does sometimes appear to solve it, and it doesn't matter if there are unused
columns in the table).
You should also check to see if there are several used sheets in the file. If you do
not specify which sheet you want to read then it is assumed that you want to read
the first sheet.
17th June 2008 - extra
Section 7.6.2 creating MDE files
You might also like to look at the information at
http://www.databasedev.co.uk/microsoft-access-mde.html and
http://www.databasedev.co.uk/converting-ms-access-files.html for further info.
4th August 2008 - things are DIFFERENT in Access 2007...

30th March 2006 - extra.


Section 8.2.5 Using the IIF function in the CourtAvailability query
I forgot to mention that "Like '*' " will not select fields where the content is Null.
The code here works because [Lastname] always contains a value (the Required
property = Yes so that it cannot be left empty).
Depending on the purpose of the field, it could also be useful to set a default ("None" or
"N/A", for example). Examples of fields where this could be done are [Sporting Interests]
and [Occupation].

21st March 2006 - extra


Index: Error message, can't assign value
There should also be a reference to section 5.4 (see the second bullet in the section).

Further VBA version 5.0, July 2005.

3rd June 2008 - extra


Section 1 - password protection
This section discusses various methods of adding password protection to a database.
Project students seem to like adding login forms to their databases, but that's all they
do. A login form by itself is not much use - you need to allow the users to: change their
own passwords; have a procedure for forgotten passwords; database admin procedures
for adding/removing users and allocating initial passwords. The exercises at the end of
this section were intended to make you think about those issues and implement them
appropriately. There is a lot more to password protection than just a simple login form!
The data security issues are important, too...
4th August 2008 - Look at the information and links for how to restrict access to the data
and tables in your back end database on the Access 2007 page - the link for the Access
2007 Security Paper by Garry Robinson for MSDN looks especially useful. Note that an
Access executable file (MDE/ACCDE) does not prevent a user from seeing the data in
back-end database tables, or seeing where these tables are located.

19th February 2008 - Access 2007


Sections 1.4.3: Login filter problems
Some students have been having problems with the code when using Access 2007. It
seems to work with some students but not others.
Sometimes the filter would not find any matching records at all (this happened when I
tried running the code on my Access 2002 database with 2007). Sometimes it would
work if a correct login was entered first time, but not if a correct login was entered after
an incorrect one.
One student who had problems reported that the code worked on his home machine
with Access 2003 but not at DMU with Access 2007. He had created his database using
2003.
Changing the line:
DoCmd.ApplyFilter , "[LogInId] = forms![Chelmer Leisure Log-on Control]!txtLogin"
to
DoCmd.ApplyFilter , "[LogInId] = '" & txtLogin & "'" 'another way of saying the
same thing
seems to fix the problem; txtLogin is a field on the current form so can be referenced
directly.
Note the apostrophes (')and quotation marks ("), as this field has a String datatype.

I used this form filter method as it seemed pretty straightforward for students to use.
However, if you can't get it working then two other methods are to use (a)
DCount/DLookup or (b) Recordsets. With each of these versions you will not need a
bound form, but will read the information directly from the tables to look for a matching
login then to read and check the password. Once these are both correct then you will
read any name and access level and process these as required. These topics are both
covered in the Further VBA Trainer. DCount/DLookup are also used in the Getting
Started VBA Trainer.

Advice for report design


When considering producing a report from your database system, the first thing you
need to consider is "what is the purpose of the report?".

Many students produce simple reports, each from data from just one table, for no better
reason than that they are easy to do! Some reports are just lists of key identification
fields. These reports are often just a waste of time and paper.

It is normally best to create a query on which to base a report, rather than letting the
report wizard choose fields from different tables. That way you are in control and can
test the query before creating the report, and will find that it's also easier to change the
query later. You can check that all parameters are used properly by the query (most
good reports will need parameters).
Report Wizards are very useful for getting a basic report, but the report layout often
leaves a great deal to be desired (and Access 2007 seems markedly worse at layout
than Access 2003). You will be expected to customise the layout yourself.

Ask yourself:
What is the purpose of the report? (Don't start creating the report until you know
exactly what it is for!)
What fields are needed? and from what tables? (most reports will need data
from several tables)
Does the user want key fields or data? (e.g. student no or student name, or both)
Should the data be grouped? (This is often useful, and usually omitted by
students).
Should the data be ordered? (don't just list things in primary key order!).
Are totals or other calculations needed? (they usually are).
What is the most appropriate layout for the report? (Portrait, landscape?
Columnar (rarely) or tabular (more often)? Lines between sections? How is the information best
ordered on the page? - the wizard layout is normally pretty awful. Should groups be kept together
to avoid a heading on the bottom of one page and the detail at the top of the next page?).
How large is the report likely to be? (e.g. a Computing course may have
approx.120 students on a year; the Chelmer Leisure Centre could have thousands of members).
Does the report need a chart? (not always essential but can often provide useful
visual information).

Then draft out your report on paper so that you have a plan of what you intend to
implement. The draft should include the following items (not an exhaustive list), which
are all standard good practice for reports:
Organisation/Company name or logo in the report or page header
Report title in the report or page header
All parameter values in the report or page header. Use VBA code or the
forms collection to pick up parameter values from parameter dialog forms.
Headings, sub headings and column headings
Page numbers in page footer or header (or both) - page x of y is a useful
format.
Date of printing in page footer or header (or both)
An 'end of report' line, or (better) the total number of records printed plus
any other grand totals, in the report footer
Group totals - all groups.
Clear layout - note that a detail line can actually print over several physical
lines, e.g. address lines can be positioned underneath each other.
Good use of fonts (size, bold, underline, Italics, colour, etc) for headings,
sub headings, totals, etc, to highlight important items and make the report easy
to read. VBA code can be useful here.
If you have a column that has the same value for all entries in that section
or sub section, then the value should be in a heading!
What the report should look like if there is no data to be printed ('empty
reports' are discussed in the Getting Started VBA Trainer).
Charts should have a title, and the axes should be labelled.
There is information about layout, using parameters and VBA for reports (including how
to cater for an empty report) in the Getting Started VBA Trainer and the Crash Course
document.

The Multi-Purpose example database shows how to use parameters (noting the
parameter values on the report header) and change some settings (sort order and text
colours) at run-time.

There are some example reports at http://www.databasedev.co.uk/reports.html.

Other websites
If you find any useful links please email the URLs to the site owner - thanks

Matthew Dean's website

Sites for Excel VBA

VBA Tutor

Another site that you may like to look at (recommended by a Placement student) is
http://www.mvps.org/

My thanks to Bob D at Drexel University, Pennsylvania, for recommending the following


links:
Converting Access databases to/from MySQL
http://www.softcities.com/Access2MySQL-Pro/download/10866.htm
Building a Database-Driven Web Site Using PHP and MySQL
http://dev.mysql.com/tech-resources/articles/ddws/ and
http://www.php.org/forums/
MS Access How-To Articles (this looks really useful! - lots of Q&A)
http://www.kayodeok.btinternet.co.uk/favorites/kbofficeaccesshowto.htm

My thanks to more people for the following links:


Matthew Dean for the link to http://www.tek-tips.com/
There is a VBA FAQ page at http://www.tek-tips.com/faq.cfm?pid=705
Two students on CSCI1403 for http://www.techonthenet.com/access/

Other sites that look useful:


http://www.access-programmers.co.uk/
http://www.mvps.org/access/resources/othersites.htm
http://groups.google.com/group/comp.databases.ms-access/topics
The links below were taken on 4th January 2001 from Nigel Roberts's old site for the
year 1 HND database module.
Access 2000 conversion to Access 97
How to convert Access 2000 databases to Access 97 no longer available?
MS Access version of Library Database
library.zip
Online MS Access Trainers. Useful resources to learn more about MS
Access - these are all useful tutorials
1. Microsoft Access '97 Tutorial - Prof. Holowczak
2. http://www.craneis.co.uk/access/
3. http://north.matc.edu/access/lectures.htm needs password (is this new?)
4. http://cru.cahe.wsu.edu/training/Access97/
VBA
MS Access 97 for Windows 95 VBA Programming (very detailed)
Access BASIC Tutorial (Simple overview)
Various links to other institutions on database modelling
CONCEPTUAL DATA MODELLING CONCEPTS
Data Dictionary and Entity Modelling
Data Modelling Finding the Perfect Fit
Entity relationship modelling no longer available?
Entity-Relationship Modelling slides
ENTITY-RELATIONSHIP MODELLING

Table Planning Sheet


Click here for a copy of the Table Planning Sheet.

It is always advisable to plan things on paper before implementation. Use of this sheet
will help you think carefully about your tables, will save you time in the labs setting up
your tables and should reduce the likelihood of you having to make changes later
because you missed something out!

'Crash Course' in Access basics

The document linked here (This version posted 21/8/2006) has been written for revision
lab sessions for a year 2 Project module, as a summary of some basics of MS Access
and VBA that are required for that module. It assumes that readers do have some
knowledge of how Access works and how to use it. For those of you completely new to
Access, see Textbooks.

The starter database is the one linked in the VBA Trainers section.
This link is for an SQL Trainer used on a year 1 module.

All these documents are based on the McBride Chelmer Leisure scenario (see
Textbooks link above)

A Table Planning Sheet is linked here.

These documents are posted here for staff, students and for anyone else who may find
them useful.

Retirement!
I am due to retire at the end of April 2011.
It is planned that this site will then be hosted on the Faculty's web pages, with a
redirection from here to there.
This site is unlikely to be updated any further unless one of my colleagues decides to
take it over.

Mary Spence, February 2011.

Site Owner
The current site owner is Mary Spence who has now retired from DMU.
Using Access 2010
Last Updated Sunday April 17, 2011
home

This page is intended to report differences found in Access 2010 compared with earlier
versions, plus other information that may be of use.

The Faculty's labs will be using Office (and thus Access) 2010 from September/October
2010.

This version of Access is not such a radical change as Access 2007 was over previous
versions. It still uses the Access 2007 file format as the default format, and the interface
is still based on the ribbon (though some things have changed and are not in the same
places as before).

What's New
Items no longer supported
Calendar Control
Data Access Pages
Further Links
Problems
Run-time error when sending emails
Styles are out and Themes are in
Converting Macros to Code
Error when converting .accdb to .mdb
Possible error when using File Picker
Some other Links
My Access 2007 page
My FAQ page

What's New

Searching Access Help with "What's New" gives the following links (and several others
about specific topics):
1. http://technet.microsoft.com/en-us/library/cc179181.aspx Help says that this is
really for IT and database admin info - but I think it's also of use to developers.
Detailed discussion of various changes.
2. http://office.microsoft.com/en-gb/access/access-2010-features-and-benefits-
HA101809011.aspx Help says this link is for features, but its looks to me like
just a very general overview/advertisement.

Some new things that might be of interest:


Sharing a database on the web.
Export to .PDF or .XMS has been simplified (no longer needs add-in).
Ribbon File tab replaces the Office Button - known as the 'Backstage View'.
Uses VB 7.0 (previously VB 6.0).

Some items that are no longer supported (will give error message):
1. Calendar Control. The article at the first "what's new" link above suggests using
the date picker instead; this appears to the side of date fields on tables and date
format text boxes on forms. See also the document linked here for an
explanation of the error message Missing or broken reference to the file
'MSCAL.OCX'.
2. Data Access Pages (they worked in Access 2007 but now won't work at all). The
new web service enhancements in Access 2010 are intended to fill the gap.
3. See also the document attached here for a list of discontinued features.
4. And this link: http://blogs.msdn.com/b/access/archive/2010/01/09/access-2010-
deprecated-features-and-components.aspx

Problems:
1. Run-time error when sending emails. A previously-working (in Access 2000-
2003 and 2007, Access 2000 file format) database that used DoCmd.SendObject
to send emails crashed in Access 2010. See VBA FAQ 28.
2. Styles are out and Themes are in. When creating a new form or a new report,
previous versions of Access would give you a choice of Styles from which to
select. This was useful for legacy databases so that you could create forms in,
say, Access 2003 style, and use a common style for reports.
If you have a database with an Access 2000-2003 file format (i.e. a .mdb
database) then Access 2010 no longer gives you this option - you are presented
with a new form or report in Access 2010 layout, whether you like it or not!
It looks like Themes now replace Styles, but these only appear to be enabled (on
the Form/Report Design Tools on the Ribbon) if you are using an Access 2007
format (.accdb file extension) database.
I have not found this change mentioned in any Microsoft 2010 items that I have
looked at, nor do I have any idea why the change was made. The idea of
Themes looks a useful one, but removing the previous option of styles does not
seem particularly helpful if you are maintaining a legacy database and wish, or
need, to keep the pre-2007 file format.
I found a couple of websites that look to be useful in explaining how to use
Themes. These are:
http://blogs.msdn.com/b/access/archive/2009/09/25/access-2010-custom-
themes.aspx and
http://answers.oreilly.com/topic/1848-how-to-create-forms-in-microsoft-access-
2010/ .
This site http://allenbrowne.com/ser-43.html could also be useful for getting
common styles for forms and reports (I've not tried it out, but Allen Browne
http://allenbrowne.com/index.html has a very good reputation).
3. Converting macros to code. Starting with Access 2007, the form and report
wizards now generate macros by default for controls rather than VBA code. See
my Access 2007 page, then the link for 'Wizard Code'. In Access 2010 the option
for converting a form's macros to VBA is now on the Form Design Tools ribbon
(and presumably similarly for reports). However, this option doesn't work in
Access 2010! If you try to convert the macros you'll get an error message: "there
was a problem converting the macro". This looks to be a bug in Access 2010 -
see http://social.answers.microsoft.com/Forums/en-US/addbuz/thread/edebfb3b-
2ab2-4697-872b-d52b9bd0994a : "this behavior has been filed as a bug and is being
looked at by our development team", July 2010.
So - How to get round this problem? Some ways could be:
(a) Convert the .accdb database to the previous (.mdb) format. See Save a copy
of an .accdb file in the .mdb file format in Access 2010 Help. Then wizards will
create VBA code. However, if you are using new Access 2007/2010 features you
may not be able to convert to the earlier format. Even if you don't think you are
using anything new, you may be doing so without realising. The conversion will
then fail with a message saying that "This form or report contains changes
that are incompatible with the current database format". On my machine
Access then 'encountered a problem' and had to close. I deleted all the form
buttons and replaced them with non-wizard buttons and the conversion then went
OK (I subsequently realised that simply removing the '[embedded macro]' entry
from the relevant button event on the property sheet does the same thing and is
far simpler!). There may be other controls that you also have to delete/recreate; I
have also hit this problem with an image control. This method means you can't
use any new 2007/2010 features, of course, and that you now need to write the
button code yourself (see next option (b) below) or recreate the buttons in the
.mdb file this time with wizards to generate the code.
March 2011 It could be that form/report layouts are the cause of the
'incompatible' error mentioned above. My thanks to Dan Yedinak of Oregon,
USA, for drawing my attention to the discussion at
http://www.utteraccess.com/forum/combo-box-trouble-t1949853.html. I tried this
out with the database I was using before, found a form where the layout was
'stacked' (the one where I hit the above-mentioned problem with the image
control), removed the stacking and the conversion to .mdb was then fine. This
'stacking' was first introduced with Access 2007 and appears to have been
dropped from Access 2010 (see my Access 2007 page and the link for 'Forms
and Reports') - perhaps that's the reason for the above-mentioned bug. The
database I was using was originally created in Access 2007, and the Faculty
installed Access 2010 in the labs for 2010/2011.
(b) Code everything yourself from scratch - or don't use wizards that create
macros (but not sure how you tell which do and which don't...). This method
requires more coding, so you need to know what you're doing. Look at an old
database to see the format of wizard code for buttons, then simply copy the
format for each button you want. Or create a test .mdb database and use that to
generate wizard code which you then copy/paste to your .accdb database behind
a non-wizard control. March 2011 See VBA Wizard Code database on my
Example Databases Page.
(d) Resign yourself to the fact that you won't be able to convert the macros and
just put up with it. But you should still be able to code the bits that you want
elsewhere (to get at a code window, open the form/report in design view and
click on the 'code' icon - this will create a new code module for the form/report if
one didn't exist before, or open the existing one.. You just won't be able to add
your own code to wizard-generated code (which is a pity as this can often be
useful).
4. Possible error when using File Picker
The maximum length allowed for the .Title property of the File Picker seems to
be 127 bytes (worked out by trial and error - Access Help is far from helpful
here). This restriction did not seem to apply with Access 2007 (?).

Some other links:


http://www.addictivetips.com/microsoft-office/microsoft-office-access-2010-
whats-new/ rather general and limited overview.
http://accessjunkie.com/faq2010.aspx lots of FAQs for Access 2010.
http://www.accessmvp.com/JConrad/accessjunkie/calendars.html for various
calendar controls.
http://www.brighthub.com/computing/windows-platform/articles/59569.aspx
migrating from Access 2007 to Access 2010.
Using Access 2007
Last Updated Thursday March 24, 2011
home

This page is intended to report differences found in Access 2007 compared with earlier
versions, plus other information that may be of use.

The Faculty's labs have used Office (and thus Access) 2007 from September/October
2007.
Most of the Access functionality and VBA code should work as before, but the interface
is radically different. Project students will need to be aware of this and allow time to
familiarise themselves with the new interface.

Click here for a list of What's New in Access 2007. (summary - headings only)

Click here for a list of Access 2007 specifications.

When you start up a database there will be a message bar below the ribbon that states:
"Security Warning certain content in the database has been disabled". You will need
to click on the Options button and then choose 'Enable this content' in order to run VBA
code and macros. If you don't do this then clicking on buttons, for example, will not
work! You can use the Microsoft Trust Center to specify folders (and optionally
subfolders) that you trust - databases in these folders will then open without the Security
Warning.
There's a good explanation of how to do this at
http://www.towson.edu/adminfinance/OTS/trainingdoc/shr29-mso2007.asp . (Note -
Towson university, Maryland, USA owns the copyright to all materials at this link).
There's also information about this (and much else) at http://msdn.microsoft.com/en-
us/library/bb421308.aspx under the Enabling Executable Content in Your Databases
link,

Items below are in the following categories:


General
- overlapping windows
- embedded logos and attachments
- multi-valued fields
Wizard code
Forms and reports
Forms only
Reports only
Executable/MDE/ACCDE files
DAO (Recordset) code
Custom Menus
Other Links

General:

1. Instead of overlapping windows for


forms, tables and the like, objects are shown on tabs. If you want to change back
to the overlapping windows used in previous versions then you do this via
Access Options (click on the icon in the top left-hand corner then click on the
Access Options link at the bottom of the popup box).

2. Two new features are the ability to add logos (images) to forms and reports, and
to embed attachments (images, Word documents and the like) in a record.
These are very easy to use (there is now a new table field datatype for
Attachment) - just follow the instructions in Access Help, and experiment for
yourself by creating a table and a form based on the table, then attaching
images, documents, etc via the form.
While these features may be OK for a novice database developer for a small
personal database, I have my doubts about their suitability for larger commercial
databases (not to mention backups and the size limit that applies to student
personal areas on the University network). As the images and attachments are
embedded the database will grow very large very rapidly. There is a size limit to
an Access database of 2GB (look in Access Help for "Access 2007
specifications" - this is the 5th item in the list on my machine). This item says that
you can get round the size limit by employing multiple back-end databases - but
this seems a messy 'solution' to me.
Embedding files in this way can also cause problems if, for example, a company
logo changes. If the logo is embedded in all forms and reports then each of these
objects will need to have the logo file replaced. If the logo is linked in (thus the
file exists outside the database and is linked in when each form or report is
opened) then all that the user needs to do is replace the logo file with a new one,
using the same file name. Another example could be if attached documents
change - these would have to be re-attached for the database to have the latest
version. If they were linked then the database would always pick up the latest
version.
Look at the example databases page for 'Linking Images' and 'Opening Word
Documents' - these methods would normally be more suitable for project and
placement databases. For a project, you would need to justify any use of
attachments. Student projects (year 2 and final) should not normally use
this feature. Any use would have to be discussed and justified.
You might also find the discussion at http://www.access-
programmers.co.uk/forums/showthread.php?p=566993 useful.

3. Another new feature is that of multi-valued fields. These avoid novice database
developers from having to grapple with many-to-many relationships, but can also
limit the functionality of the database - and go against one of the basic rules of a
relational database. See the What's New document for details and my
comments. These fields should NOT be used in student assignments or
projects.
Perhaps this feature is intended for people who are not database designers (in
which case I think they should not really be trying to implement a database in the
first place...).
July 2008 - I've done some Googling to see what others feel about this new
feature:
(a) http://www.theregister.co.uk/2006/07/18/multivalued_datatypes_access/ -
excellent discussion (i.e. the writer agrees with me!) on why this feature should
not be used.
(b) http://office.microsoft.com/en-us/access/HA101492971033.aspx - Microsoft's
guide.
(c) http://www.databasedev.co.uk/multivalued-fields.html - databasedev's guide.
(d) http://msdn.microsoft.com/en-us/library/bb258183.aspx - Manipulate
Multivalued Fields With DAO
(e) http://allenbrowne.com/Access2007.html - views and known bugs.
(f) http://books.google.co.uk/books?id=61Ps8-
AU12IC&pg=PA232&lpg=PA232&dq=multi-
valued+fields+and+Access+2007&source=web&ots=gTy9wfRRQa&sig=auauHW
Z5rO7n02sl-TzEJxYuVhA&hl=en&sa=X&oi=book_result&resnum=9&ct=result -
someone else who doesn't like them.
(g) http://www.eggheadcafe.com/software/aspnet/30144866/multivalued-field-
functio.aspx - Q&A re porting this feature to Access 2003 (can't be done).
Wizard code:
1. If you create your database with a 2000/2002/2003 file format then you should be
able to port it between the new and previous versions of Access (which can help
if you have an older version on your home machine or want to ask a staff
member [who may well be using the previous version] for help).
2. If you create your database in an Access 2007 format the wizards will generate
macros rather than the code we have been used to. If you want to see/use the
code then there is a facility to convert macros to code - see the document
attached here. Note that the code is slightly different from 2003 and earlier
versions.
3. If you have created your database in an earlier format then you should still get
wizard code created as before, even if using Access 2007.

Forms and Reports:


1. There is a new 'feature' when creating wizard forms and reports - the fields
added are all set in a fixed grid (in a very simplistic and poor layout). In order to
move the fields around to get a decent design for your form or report (and you
will need to do this) you need to do the following:
(a) right-click on the control(s) you wish to move
(b) choose 'Layout' from the drop-down list
(c) choose 'Remove' from the second list.
March 2010 This feature seems to have been removed from Access 2010.

2. Using logos - see discussion under General above.

Forms only:
1. There may be problems with using the Forms Collection or DoCmd.ApplyFilter
(or when using them both together). See the information about Login Filter
problems in the code for the Further VBA Trainer.
2. It appears that the Access 2007 command button wizard generates the code for
a Close form button that uses the Dirty property. This can cause an error at run-
time - see Access FAQ 36 What does the message "You entered an
expression that had an invalid reference to the property Dirty" mean?

3. If you use the query design window to change the RecordSource for an object
such as a combo or list box, when you close the window you are prompted to
save the changes to the RecordSource. But in Access 2007 the changes made
do not seem to save (they do in earlier versions). So, go to the SQL window and
copy the SQL then paste it directly into the RecordSource property for the object.

4. April 2009 - a student has brought to my attention that Combo Box lists based on
a 'value list' can now be edited at run-time. The LimitToList property must be set
to Yes/True. See http://office.microsoft.com/en-
us/access/HA101130521033.aspx, the item headed "Edit a value list in Form
view". The article then goes on to describe how to switch this facility off if
required.
This new facility does not appear to need, or use, data in the RowSource
property of the combo box. It appears that the list is held elsewhere. Adding to
list items seems straightforward, however, it is possible to remove an item from
the list without getting an error message stating that data now fails referential
integrity!
My personal opinion is that Value List combos are best restricted to items that
are highly unlikely to change (Gender [Male/Female], for example) and the user
should not be allowed to edit them. Anything else, which will normally involve
data that is applicable to the application, should be held in a table and the combo
box should be based on the table, with referential integrity enforced. If the user is
to be allowed to add entries at run-time (not always desirable; it depends on the
data and the application) then this is best done using VBA, perhaps by the
method discussed in section 6.3 of the Getting Started VBA Trainer. Admin
facilities should be provided to edit and delete entries (the latter checking to see
if there is data that uses the value; DCount could be useful for this). If the user is
not to be allowed to add to the entry at run-time then this Admin facility would
also add new entries. Admin facilities may need to be restricted to certain users
(two possible methods are to use a separate database linked to the table in
question or via permissions at log-on).
Perhaps this is another of Access's new facilities for naive users that appear to
hide what's going on and why.

Reports only:
1. When running code by clicking on the report icon in the navigation pane you will
open the report in Report View and not all code events will fire up - this includes
the Detail Print event. You need to open the report in Report Preview to be able
to run all the code. (If you are opening the report from a preview button on a
form, all will be OK). I have tried looking through Access Help to see what the
difference is between Report View and Report Preview, but I can't find anything
there (Access help seems to get more unhelpful with every new release - it lists
loads of stuff you don't want and very little that you do).

2. See the document attached here for information about locating the sorting and
grouping information. this also mentioned on the What's New document.

3. It is now possible to save an Access report as a PDF file. See the document
attached here.
Executable/MDE/ACCDE files

This procedure works differently in Access 2007 from previous versions - now you
create an ACCDE file if you have an Access 2007 format database. See section 6 of
article at http://office.microsoft.com/en-us/access/HA102190051033.aspx .

Extract from: http://office.microsoft.com/en-us/access/HA100678311033.aspx


.accde This is the file name extension for Office Access 2007 files that are
compiled into an "execute only" file. This format takes the place of the .mde file
name extension that is used in earlier versions of Access.

An .accde file is a "locked-down" version of the original .accdb file. If the .accdb
file contains any Visual Basic for Applications (VBA) (Visual Basic for Applications
(VBA): A macro-language version of Microsoft Visual Basic that is used to program Microsoft
Windows-based applications and is included with several Microsoft programs.) code, only the
compiled code is included in the .accde file. As a result, the VBA code cannot be
viewed or modified by the user. Also, users working with .accde files cannot
make design changes to forms or reports. You create .accde files from .accdb
files by doing the following:

1. In Office Access 2007, open the database that you want to save as an
.accde file.
2. On the Database Tools tab, in the Database Tools group, click Make

ACCDE.
3. In the Save As dialog box, browse to the folder in which you want to save
the file, type a name for the file in the File name box, and then click Save.

July/August 2008 - I have just discovered, when running an Access 2002 MDE file
under Access 2007 that you can get at the Navigation Pane and see/change tables
(design and data!) and create/alter queries (even though I had removed these options in
the Access 2002 .mdb version).
By following the Access 2007 Security Paper instructions (see pages 4 to 8 of the
document) information can be hidden from casual users, but the author suggests using
SQL Server to protect data in the back-end database(s). I used the advice on pages 4
to 8 on my Access 2002 database using Access 2007, then transferred it to a machine
with Access 2002 to create the MDE - this now has various items 'hidden' as I wanted
when run under Access 2007. (Some staff here still have Access 2002-2003 on their
machines).
But I'm puzzled as to why Microsoft makes it so easy for a user to see the raw data
back-end tables from an MDE or ACCDE front-end...

4th August 2008 - some more links:


http://www.vb123.com/Toolshed/06_access/securitypaper2007.htm - Access 2007
Security Paper by Garry Robinson for MSDN. Shows how to hide objects on the
navigation pane so that non-technical users cannot see the data you wish to keep
hidden, plus a lot else about database security. This looks to be an interesting and
useful article.
http://www.jamiessoftware.tk/articles/runtime.html - Access Articles: Distributing A
Microsoft Access Application - up to 2003 only.
http://www.utteraccess.com/forums/showthreaded.php?Cat=&Board=53&Number=4963
38&Forum=f53&Words=runtime&Searchpage=0&Limit=25&Main=496338&Search=true
&where=bodysub&Name=33905&daterange=0&newerval=12&newertype=m&olderval=
&oldertype=#Post496338&bodyprev= - post discussing this topic for 2003.
http://office.microsoft.com/en-us/access/HA102190051033.aspx#Controlling - but
doesn't mention anything about changes to tables/queries or being able to see/change
the data.
You may also find the information at http://allenbrowne.com/ser-69.html useful.

DAO (Recordset) code

See VBA FAQ #25 on the Frequently Asked Questions page.

Custom Menus

previous versions of Access allowed you to create and edit custom menus (via Tools--
>Customise), which you could then set up as a new toolbar.

Access 2007 will allow existing custom menus to be used, but it does not appear
possible to edit these menus (!).

The following links may shed some light:


http://msdn.microsoft.com/en-us/library/bb258174.aspx
http://msdn.microsoft.com/en-
us/library/bb203849.aspx#OfficeAccess2007MigratingExistingApplications_Concl
usion
http://www.experts-
exchange.com/Microsoft/Development/MS_Access/Access_Coding-
Macros/Q_24247256.html
http://www.databasejournal.com/features/msaccess/article.php/3790286/Setting-
Up-Right-Click-Menus-for-Access-2007.htm
http://groups.google.co.uk/group/microsoft.public.access.modulesdaovba/browse
_thread/thread/5412a3dfc5524c89
I have recently (spring 2009) hit this problem with a legacy database. Fortunately I have
Access 2002 at home so could port the database to there to amend the menu, then re-
install the database where it is to be used. Judging by forums on the Internet I am not
the only one with this problem...

If you no longer have Access 2002 available then you may have to replace the custom
menu by a more conventional (form-based) menu of your own, and set this to open
when the database opens. If you want to simulate the way the custom menu worked
then you might like to see the database linked here. A nicer method could be to use
combos or list boxes, but I haven't worked out how to do that. Added 22/6/2010.

A link to various other sites that may help with creating custom menus on the ribbon:
http://accessjunkie.com/faq_30.aspx added 11/8/2010.

Other Links
Some links here that I have discovered. Please email the site owner if you find others
that could be useful.
1. http://allenbrowne.com/Access2007.html. - "Microsoft Access Tips for Serious
Users" - very useful for all sorts of things!
2. http://accessjunkie.com/faq2007.aspx - "This page presents answers to some of
the most frequently asked questions concerning Microsoft Office Access 2007.
These questions are loosely organized by category."
3. http://blogs.msdn.com/access/archive/2007/12/18/access-2007-tips-and-tricks-
from-the-access-team.aspx - "Access 2007 tips and tricks from the team"
4. http://msdn.microsoft.com/en-gb/library/bb905409.aspx - "Developer
Considerations for Choosing File Formats in Access 2007"
Various MS Access and VBA textbooks
Last updated 26/03/11

home

Some Access 2007 books that I have come across that you might like to explore
further:

Reviews of various books can be found at


http://blogs.msdn.com:80/access/archive/2007/02/28/access-2007-books-list.aspx

"Pro Access 2007" By Martin W. P. Reid - preview of sample pages at


http://books.google.co.uk/books?id=61Ps8-AU12IC and there's a review at
http://hubpages.com/hub/Pro-Access-2007

"Brilliant Access 2007 Pocket Book" by S Slack -


http://www.pearsoned.co.uk/Bookshop/detail.asp?item=100000000243677

Alison Balter's Mastering Microsoft Office Access 2007 Development (Kindle Edition) -
good reviews at http://www.amazon.com/Alison-Balters-Mastering-Microsoft-
Development/dp/B00142KQ7A/ref=dp_kinw_strp_1/103-1930685-1651808

Special Edition Using Microsoft Office Access 2007 (Kindle Edition) by Roger
Jennings - good review at http://www.amazon.com/Special-Using-Microsoft-
Office-Access/dp/B000RH0DNU/ref=pd_sim_kinc_2

Access 2007 VBA Bible: For Data-Centric Microsoft Office Applications (Kindle
Edition) by Helen Feddema - no review at http://www.amazon.com/Access-2007-
VBA-Bible-Data-Centric/dp/B0014JR2IY/ref=pd_sim_kinc_1

March 2008 - I am no longer teaching database design and implementation to


beginners so have not explored books using Access 2007.
Essential for CSCI1403 (module last ran in 2006/2007)
Further Reading
All of these should also be in the library.

DMU LE students can also obtain copies of some VBA Trainers to help them with
learning VBA for MS Access.

Essential:
Access 2000 Further Skills, Smart Guide series
Nat McBride
ISBN 0-8264-5648-0
Published by Continuum, 2001 - sold summer 2003 to Thomson Publishing
Services
price approx. 11.99. (October 2005)

Click here for a copy of an MS Excel data file for the database table data. use
File-->Get External Data to import the data. The file is Excel 97 and imports OK
into Access 97 and 2000-2003. Added 30/9/2004 as several students are unable to access
the Blackboard CSCI1403 website in week 1 2004/2005.

Previous students recommended the earlier (Access 97) version of this textbook. It has the
advantage of being reasonably priced and of taking students gently through the steps needed for
the basic functions of the software. However, the Access 2000 version has several irritating
points:

It won't stay open on a desk

It has several errors - see Click here for list of known errors and omissions

It has a 'read then do' format in many places. Students often (and quite reasonably) work
through the software while reading the book, then come to a 'task' that repeats what they
have just done, which they (understandably) find confusing. The book only intends sections
headed 'task' to be worked through with the software; the rest is to be read and then used for
reference as necessary.

Sometimes you are asked to do a task then not save the result. This annoys some
students, but is not as silly as it may at first seem, as it is just using the software to
demonstrate a point. However, there is nothing to stop you saving the result if you want - you
could think up a name of your own, or use the unit and task numbers.

We have passed on comments from previous students, and the list of errors, to the Publishers for
the next version of the book. If you have any constructive comments, or find any more errors,
please let us know, then we can post the information here for the benefit of all.

A copy of the database with just the tables and some initial forms is available on the
VBA Trainers page of this site.
Further Reading:
Data Analysis for Database Design (3rd edition)
David Howe
ISBN 0-7506-5086-9
Published by Butterworth Heinemann, 2001
price approx 22.00. (2001)

The Essence of Databases


F.D. Rolland
ISBN 0-13-727827-6
Published by Prentice-Hall, 1998

Microsoft Access/Visual Basic, Step by Step series


Evan Callahan
Published by Microsoft Press, 1995
price approx. 30.00. (2000)
Easy step-by-step approach to using VBA with Access. Doesn't cover a lot of
ground, but opens up the topic so that you should be able to work out more for
yourself. Recommendation by student

Access Database Design and Programming


Steven Roman
Published by O'Reilly
price approx. 25.00 (June 2001)
Overview of database design, queries and programming, homing in on the
important points only. Good complement to lectures - not a self-study book to
replace lectures! Recommendation by student

VB and VBA in a Nutshell: the Language


Paul Lomax
Published by O'Reilly
price approx. 21.00 (June 2001)
Good statement reference with examples. Recommendation by student

Running Microsoft Access 2000


John Viescas
Published by Microsoft Press, 1999
price 41.99 in 2002
Good overview of Access 2000 features, including: SQL; database design; some
VBA; publishing data on the web. Looks to be a useful reference book to
consolidate existing knowledge and see what (else) Access offers. Rather too
high-level (my opinion) for a year 1 set text. Written in an accessible style.
Recommendation by student

Using Access97
Roger Jennings, published by QUE.
Expensive (65!!) (2000)
Very comprehensive reference on Access features, but not too much on VBA.
Plus CD.

Access 97 Power Programming


F. Scott Parker, published by QUE. Recommended by Jennings - see above.
2000 version may also be available now?

Microsoft Office 97 Visual Basic Programmer's Guide


Advertised in Access Help. 2000 version also available.

Real World Microsoft Database Protection and Security


Garry Robinson, published by APress
ISBN 1-59059-126-7
43.00
Reviewed in BCS Computer Bulletin November 2004
Star rating **** (good)

Access VBA Programming for Dummies


Alan Simpson, published by Wiley
ISBN 0-7645-7411-6
16.99 in 2006
Assumes you know the basics of point-&-click Access, but does not assume that you
know about programming. There are websites that accompany the book.
The book is written in a nice friendly style but seems to have some fairly heavy topics
right at the start of the book. Chapters 2, 4 and 5 in particular may probably be better
used as references on a 'need to know' basis. Chapter 3 looks OK, then event code
proper starts with chapter 6. There is no reference that I can find for Option Explicit -
rather an odd omission. The Debugger is not discussed until right near the end - I think it
should come a lot nearer the start. It doesn't really come at VBA from a business
problem-solving point of view. On the plus side, it uses the newer ADO rather than DAO
for Recordsets.
My personal opinion is that the Step By Step book (or a 2000+ edition, if available) may
be better as a first introduction to VBA for Access for those of you who have no
knowledge at all of programming.
Copies for the library ordered December 2006.

Known errors and omissions in Access 2000 Further Skills Listed in page number
order
You may find it useful to note these in your textbook before starting your work. As I add
new errors to the list each year, I will date them, so that you can then spot which ones
are new for that (academic) year.
These errors apply only (so far) to the units used in module CSCI1403.

Please email the site owner if you find any more.

See also Access and VBA FAQ page

Unit 1
1. The opening windows for Access 2003 are not as shown in McBride. Click here
to see how to open Access 2003 and create a new database.
Unit 2

1. Pages 11 and 14, Unit 2. There are two task 3s

2. Page 11, Task 3. Reference to Fig 2.1 here should be to Fig 2.2 on page 12.

3. Page 12, Unit 2. The third item in the Membership Category table should read
Membership Fee, not Membership No.

4. Page 12, Unit 2, Fig 2.2. The diagram here shows how the tables are joined, but
it should be noted that there are several errors in the database design. The
classical approach via Entity-Relationship diagrams, Functional Determinancy
Diagrams and Table Types would not result in these tables. However, the design
is useful for demonstrating features of Access.

In particular, the Bookings table is poorly-designed:


o The Bookings and Classes tables both show a time field. These times would
appear to be for the same thing (booking time), so this may be an example of
data redundancy. So the next question is: which of the times should be
removed? It is a required field in the Bookings table, which seems logical, but the
attribute more naturally belongs to Class. Or is it that the Classes table holds
the normal time and day whereas the Bookings table holds the actual time and
day, which could be different.
o The structure of the Classes table would appear to be that it shows details of
regular classes except for the actual dates on which the classes run; e.g. a class
runs on Tuesday nights at 19.00. It may be better for the User if this table also
had the start and end dates and then the system would work out the individual
bookings, but this is probably beyond the capacities of the Access click and
point features and would require VBA code, which is beyond the scope of this
book. See the 'Getting Started' VBA Trainer section 8 for examples of using VBA
for Bookings.
o The Bookings table has a very weird layout it is trying to cater for both
Member and Class bookings in the one table, although both bookings are
different types. The foreign key fields of Membership No and Class No are not
required fields; they cant be, as the table should have just one or the other of
these fields. (In fact the table structure will allow you to enter neither or both for
any one booking! A Record Validation Rule could be useful here). It does,
however, allow for referential integrity checking with the relevant table when the
foreign key is present. (Note that, with referential integrity enforced, it is possible
to leave a foreign key field as Null, indicating that there is no match).
o The actual process of booking via the Bookings form (Unit 16) does not check for
double-booking, and double-bookings can therefore be made! Checking for
double-booking probably requires VBA code, but is not even mentioned in the
book. And the Class bookings have to be entered for each occurrence of a class.
It can be done via a composite Index of Room, Date and Time but the Access
error message here is very unfriendly, however you can use VBA to trap the error
and display your own error message. See the 'Getting Started' VBA Trainer
section 8.2.8 to see two methods that can be used to prevent double-bookings.
o I think a design where Class and Member bookings are in separate tables may
well be better, as classes book for periods between two dates, on a set day of
the week at a set time, and members book for odd hourly sessions. It also
appears that Courts are booked by members only and the other rooms by
classes. If it is required to see all bookings together, then this could be done via a
UNION query, but SQL and UNION queries are also beyond the scope of the
book.
o So for demonstrating what the book intends, this design works, after a fashion.
But do not take it as an example of good database design!

Some other items are:

Many of the table names are inappropriate; a table name should indicate what is
recorded by each row, not by the whole set of data for that table.
The tutor last name is repeated in both the Tutor and Class tables. It would be better to
have a Tutor No field, so that the Centre can employ tutors with the same last name.
While a Yes/No field may be appropriate for the Smoker field on the Membership table, a
drop-down box (easily defined with the Look-up Wizard) may be more appropriate for the
Sex field. Unit 22 suggests that an option group be used for the Membership Category;
such a group would also be useful for Sex, and can be done with a Yes/No field.
A drop-down box (again can be created with the look-up wizard) may be useful for the
Category field on the Membership table, this time based on the Membership Category
table. The LimitToList property should be set to Yes so that only the values in the list are
used.
it may also be better if there was a separate table for the Room/Hall/Court names, so
that this could be used as a look-up for the Room/Hall/Court field and thus remove
redundancy from the Bookings table. It could also ensure consistency throughout the
system whenever the room names are used.
Unit 3

1. Page 15, Unit 3, Task 1. If you click on create table in design view (point 2) you will go
straight to the second screen shown in Fig 3.3. If you click on the New button, then you
will get the first screen in Fig 3.3 from which you can choose Design View to get to the
second screen.

2. Page 19, Unit 3, Task 3. The end of this section mentions that if you want to have
Access create your primary key it will create a key field called ID. This is correct if you do
not have an AutoNumber field in your table, but if you already have an AutoNumber field
then Access will assume that this to be the primary key.
3. Page 20, Unit 3, Fig 3.4. The screen shown here will not match what you have got. At
this stage, you will only have the Membership table in your database.

Unit 4

1. Page 24. Unit 4, Task 1, Defining Field Properties. Points 3 and 4 for the
Category No properties. The change of datatype to Byte is required here
because the Primary Key for the Category table (see page 242) is a Number
field, set to Byte. Later in the book you will need to create a relationship between
the Membership and Category tables, and you will not be able to do it if the
datatypes or field sizes are different. See point 2 in I've chosen referential
integrity when setting up a relationship, but get an error message - why?

2. Page 25. Unit 4, Creating Custom Display Formats. Date. New feature for
Access 2000. If you look at the standard display format for Short Date you will
see that it shows only 2 digits for the year - the example shown in the drop-down
box for the table field property box is 19/6/94. But you can now set this to show
4-digit years, via Tools-->Options, General tab, and click in box Use four-digit
year formatting. Simple!

3. Page 25. Unit 4, Creating Custom Display Formats. Time. The book states
that the placeholder for minutes is 'm' - for example enter hh:mm to display
time as hours and minutes (e.g. as 10:05). The correct placeholder is actually n
(not m) but if you use m Access will correct it for you automatically (try it and see
what happens)!

Unit 5

1. Page 30. Unit 5, Fig 5.1. The instructions in task 1, point 3, ask you to create
indexes for two date fields. These indexes are not, however, shown in the
Figure.

2. Page 31, Unit 5, Task s. This should read Task 2.

Unit 7

1. Page 39. Unit 7, task 1, point 3. Enter 'No' for the sex column. This is a Yes/No field,
and has been set to show 'Female' for the value No.

Unit 9

1. Page 50. Unit 9, task 1, point 2. The word Currency for the field Membership Fee
should be in the Data Type Column, not the Description (looks like a tabbing error).

2. Page 52. Unit 9, after setting up the relationships. New feature for Access 2000.
Open your Membership Category in table view and have a look at the contents. Notice
the little + sign in the first column. Click on one of these and you will see a
'subdatasheet' showing you the table rows from the membership table of all members
with this category number. Use Format-->Subdatasheet to 'expand' (show) or 'collapse'
(hide) this information for all entries in the table. This is useful if you just want to check
up on linked information for one entry, or to checked all linked information to check that a
form/subform or grouped report is showing the correct information.

Unit 10

1. Page 55. Unit 10, task 1, point 4. (also applies to the text just before the task). Two
icons have not printed correctly here. They should be (in order): Next then Finish. Note
also that the columns shown in Fig 10.3 are not in the suggested order in point 3 of the
task - they will show in the order selected. The number of records in your table may not
= 21; there are 20 records in the supplied Membership Data 97 file, and you may have
added records of your own.

Unit 12

1. Page 68. Unit 12, task 2, query 1. (with thanks to the student who spotted this and told
me).
The dynaset shown here bears no relationship to the data shown in the back of the
book! Your dynaset should look like:

Addresses of Male Smokers

Member No Title Lastname Street Town County Post Code

13 Mr Gray 4 The Parade Chelmer Cheshire CH1 7ER

7 Mr Harris 55 Coven Road Chelmer Cheshire CH3 8PS

20 Mr Jones 17 Mayfield Avenue Chelmer Cheshire CH2 9OL

1 Mr Walker 16 Dovecot Close Chelmer Cheshire CH2 6TR

2.
3. Page 70. Unit 12, Task 3, query 1 - querying text fields. The dynaset shown here
does not match the data shown at the back of the book. The records displayed should
be for Member Nos 1 (Walker) and 16 (Robinson).

4. Page 70. Unit 12, Task 3, query 2 - logic using AND.


Should look for 1992 joiners as there are several for this year but only one (Jason Perry)
for 1996. [The previous version of the book used 1992 - goodness knows why this was
changed]. Note that this also means changing your criteria test in point 3 to
>=1/1/92 and <1/1/93
(the textbook seems a little mixed up here between 1992 and 1996!).
And, as in many of these items, the dynaset in the book is not correct:
When Joined

Title Firstname Lastname Telephone No


Mrs Sandra M Davies 01778 891441
Miss Donna Jameson
Miss Alison Locker
Mr Liam Locker
Mr Imran Shangali 01777 561553
Mr Andrew J Walker 01777 569236
Mr George W Weiner
F
Ms Aileen Young 01778 894471

5.
6. Page 71. Unit 12 Task 3, query 3, point 8. Wrong data set is shown - it does not
match the data in the back of the book.

Unit 13

1. Page 74. Unit 13 Task 3, screenprint under point 3. The 'Total' entry for the 'Age'
column is incorrect. It should read Avg not Expression.

2. Page 76. Unit 13 Task 5, query 2. This query asks you to show the initials of the
selected members, but there is no initials field on the table. I suspect this is an omission
due to a change of mind somewhere along the way. Use the Firstname field instead.
You may also like to look at How can I work out initials from a name field? (with
thanks to the student who spotted this and told me).

Unit 14

1. Page 80. Task 2, at bottom of page. The reference to the Classes table should be to
the Membership Category table.

Unit 19

1. Page 114. Task 1, second part of task to define the label report. You are asked to
create a query to select members who joined since 1999, but, if you look at Quick
Reference 1 at the back of the book you will see that there are no such members. So,
either change your data, or use the year 1995 instead. With 1995 you will pick up three
members (membership numbers 2, 3, 13) plus any other members that you may have
added for yourself (for example, in Unit 15 Task 3).

2. Page 114. Task 1, second part of task to define the label report. Look at the
postcode in the labels that you have created. Are they converted to upper case? My data
was typed in as lower case, relying on the field format as defined in the table to display
the data in upper case. This display works fine on forms and reports, but apparently
NOT on labels. If you look at the labels in design view you will see how the data on the
labels is formatted, and it is easy to add a conversion to upper case:
=Trim([County] & " " & UCase([Post Code]))

The text in blue shows the addition needed to convert the postcode to upper case.
It is interesting to note that there is no example screen-print of the labels in the
textbook

Unit 24.

1. Page 143. Task 4, Point 2. This should read: Select Yes for Group Header and Group
Footer.

Unit 31.

1. Page 167. There are two Task 2s. The first task 2 is relevant to the Unit but the second
one does not seem to be.

Unit 32

1. Page 172. Unit 32, task 2, point 4. The name of your renewal field may be [Date of
Renewal] if you created it using table 3.1 in unit 3. Elsewhere in the book it is [Date of
Last Renewal].

2. Page 172. Unit 32, task 2, point 6. The figure of 183 here refers to the number of days
(approx.) in 6 months. Much of the data is older than that, and, as the book says, you
may need to adjust your data to get some meaningful output from the query.
Alternatively, simply look for a longer time-period. The SQL shown for this task in the
labwork handout uses a figure of 2000 days (slightly less than 5.5 years). Experiment
with different time-periods, looking carefully at the data in the table, and see what you
get (better still, try to predict in advance, and see if you were right).

3. Pages 172, 173, Unit 32, Fig(s) 32.1. There are three figures all called 32.1 here. They
should, of course, be 32.1, 32.2 and 32.3.

Appendices

1. Pages 237 to 243 - Quick Reference 1 - there is a table definition for the tutor
table but no data. The data may well be buried in a unit somewhere (I can't find
it). An Excel file with the data is available; ask your module tutors.

2. Page 238, the 'Town' field for the Membership table. The Town for Member
12 is shown as 'Branford'. This should be 'Bradford'.

3. Page 238, the 'sporting interests' details for the membership table. The
tabbing is incorrect for member numbers 5, 7, 15, For example, member 5 has
interests of 'Aerobics, squash yes'. This should read' Aerobics, squash' for the
sporting interests, 'yes' for smoker and 'No' for Sex.
4. Page 240 - the booking table is of a rather strange design and the data here is
confusing. If the booking is for a member, put the Membership/Class No shown
in the Membership No column. If the booking is for a class, put it in the Class No
column.

5. Page 240 - booking number 22 is for 'Court 1' not 'Court!'.

6. Page 241 - the definition for the Bookings table has several lines that are
incorrectly aligned, but you should be able to work out what the correct
information should be.

7. Page 242 - you are instructed to use a data type of Number with a size of Byte
for the Category No. However, if you have used Autonumber (size LongInt) for
the Category Number in the category table, you will also need to use LongInt
here or you may not be able to join the tables. (This seems to cause a problem in
Access 2000, but is OK in XP (?) ). See also Access and VBA FAQ.
Frequently Asked Questions for MS Access and Access VBA

Last updated 17/04/11

home

This page holds questions that students have asked, plus answers to problems that
Project and Placement students have come across. You might find it useful to use Edit--
>Find to locate a question.

Click link here for an Excel spreadsheet that lists some common errors (compilation,
run-time and logic) with possible causes and solutions when coding with VBA. This
spreadsheet has been created for a year 2 module to accompany a 'finding and fixing
errors' tutorial. It is intended that new entries will be added from time to time. This version
posted March 2011.

Useful links:
http://support.microsoft.com/kb/146864 Error trapping with VBA
http://msdn.microsoft.com/en-us/library/aa264975(VS.60).aspx core (trappable) VBA
Errors
http://msdn.microsoft.com/en-us/library/aa338172(VS.60).aspx miscellaneous VBA
errors
http://msdn.microsoft.com/en-us/library/aa338178(VS.60).aspx additional VBA
information
http://www.mdbrecovery.com/mdb-corruption.html some steps to avoid a corrupt
database
Also use Google advanced search (type/paste in the 'exact wording or phrase' box) to
look for entries for a particular error message.

Students wishing to use Access VBA may like to use the VBA Trainers.

If you think of any useful items that could be included here, please email the site owner.

You may also like to look at some example databases or Links to other websites

This link looks useful - lots of FAQs http://allenbrowne.com/tips.html

Make sure that you have enough space on your disk!

Access needs to use extra space to perform certain tasks, and all changes/additions
you make to your database will also require more space. If there is not enough space
available then your database could be corrupted. This corruption could cause all sorts
of weird error messages and failures.

See also Access FAQ 27. This error used to occur with earlier versions of Access, so
may not apply to Access 2003 or 2007, but the advice does still apply.

Access FAQ 35 has occurred with students using Access 2007 and 2010.

The information here is split into those FAQs that have a standard 'point-and-click'
solution (Access Q&A), and those that require the use of VBA (VBA Q&A). With
hindsight, it might have been better to have just one list...

Access Q&A
1. How do I add (or subtract) time differences to (or from) a date?
2. Why do Yes/No fields show as a square box rather than the words?
3. Why don't my table relationships show as '1' and ''? All I have is the line.
4. Why has a relationship shown as 1:1 when I was expecting 1:?
5. I've chosen referential integrity when setting up a relationship, but get an
error message - why?
6. How do I convert an Access database to/from another version?
7. I'm setting up a validation rule and get the message "Error evaluating
CHECK constraint in the validation rule". What does this mean?
8. What Documenter options should I choose when printing out my table
details?
9. What does "Application-defined or object-defined error" mean?
10. How do I make a calculated field in a query, form or report?
11. How do I make an AutoNumber field start from 1 again?
12. How do I query on all records by date or parts of a date? For example, all
records in a particular month, year, etc.
13. How can I list details not in a database? For example, members who have
not made bookings, or cars that are not on hire?
14. Why is the data in my report not shown in the same order as in the query?
15. How can I force a page break in a report?
16. How can I combine column values to form just one column in a query?
17. What is a CROSSTAB query?
18. What is an Outer Join?
19. Can I compact my database automatically?
20. Is there an easy way to change a table field name without it affecting all
queries, forms, reports, etc?
21. How can I work out initials from a name field?
22. How do you use the Calendar Control? amended November 2010.
23. What is a UNION Query?
24. How do I select the top/bottom rows of a query dynaset? amended April
2010
25. How do I reconnect a mail merge Word document when I have moved the
Access database?
26. What does the message "Undefined function '<name>' in expression"
mean?
27. What does the message "Table 'TempMSysAccessObjects' already exists"
mean?
28. Why cant I enter data into my form?
29. Why cant I use the combo box wizard to find a record on a form? The
third option that should be there isnt listed.
30. Why dont my query criteria work when I use an input mask to attach a
prefix character to a field?
31. Why is my event code ignored? (e.g. click on button but nothing happens)
32. How can I lock part of a form?
33. How can I order records in logical day of week order?
34. Should I embed or link images into my database?
35. What does the message "The expression <event name> you entered..."
mean?
36. What does the message "You entered an expression that had an invalid
reference to the property Dirty" mean?
37. Why doesnt a formatted prefix for an AutoNumber ID show in a combo box?
38. How can I prevent a report field from being truncated?
39. Can I save a report as a PDF file?
40. What do the different RowSourceTypes for list and combo boxes mean?
41. Why do I get a dialog box Enter Parameter Value?
42. Why doesn't Access 2010 give me the option to select a Style for new forms or
reports? October 2010.
43. What does the message "Missing or broken reference to the file 'MSCAL.OCX' "
mean? November 2010.

VBA Q&A
1. What does a "type mismatch" error mean?
2. Why do I get a "Type mismatch" error trying to use Recordsets in Access
2000+?
3. Why does my list box click event code no longer work?
4. How can I create a multi-purpose query/report which allows the user to
enter a variable number of values each time?
5. How do I update a table value via a form? For example, subtracting quantity
sold from the stock total.
6. How do I create my own primary keys? For example, membership key =
M123456.
7. How can I change the size of a form at run-time?
8. How can I cater for production of (mailing) letters?
9. I'm using the debugger for VBA code and get the message "The value in
the field or record violates the validation rule for the record or field". What
does this mean?
10. How do I pass an array as a parameter?
11. What does the message "Compile Error: Expected variable or procedure,
not module" mean?
12. What does the message "Run Time Error - You cancelled the previous
operation" mean?
13. Why doesn't the Round function round up numbers all ending in 5?
Sometimes it rounds up and sometimes it rounds down.
14. How can I add a criterion to a Crosstab query?
15. Why does a calculated date give the wrong result in an SQL statement?
16. Why don't the Date and Time functions work in my module?
17. Why doesn't my 'On Error' code trap the error?
18. How can I get totals on a form?
19. How can I copy details from one form to another?
20. What does Run-time error 3061: Too few parameters. Expected 1
mean?
21. How can I search for files outside my database?
22. How can I capitalise the words that make up a name?
23. What does "The current field must match the join key '?' in the table.." mean?
24. How can I send emails from my database?
25. What does "Run-time error '3251': Operation is not supported by this type of
object" mean?
26. Why does my loop code cause Access to hang?
27. What does "Runtime error 3027 - cannot update. Database or object is read-only"
mean?
28. Why does DoCmd.SendObject to send emails cause Access 2010 to crash? August
2010
29. How can I change a report or chart RowSource SQL at run-time (dynamically)?
April 2011

1. How do I add (or subtract) time differences to (or from) a date ?

Access has many date manipulation functions - see Help for a full list.

Example - add 1 year to the system date:


=Date() uses the Date function and will give today's date (the system date).
=DateAdd ("yyyy",1, Date()) uses the DateAdd function to add one year to today's date.

You cannot reference another field in an expression like this in a table definition. But
you could do so in VBA code for a data entry form, or in a calculated field in a query, for
example.

=Date() + 365 will give a date in a year's time, but will not work for leap years!

There are some more examples in Access FAQ10 example 2 and Access FAQ 12

Back to Top

2. Why do Yes/No fields show as a square box rather than the words?

You have probably got the field defined as a 'check box' in the table definition. If this
field is actually destined for a form, then a check box may be appropriate. However, it
can look odd in the table layout or on a report. If you want to change the display, simply
look at the property box for the field on the table, form or report and change the display
control from 'check box' to 'text'.

You may also like to think whether a Yes/No box really is the most appropriate data type
to use. The user has to enter either 'Yes' or 'No' for the field. A 'Yes' (or tick in a check
box) on a form for 'Smoker' may make sense, but seems (to me, at least) to be
decidedly odd for the 'Sex' or 'member/class' fields for the Chelmer leisure Scenario
(though it does save space). You may like to experiment with using a Look-Up Wizard
for the data type here, and setting just the two values 'Male' and 'Female' or 'Member'
and 'Class' for the list box that the Wizard will create. 'M' or 'F' etc would save space.

Back to Top

3. Why don't my table relationships show as '1' and ''? All I have is the line.

You have probably not chosen to have referential integrity checked when you created
the relationship. Delete the relationship (click on the line then choose delete) and try
again, this time choosing to have referential integrity checked.

See also Access FAQ 5 I've chosen referential integrity when setting up a
relationship, but get an error message - why?

Referential integrity is important. For example, in the Chelmer Leisure database, for the
1:m relationship between the Category and the Membership Tables, referential integrity
will ensure that all member records have a membership type that is already listed in the
Category table.
It is best to set up all relationships before entering data.

Back to Top

4. Why has a relationship shown as 1:1 when I was expecting 1:?

This can occur if...:


1. ...you are joining two primary keys. A 1: relationship requires that one key only
is a primary key. Check to see that you are joining the correct fields.
2. ...you are joining a primary and a foreign key and the foreign key is specified as
'no duplicates' in the Index property for that field in the table.
(a) If the foreign key can have duplicate values in the table (this is the normal
situation) then change the Index property to show this.
(b) If the foreign key really is a unique value in the table then check to see if you
need to use a separate primary key for this table; perhaps you can use the
primary key from the main table in both tables (as in point 1 above).
You should also check your design carefully. Sometimes a 1:1 relationship is correct
(e.g. to save space in the database for information that that doesn't apply to all records,
or to put sensitive data in a separate table in order to restrict access). But you need to
be able to justify each 1:1 relationship that you have, so that you know that it is correct.

Back to Top

5. I've chosen referential integrity when setting up a relationship, but get an error
message - why?

There are two common reasons for this:

1 - Existing data violates integrity (error message: "Microsoft Access can't create this
relationship and enforce referential integrity" - this message is then followed by a nice
clear example of what the problem might be).
The most likely reason that either or both of your tables already have data in them but
that the data violates the integrity rule.
Example A: You have data in your membership table but not yet in your category table.
The tables will be joined via the category number. As referential integrity requires that
all category numbers in the membership table are also in the category table, you must
now set data in your category table before creating the relationship.
Example B: You have data in both the membership and the category tables. The likely
reason is that you have a category number in your membership table that is not in the
category table. Correct your data and try again.
It is safest to set up all validations and rules before entering any data.
2 - Key data types do not match (error message: "relationship should be on the same
number of fields with the same data type")
The relationship joins two keys - one in each table. These keys should be of the same
data type and size. If the primary key of one table is an Autonumber field (LongInteger),
then the corresponding foreign key in the other table should be a Number data type,
also LongInteger. If one key is a text field, then so should the other one (and of the
same size).

Back to Top

6. How do I convert an Access database to/from another version?

When you open an Access database in a newer version of the software, Access will ask
you if you want to convert it and then, if you reply 'yes' will do the conversion. When
converting from Access 97 to Access 2000, it is recommended that you first compile all
the code (see Debug-->Compile all Modules), then repair and compact it (see Tools--
>Database Utilities). If you don't do this, you may get a message saying that the
database is corrupt. This not does seem to be necessary when converting to XP.
If you reply 'No' to the conversion, then the database can be opened and data amended
(I think), but no design changes can be made.

There is also information regarding conversions to/from different versions in Access


Help. Use the keywords
convert, access
to find the relevant pages.
(Tip. You may find it easier to use Help if you switch the 'Assistant' off and then use
Help-->Index and type the relevant keywords in. This will show you all matching
references and you can search for the one that fits what you want)

Back to Top

7. I'm setting up a validation rule and get the message "Error evaluating CHECK
constraint in the validation rule". What does this mean? With thanks to the student who
had this error, sorted it out, and told me the answer.

This has occurred where students have written a validation rule enclosed in quotation
marks, or possibly with quotation marks instead of square brackets around a field name.

Quotation marks are used in programming (also in Access SQL and expressions) to
denote a string literal. The actual contents of these literals are not looked at by the
software but are simply used as required. For example Town = "Chelmer" where
Town is taken to be a data name and "Chelmer" is a string literal.
June 2003 (and updated January 2009). This error has also occurred with Recordset
DAO code, where a student was writing a record to a table. The table had a field
validation rule. This appeared to conflict with the Recordset DAO code and was the
cause of the error. When the field validation rule was removed and replaced by
validation VBA code then all was well. So, do not use field (or table) validation rules with
Recordset DAO code; code all validations using VBA code. If you are coding everything
via Recordsets then it would seem more logical to validate data via code anyway.
This error could also occur with embedded SQL with invalid data.

Back to Top

8. What Documenter options should I choose when printing out my table details?

The Documenter gives you several options to choose from:

The options chosen above will give a concise listing with just one line for each field, but
showing record (table) validations only.

If you want to show all the field validations as well, choose the '...and Properties' option
for Fields. Note, though, that this gives a much larger listing, with a load of extra stuff
you may not want. You could cut the listing down by publishing it in Word then deleting
the stuff you don't want.
If you have used the Table Planning Sheet to plan out your table before creating it, then
the sheet and the shorter listing could provide a concise method of documenting the
table details and field validations.

Back to Top

9. What does "Application-defined or object-defined error" mean?

This error has occurred in some labs at DMU Leicester, when students are trying to use
the Documenter.

It probably means that the Access installation is incorrect. Please report the problem to
the lab technicians or the Student Support Centre <csesupport@dmu.ac.uk> then go
and try another lab.

Back to Top

10. How do I make a calculated field in a query, form or report?

Query

Example 1
You should all be familiar with the concept of adding table fields to a query in the Query
Design window. A calculated field in a query is a Query Design column, which is not a
simple reference to a table field, but is the result of a specified calculation.

For example, suppose you have a stock table with entries for stock number, description,
unit price and quantity in stock (there will probably be other fields in the table as well).
The following will query the stock details plus the total value:
The SQL is:
SELECT stock.StockNo, stock.Description, stock.UnitPrice, stock.QtyInStock,
[UnitPrice]*[QtyInStock] AS TotalValue
FROM stock;

The result of running the query is:


StockNo Description UnitPrice QtyInStock TotalValue
1 Socks 5.99 6 35.94
2 Handtowel 7.95 43 341.85

NOTE: You do not have to have query columns for the individual table fields
used in the calculation. For example, the above query will still work if the Query
Design only uses StockNo, Description and TotalValue.

Example 2 New 8 March 2005

Sometimes the calculated value may vary according to the value in another field. For example,
a database has a field called ReceivedDate for a date when an enquiry was received. The
business has set a target date of 2 working days (i.e. excluding weekends) for each enquiry to
be actioned, and requires a query to list enquiries and their target dates. (This example is based
on a real-life situation).
The picture below shows a very simple query which uses the built-in Weekday and IIf functions
to calculate such a target date.

The SQL is:

SELECT tblDates.ReceivedDate, IIf(Weekday([receiveddate])=5 Or


Weekday([receiveddate])=6,[receiveddate]+4,[receiveddate]+2) AS TargetDate

FROM tblDates;

The result of running the query is shown below. 28th February 2005 was a Monday.

qryDates using IIF

ReceivedDate TargetDate

28/02/2005 02/03/2005

01/03/2005 03/03/2005

02/03/2005 04/03/2005

03/03/2005 07/03/2005
qryDates using IIF

ReceivedDate TargetDate

04/03/2005 08/03/2005

The Weekday function returns 1 for Sunday to 7 for Saturday. For further examples and
information about date functions, see FAQ 12 on queries using dates.

The IIf function is very useful in cases like this. The basic description of the function is:

IIf(expression, truepart, falsepart)

The logic of how it works can be expressed as:

If expression is true then

Result = value in truepart

Else

Result = value in falsepart

End if

Thus, in this example,

Expression is Weekday([receiveddate])=5 Or Weekday([receiveddate])=6

It is checking to see if the received date field is for a Thursday or a Friday

Truepart is [receiveddate]+4

4 days are added to the Thursday or Friday date for the required working date after the
weekend

Falsepart is [receiveddate]+2
2 days are added to the (Monday to Wednesday) date for the required working date this week

Form or Report

One method is to base the form or report on a query such as the one above.

Alternatively, add a text box to the form or report then:


Put the appropriate formula in the Control_Source property for the text box (see
McBride Unit 24), or
Use VBA code to do the calculation and put the value in the new text box.
These alternative methods are discussed in more detail in section 3.2 of the Getting
Started VBA Trainer.v5.

See also:
Access FAQ 26 What does the message Undefined function '<name>' in
expression" mean?
VBA FAQ 5 How do I update a table value via a form?

Back to Top

11. How do I make an autonumber field start from 1 again?

When you are doing initial testing or if you make mistakes entering data and delete a
row, the AutoNumber field keeps incrementing from the last number used. You may
wish to start from 1 again (perhaps with existing data or perhaps after deleting initial test
data).
This is very simply done as follows:
Make a copy of the table (just in case)
Remove all relationships between this table and any others
If the AutoNumber field is a primary key, click on the primary key icon to
undesignate it as a key
Delete the row for this field
Insert the row again and recreate the field as an AutoNumber field
Redesignate it as a primary key, if appropriate
Look at the table in design view - it should now be renumbering from 1 again.
Reinstate the table relationships.
WARNING 1 - if you have a table joined to this one, with the second table using the
AutoNumber field as a foreign key, then renumbering the first table will upset all the
relationships, as the data will no longer correspond.
WARNING 2 - if you are using the AutoNumber key as a base for a second key field key
of the form M000001, where you have VBA code on the form that affixes "M" to the front
of the AutoNumber key, then the second key field will NOT be changed automatically by
this method. You would need to do an Update Query to reset the second key field, for
example:
UPDATE Member SET Member.[Membership No] = "M" & Format([Memb No
Auto],"000000");
Where [Memb No Auto] = the AutoNumber key
and [Membership No] = the second key field
and the calculation is that already used on the form.

Back to Top

12. How do I query on all records by date or parts of a date? For example, all
records in a particular month, year, etc.

Consider the 'date of joining' field in the Membership table of the Chelmer Leisure
database. The management may want to know answers to questions to such as:
- How many people joined in 1992?
- How many people joined in each month of 1992?
- How many people joined each year?

You specify the criteria as normal for the column in the Query Design screen, or the
WHERE / HAVING section of SQL. The table below shows some examples. Note that
some of the details have calculated columns that make use of the date functions, Date,
Year and Month.
Access has many of these date manipulation functions.
For an example showing calculated columns and the functions, see after the table.

Criteria Column(s) Result

>=#01/01/92# And <=#31/12/92# Date of joining Selects data between the two dates shown
If used for a query requiring totals, will group by all
the separate dates, not by the year.

Between #01/01/92# And #31/12/92# Date of joining As above.

Year(Date())-1 Date of joining Selects data for last year.

Year(Date())-Year([date of joining])<4 Date of joining Selects data where the year of the date of joining
is less than 4 years ago.

<DateAdd("yyyy", -4, Date()) Date of joining Selects data where the date of joining is less than
4 years ago. The DateAdd function is used to
New - 8 March 2005 subtract 4 years from the system date.
1992 Year([date of joining]) Selects dates of the form dd/mm/1992
Use this to group for a count of members joining in
1992.

[please enter required date] Year([date of joining]) Similar to above, but uses a run-time parameter
for the year. This will cause a parameter box with
the text "[please enter required date]" to popup.

=forms!frmReports!txtYear Year([date of joining]) Similar to above, but checks the value in a textbox
called txtYear on a form called frmReports. This
New - 8 March 2005 uses the Forms Collection.

none Year([date of joining]) Use this to group for a count of members joining
by year.

1992 Year([date of joining]) This uses two calculated columns to select by


and
and Month([date of joining]) month for 1992 - see example below.
none

Query Design screen for the last example, counting membership joins by month for
1992:
Experiment with some of the other examples above and see results.

SQL for the above example:


SELECT Month([date of joining]) AS Month, Count(Membership.[Membership No])
AS Total
FROM Membership
GROUP BY Month([date of joining]), Year([date of joining])
HAVING (((Year([date of joining]))=1992));

Result of running the query:


(the year column is suppressed here as it will be the same for all rows).
Month Total
2 1
4 2
6 3
7 1
8 1

But what if the management wanted the query to show all months (1-12), even when
there were no new members joining that month? See Example 3 in FAQ 13 How can I
list details not in a database? and FAQ 18 What is an Outer Join?

The Forms Collection. New - 8 March 2005

The Forms Collection is invaluable for enabling queries (and VBA code see VBA Getting
Started Trainer Appendix I) to reference values on an open form. See example in table above,
where frmReports is assumed to be a form where the user enters parameter values and then
can open reports based on queries that use the parameters. The field for the parameter used in
the example shown is called txtYear.

There is some limited Help available from the Access database window; search using the
keywords Form Object, then select the item About referring to an object or its properties in
expressions. This item does not mention queries (I dont know why) but does show how to
make a reference to a field on an open form.

There is more information (using the same keywords) via VBA Help.

Date manipulation functions. New - 8 March 2005


There are many date manipulation functions available in MS Access. The Help files for these
functions are only available from VBA Help (which is not very helpful) even though the functions
can be used in Access queries, etc. Two such functions are Date [gets the system date] and
DateAdd [add days, months, years etc to a given date], demonstrated in the table above.
Another useful function is Weekday, an example of which in use can be seen in FAQ 10.

There is some limited help via the Access database window. Search with the word
expressions and then look at the item titled examples of expressions. This has various
examples of calculated fields in queries, forms and reports, and includes some examples using
date functions.

In VBA Help, use the keywords Function; Date; Time; Date and Time. There is some more
information in the VBA Getting Started Trainer, with a summary in Appendix H.2.

VBA Help New - 8 March 2005

To see VBA help, you need to be in an open code window. (If you dont know how to do this, a
simple method is to (a) click on the Modules object in the database window, then (b) click on
New. Then you will see the code window open. This is a separate window to the Access
database window, so you can safely close it when you have finished looking at Help).

Back to Top

13. How can I list details not in a database? For example, members who have not
made bookings, or cars that are not on hire?

This is a very common requirement in booking systems, for example listing hire cars,
hotel rooms, etc that are free for particular dates. Another use is for for financial data for
accounting periods.

Listing free slots for bookings (for example, the bookings each hour for a day for the
Chelmer Leisure Centre) can be done by several methods. Some of these are illustrated
using worked examples in the VBA Trainers.
The clue to the answer is in the words 'not in' in the question. There is a simple solution,
based on two queries:
Query1 - list the unique identifiers (membership, car, or room numbers, for
example) for the bookings that have been made.
Query2 - select the required details, where the unique identifiers are NOT IN the
list from Query1. This uses a NOT IN subquery, selecting just the one column
from the subquery.
There follows below three examples of instances of use of a NOT IN subquery.

Note that Access allows you to refer directly to sub queries within the SQL, and this can make
things easier to follow. Other RDBMSs may allow similar references to Views, but if they dont,
follow the examples below to set up the full SQL.

Example 1, the Chelmer Leisure management want to know which members did not
make any bookings last year.

Query1 - select the membership numbers of the members who did make a booking last
year:
SELECT DISTINCT Membership.[Membership No]
FROM Membership INNER JOIN Bookings ON Membership.[Membership No] =
Bookings.[Membership No]
WHERE (((Year([Date]))=Year(Date())-1));
You may need to add the word DISTINCT if creating the query via Query Design. It is
not essential, but does reduce the size of the result of query1 and thus may (?) speed
up query2.

Query2 - create a query to select the required fields, and in the criteria for the
Membership No column do:
- enter : NOT IN (
- paste the SQL for query1
- replace the semi-colon (;) at the end of the SQL for query1 with a closing round
bracket
- your SQL will now be of the form:
SELECT [Membership No] <,any other field(s) required>
FROM Membership <,any other tables required>
WHERE [Membership No] NOT IN (SQL for Query1);
The second select here is known as a subquery. Access may add loads of extra
brackets here, which can be a bit confusing.

Actual SQL, selecting the three fields shown is:


SELECT Membership.[Membership No], Membership.Lastname,
Membership.Firstname
FROM Membership
WHERE Membership.[Membership No] NOT IN (SELECT DISTINCT
Membership.[Membership No]
FROM Membership INNER JOIN Bookings ON Membership.[Membership No] =
Bookings.[Membership No]
WHERE (((Year([Date]))=Year(Date())-1)));
Alternative method, referencing intermediate queries directly, rather than using
the full SQL:
SELECT Membership.[Membership No], Membership.Lastname, Membership.Firstname

FROM Membership

WHERE Membership.[Membership No] NOT IN (SELECT [Membership No] FROM [Query1]);

this might be a simpler method to use.

Example 2 - click here for an example car booking database (Access 2000). This has
just 2 tables, Car and Booking, with a form in which to enter the two dates for the hire
period. There are two queries; Booked (the 1st query) and Free (the 2nd query, which
uses the SQL from the 1st query for the NOT IN subquery). Have a play with it and see
how it works. I think it covers all conditions, but it is up to you to test it thoroughly in your
application! There are two versions of the Free query (called Free and Free2; one with
the full SQL, and one referencing the Booked subquery by name).
Click here for a Word document with further explanation.
There is just a small amount of VBA code behind the form, for the two command
buttons. The Booked button code is generated by the 'run query' form wizard. The Free
button code is my own, to operate a list box which shows the details of the cars that are
free.

Example 3 - The Chelmer Leisure management want a graph showing numbers of


members who joined in each month in 1992.

See Access FAQ 12 How do I query on all records by date or parts of a date? This
FAQ shows how to list totals for all months in which at least one member joined. What is
needed now is to list all the months NOT IN this list, and then to join the two lists
together.

Stage 1 - create the query 'Totals by months in a year' from the above-mentioned FAQ.

Stage 2 - create a new table ("Month"), with just one column ("Month"), and add
numbers 1 through 12 as data to the table.

Stage 3 - create a new query ("months with no bookings") which uses a NOT IN
subquery:
SELECT DISTINCT Month.Month, 0 AS Total
FROM Month
WHERE (((Month.Month) Not In (SELECT Month([Date of Joining]) AS Month
FROM Membership
GROUP BY Month([Date of Joining]), Year([Date of Joining])
HAVING (((Year([Date of Joining]))=1992)))));
The result of this new query is then
Month Total
1 0
3 0
5 0
9 0
10 0
11 0
12 0
Note how to create a column with a fixed value in it. Look to see what the Query Design
screen looks like.
Note also that the subquery SQL is the same as that for the 'totals by month in a year'
query, but omitting the 'Total' column, as the subquery must have only one column.

Stage 4 - open a new query, do not choose any tables, go to the SQL view and do the
following:
(a) paste in the SQL for the 'totals by month in a year' query - deleting the semi-colon (;)
at the end
(b) add the word UNION
(c) paste in the SQL for the 'months with no bookings' query (do not delete the semi-
colon at the end).

You now have a UNION query, with SQL like:


SELECT Month([Date of Joining]) AS Month, Count(Membership.[Membership No]) AS
Total
FROM Membership
GROUP BY Month([Date of Joining]), Year([Date of Joining])
HAVING (((Year([Date of Joining]))=1992))
UNION
SELECT DISTINCT Month.Month, 0 AS Total
FROM Month, Membership
WHERE (((Month.Month) Not In (SELECT DISTINCT Month([Date of Joining]) AS
Month
FROM Membership
GROUP BY Month([Date of Joining]), Year([Date of Joining])
HAVING (((Year([Date of Joining]))=1992)))));
Note that for UNION queries, the results of each query must be of the same format (i.e.
same number of columns with the same data types in the same order).
Run this and see what you get! You can then use this new query result as the basis for
a graph.

See also What is an Outer Join?

Alternative method, referring directly to query, instead of copying the SQL.

SELECT DISTINCT Month, 0 AS Total

FROM [Month]

WHERE Month Not In (SELECT Month from [Totals by months in a year]);

Note that must only select one column for the sub query.

Alternative method for UNION query, referring directly to both queries:

SELECT * FROM [Totals by months in a year]

UNION

SELECT * FROM [months with no bookings]

ORDER BY Month;

Back to Top

14. Why is the data in my report not shown in the same order as in the query?

I don't know why this is, but you can specify the order of the report using 'Sorting and
Grouping' (see the View menu; there may also be an icon on the toolbar) and this
appears to work OK.

You can also add/remove group headers/footers using 'Sorting and Grouping'. This can
be useful if you want to change an existing report.

Back to Top

15. How can I force a page break in a report?


Look up 'page break, report' in Help - this is easy to do and clearly explained in Access
97, so simply experiment until you get what you want. However, I can't find it in Access
2000/2002 Help, so copy below the text from Access 97 Help.

Page breaks are useful if you want a new group to start on a new page. The group
value can then be put in the group header and this header used to replace the page
header.

Page or report headers/footers can be added/removed via the View menu.


Other group headers/footers are controlled via View--> Sorting and Grouping.

Page breaks in reports

All this is extracted from Access 97 Help, by typing page break in Contents and Index.
Access 2000/2002 help does not appear to have this (or if it is there it not so easy to locate).
However, you can find something if you type how can I force a page break in a report? into
the Help answer wizard.

Add a page break to a report

In reports, you use a page break control to mark where you want to start a new page within a
section. For example, if you want a report's title page and introductory message printed on
separate pages, place a page break in the report header after the controls that you want to
appear on the title page and before the controls for the second page.

1 Open the report in Design view.

2 Click the Page Break tool in the toolbox.

3 Click the report where you want to place the page break. Place the page break above or
below a control to avoid splitting data in that control.

Microsoft Access marks the page break with a short dotted line on the left edge of the report.
If you want each group or record in a report to start on a new page, set the ForceNewPage
property of the group header, group footer, or detail section.

Print each record, group, or section on a separate page on a form or report

1 Open the form in Design view or the report in Design view.

2 Double-click the section selector to open the property sheet.

3 Set the ForceNewPage property of the section to one of the following settings:

None. (Default) Prints the section on the current page.

Before Section. Prints the section at the top of a new page.

After Section. Prints the following section at the top of a new page.

Before & After. Prints the section at the top of a new page, and prints the following
section at the top of a new page.

Notes

The ForceNewPage property is available for all sections except page headers and
footers.

To print each record on a separate page, set the ForceNewPage property of the detail
section to After Section. To print each group on a separate page, set the ForceNewPage
property of the group header to Before Section or the ForceNewPage property of the group
footer to After Section.

Use Visual Basic to force a page break in a report if a condition is met

1 Open the report in Design view.


2 In the toolbox, click Page Break , then click in the report section where you want a
conditional page break.

3 Open the report's PageHeader_Format event procedure.

4 In the event procedure, add an assignment statement that sets the Visible property of
the page break control to No. For example, if the name of the control is CondPgBreak, add the
following assignment statement:

Me![CondPgBreak].Visible = False

This hides the page break control when the report starts formatting each page, so the page
doesn't break.

5 In the Format event procedure of the section where you placed the page break, add
Visual Basic code that sets the Visible property to Yes when a condition is met. For example,
suppose you want a page break to occur in the detail section of the report if the value of the
Counter control is 10, so that the first 10 records will print on the first page. Add the following
code to the Detail_Format event procedure:

If Me![Counter] = 10 Then

Me![CondPgBreak].Visible = True

End If

When the condition is met, the page breaks. After the page is broken, the event procedure
attached to the page header hides the page break control until the condition is met again.

Back to Top

16. How can I combine column values to form just one column in a query? For example,
join forename and surname, or show first initial and surname?
In order to join fields you use the concatenation character

& (ampersand).

Remember to allow for space characters between fields where necessary.

Query column showing the full name.

Enter the following for the Field row in the Query:

Fullname: [Firstname] & " " & [Lastname]

The Fullname field now consists of three parts, joined together: the Firstname, a space
character, the Lastname.

Note that there is no need to specify the Membership table in the Table row.

Query column showing the first initial.

Enter the following for the Field row in the Query:

Init and name: Left([Firstname],1) & " " & [Lastname]

As above, the field consists of three parts, but there the first part if just the first character of the
Firstname field. The Len function is just one of several useful String Manipulation functions
available - to see details, look at Help.

Here you must not specify the table name in the Table row. If you do so, Access will say that
there is a syntax error in the expression, as it will look for the field Left([Firstname],1) in the
Membership table, and object to the presence of the comma.

Be careful if your query uses more than one table and the tables have the same field names for
the fields that you wish to combine!

Look at Access FAQ 21 How can I work out initials from a name field? for screen prints and
results for these examples.

Back to Top
17. What is a CROSSTAB query? (also known as a PIVOT TABLE query)

"A crosstab query displays summarised values (sums, counts, and averages) from one field in a
table and groups them by one set of facts listed down the left side of the datasheet and another
set of facts listed across the top of the datasheet." (Explanation from Access 97 Help). These
queries can be extremely useful for providing summarised information.

You may find that using the crosstab query as the source for a report proves problematic
(various error messages, etc). A simple way round this is to create a second query, which is
merely a simple select query that selects all the fields from the crosstab query. Then base your
report on this second query. This seems to work...

Example using Crosstab Query Wizard (example with only one table)

As an example, suppose you wanted to see totals of bookings by Room/Hall/Court. Do the


following:

(a) Create a new query and choose crosstab query wizard

(b) Choose the Booking table, then the [Date] field for the row headings.

(c) Choose the [Room/Hall/Court] field for the column headings.

(d) Choose the Count Function.

(e) Save and run the query. The result will look like:

Date Total Of Court 1 Court Court 3 Fitness Sports Hall Sports Hall
Booking 2 Suite 1 2
No

13/05/1996 5 1 2 1 1

14/05/1996 4 1 3

15/05/1996 5 1 1 3

16/05/1996 5 1 1 3

17/05/1996 3 1 2
Date functions could be used in the date column to select date ranges, show values by year,
etc. (See Access FAQ 12 How do I query on dates or part of a date?)

Look at the result in the Query Design Window and at the SQL. Note the TRANSFORM and
PIVOT SQL statements.

Example using SQL (example with more than one table)

Suppose that the Chelmer Leisure management wants to check that correct category numbers
have been allocated to members. One way would be to have the row header for the year of birth
and the column headers for the category description (the description being more of more use
than the category number).

Create a query with the following SQL:

TRANSFORM Count(Membership.[Category No]) AS [CountOfCategory No]

SELECT Year([Date of Birth]) AS [Year of Birth]

FROM [Membership Category] INNER JOIN Membership ON [Membership Category].[Category No]


= Membership.[Category No]

GROUP BY Year([Date of Birth])

PIVOT [Membership Category].[Category Type];

Compare this SQL with that for the first example above, and look at the query design window.
Run the query and see what you get.

A better query would show the actual ages rather than just the year of birth. The Getting Started
VBA Trainer shows how to create and use a CalculateAge function. Using this, the SELECT
statement could be changed to : SELECT CalculateAge([Date of Birth]) AS Age

So - experiment with the examples above and try creating a crosstab query of your own. For
example, create a query to show the bookings each day by membership type. You will need to
use the Booking, Membership and Membership Category tables. Select the booking date for
the row header, the category description for the column header, and count the category
descriptions for the value column. Go back to the first example above and see how the Crosstab
Query Wizard has created a Total column, then try doing the same for your new query.
See also VBA FAQ 14 How can I add a criterion to a Crosstab query?

See section 8.4 of the Getting Started VBA Trainer for a further example of the use of Crosstab
query.

Back to Top

18. What is an Outer Join?

Inner Joins (the normal joins with which you should be familiar) show rows in a query where
there are matching records in both tables.

"Left outer joins include all of the records from the first (left) of two tables, even if there are no
matching values for records in the second (right) table." (Description here taken directly from
Access 97 Help).

Right outer joins are similar to left outer joins, with the tables in the other order.

As an example, consider the Query Totals by Month in a Year from all records by date or part of
date? and example 3 in How can I list details not in a database? An outer join can be used to
query the result of the query joined with the month table, to show all months from the Month
table, and values where they exist from the query. However, outer joins cannot be used with
queries, only with tables, but queries can be used to create tables. So do the following:

Stage 1 - Create Totals by Month table by changing the query SQL (and saving it as a new
query) so that it looks as follows:

SELECT Month([Date of Joining]) AS Month, Count(Membership.[Membership No]) AS Total

INTO [Totals by Month]


FROM Membership

GROUP BY Month([Date of Joining]), Year([Date of Joining])

HAVING (((Year([Date of Joining]))=1992));

Save and run the query - look at the tables where you should now see this new one.

Stage 2 - Create a query using the Month table (see stage 2 of example 3 of FAQ 13 How can I
list details not in a database?) and the Totals by Month query as shown below.

To create the join between the tables, click on Month in the Month table and drag to Month in
the Totals by Month table. Then right click on the line to see the Join properties box and
choose option 2: "Include ALL records from 'Month' and only those records from 'Totals by
Month' where the joined fields are equal".

Now, if you run this second query, the result you get is:

Month Total

2 1
3

4 2

6 3

7 1

8 1

10

11

12

This shows all months, and values where they apply. Note that the Create Totals by Month
query must always be run before running the Totals by Month - Left Join query. You will be
prompted to delete the existing Totals by Month table. If running the queries via VBA, you
should code a DROP TABLE command first.

Look at the SQL to see how the outer join is coded.

Compare this method with the NOT IN method shown in example 3 in Access FAQ 13 How can
I list details not in a database?

See Part 8 of the Getting Started VBA Trainer v 5.1 for further examples of the use of Outer Join
queries.

Back to Top

19. Can I compact my database automatically?


Yes - this is a new feature for Access 2000. Use Tools-->Options and then choose the General
tab. Click in the Compact on Close box. See Compact on Close.

For fuller information (which includes when you can not use this feature) use Help with 'Close'
as the keyword, and choose 'Compact and Repair an Access File'.

However, using this can be dangerous if the process crashes or if you are short of disk space.
See Access FAQ 27 What does the message "Table 'TempMSysyAccessObjects' already
exists" mean? . It may be safest to make a backup first, then compact manually via Tools--
>Database Utilities. See also section 7.4 of the Getting Started VBA Trainer.

Back to Top

20. Is there an easy way to change a table field name without it affecting all queries,
forms, reports, etc?

Yes - this is a new feature for Access 2000. Use Tools-->Options and then choose the General
tab. Click as required on the entries in the Name AutoCorrect box. See Name AutoCorrect.

For fuller information use Help with 'Name' and 'AutoCorrect' as keywords, and choose 'About
using Name AutoCorrect to fix errors caused by renaming'.

Back to Top

21. How can I work out initials from a name field?

See later on this section for logic for a possible own VBA function to do this.
The example here demonstrates several useful features:

Calculated field - a new field that displays the results of a calculation defined with an
expression.
LEFT function, here used to select just the first character to the left of the field. See also
RIGHT and MID functions.
Using the '&' character to concatenate (join, combine) elements in an expression.
If you want to use initials of all names it's probably easiest to have middle names in separate
fields.

The example uses the Membership table from the Chelmer Leisure database.

The two fields Initial and FullName are calculated fields - they do not exist in the table,
but are created via the query.
Initial uses the left function to select just the leftmost single character of the Firstname
field from the table.
FullName concatenates the Title, Initial and last name into one field. Note how the &
character is used to join each bit and how spaces (" ") and full stops (". ") are put in the
result. The FullName here uses the Initial field, but it could also have used the left
function instead.
Query to create Initial and Fullname:

Result of query:

Title Initial Lastname FullName


Mr A Walker Mr A. Walker
Mrs D Cartwright Mrs D. Cartwright

Mr J Perry Mr J. Perry

Miss A Forsythe Miss A. Forsythe

Miss D Jameson Miss D. Jameson

Miss P Robinson Miss P. Robinson

Mr D Harris Mr D. Harris

Mr I Shangali Mr I. Shangali

Mrs M Barrett Mrs M. Barrett

Mr G Weiner Mr G. Weiner

Mr D Ali Mr D. Ali

Ms A Young Ms A. Young

Mr I Gray Mr I. Gray

Miss F Swift Miss F. Swift

Mrs S Davies Mrs S. Davies

Mrs R Robinson Mrs R. Robinson

Mr A Everett Mr A. Everett

Mr L Locker Mr L. Locker

Miss A Locker Miss A. Locker

Mr E Jones Mr E. Jones

You can also create your own function, using VBA, to do this.

(a solution is not given here as it is set as labwork, with the logic shown below, on a module)

A suitable function header could be:

Public Function myInitials(prmString As String) As String

When testing in the Debugger, ?myinitials(John Joe Fred) should return JJF.

Logic examples below assume the first character is not a space. Could use Trim/LTrim at the
start to trim off any starting spaces.
Suggested logic 1:

get first initial (hint use Left)

get length of string (hint use Len)

For each char in the given string

If the char = space then (hint use Mid)

position to next char (hint add 1 to loop

counter)

if position is outside end of string then

exit for

else

add char after the space to the initials

so far (hint use &)

end If

end If

Next 'go round again

return upper case initials

Suggested logic 2:

get first initial (hint use Left)

get length of string (hint use Len)

set a counter to 1 for start of string

Do

find position of space in string (hint use InStr)

If position = 0 Then char not found

exit do 'no (more) occurrences of char


else

position to next character (hint add 1 to counter)

If position > length Then

Exit Do

Else

add to list of initials (hint use &)

End If

End If

Loop

return upper case initials

Back to Top

22. How do you use the Calendar Control?

This feature has been removed from Access 2010. See VBA FAQ 43.

The calendar control is an Active-X data object that shows a calendar on a form and allows a
user to choose a specified date.
It can be used as an alternative to requiring the user to type a date directly into a text box. You
need to think carefully which control (textbox or calendar) is appropriate for the given context.

Putting the control on a form.

This is simple, via Insert ActiveX Control, and then choose Calendar Control from the list
presented.

The name for the control will be something like Calendar0. You can change this via the property
box to something like ocxCalendar (using the usual prefix for this object).

By default, the months may show as Jan, Feb and the days as Mon, Tue. You can change
these via the property box; look at the Other tab for the entries for DayLength and Month
respectively. Look at the property box to see the various other items here that can be changed.
As for other form controls, these items can be changed using VBA code (see below for an
example of how to change the Value property).
Showing todays date

The date shown will probably be the date that you created the control on the form. To make it
change to the system date each time the form is opened, code the following line in the
Form_Load event:

ocxCalendar.Value = Date

This uses the Date Function to assign the system date to the Value property.

(Note this code has no effect in the Form_Open event!).

Using the Calendar

You can refer to the control by name in VBA code just as with any other form control. You can
also use it with a forms collection reference (for example, as a query parameter):
[forms]![form1]![ocxCalendar]

If you look at the property box you will see that there are five events for which you can provide
VBA code.

There are examples of use of a Calendar control in the VBA Trainers.

Back to Top

23. What is a UNION Query?

"A union query combines fields from two or more tables or queries into one field in the query's
results. You might use a union query to combine data from two tables. For example, you might
combine company name and city data for all companies in Brazil that are listed in the Suppliers
and Customers tables." Access 2000/2002 Help.

Note that both SELECT statements must return a dynaset that has the same number of
columns with the same datatypes in corresponding columns. The UNION clause will combine
the two dynasets into one dynaset. You cannot create a UNION query via the query design
window, but you can create each separate SELECT query this way, then copy/paste the SQL
into a new UNION query into the query SQL window.

See VBA FAQ 4 How can I create a multi-purpose query/report? (which actually uses very
little VBA) and Example 3 in Access FAQ 13 How can I list details not in a database? for
some examples.

An example from Help is:

SELECT [CompanyName], [City]


FROM [Suppliers]
UNION SELECT [CompanyName], [City]
FROM [Customers]
ORDER BY [City];

Back to Top

24. How do I select the top/bottom rows of a query dynaset?

This is very easy to do with MS Access. Look at Access 2000/2002 Help, keyword
maximum, and select the item Show only high or low values in a query.

In Access 2007 the same keyword will get you an item "Find the records with the top or bottom
values in a group or field" (on the first page of the list on my machine!).

This Help information looks very useful, and indeed, helpful.


The following screen shows a query to list all members of the Chelmer Leisure Centre by
ascending date of birth.

By using the little drop-down box shown above, you can select the top/bottom rows that you
require. You can specify either an absolute number of rows, or a percentage. There are
suggestions in the drop-down box, but you can over-ride these by entering your own figure.

In the example above, the top values (in this case, for those members whose dates of birth are
earliest) will be selected, as the list is sorted in ascending order; i.e. the first several rows are
selected. If you wanted to see those at the other end of the list, simply sort in descending order.

Look at the SQL note the new item, 'TOP 5':


SELECT TOP 5 Membership.[Membership No], Membership.Firstname, Membership.Lastname,
Membership.Title, Membership.[Date of Birth]

FROM Membership

ORDER BY Membership.[Date of Birth];

new 3 April 2010

(If you wanted the report to list by descending Age, then add a calculated column to the query to
calculate the age. There is a suitable function in section 3.2.3 of the Getting Started VBA
Trainer.)

Most likely you will want to add up something, for example total bookings by member in the
Chelmer Leisure scenario, or total products sold for a sales system. You may also require
further parameters such as bookings/sales between two user-specified dates. You will need an
aggregate query for this, with an appropriate sort order, then use Top on the totals column.

However, there is no very easy way to allow the user to select this Top value (5 in the example
above) at run-time. Two suggestions are shown below; both need VBA code:

One way I have done this, for the 'top n' records where n is determined by the user, using VBA
is:

1. Use a combo box on a form, and allow the user to select a value for the 'top n'.
2. Create the report as usual using your query.
Group the report on the field being used for the top value.
Set the required sort order (even though this has been specified on the query it may
need to be done again here).
Note that Access Top will take account automatically of equal value rows (joint
positions).
3. Delete the RecordSource property from the report property box.
4. In the Report_Open event set up the query SQL in a String variable.
Use the value from the form combo box for the 'Top' value in the SQL.
Then assign the value in this String variable to the report RecordSource property.
The report will now open using the data retrieved by the SQL.
5. In the Report_Open event set an integer variable to the value 1 (one).
The first record listed will be number 1 in the 'Top n' list.
6. In the Detail_Print event, add 1 to the integer variable for each line printed.
7. In the GroupHeader_Print event show the integer variable value in the header.
An alternative (possibly more challenging) method is:
1. Read the aggregate query (without the Top clause) into a DAO Recordset.
2. Read the Recordset row by row from the first record (this means coding a loop), taking
account of duplicate values, writing the records to a temporary table (perhaps adding the
position in the list as a new field, or you can work this out using report event code as
for points 6 and 7 above).
3. Use a combo box on a form for the user to specify the 'top n' value, and stop the loop
when the appropriate number of rows have been read and written to the temporary table.
4. Work out your logic for this before you start to code it!
5. Then use this temporary table as the basis of the report.
And don't forget to add suitable improvements to your report. Some of these may require VBA;
see section 5 of the Getting Started VBA Trainer. See also advice for report design.
Improvements to your report should include:

1. Showing the 'top n' value, and any other query parameters used, in the report or page
header.
2. Catering for an empty report.
3. Group and report totals.

Back to Top

25. How do I reconnect a mail merge Word document when I have moved the Access
database?

When you create a mail merge Word document linked to an Access database, the full
connection path of the database is stored with the document. If you move the database (or
install the database and document on another machine) you will need to change the path.

This is relatively simple (if a little long-winded) to do. Click here for an explanation.

Back to Top

26. What does the message "Undefined function '<name>' in expression" mean?

This can occur when creating calculated fields on a query (and possibly in other situations).
Some possibilities are:

You are using a built-in function, or one of your own, but have mis-spelled the name.
You are using a function of your own, but have not coded it yet.
The function is not declared as Public so cannot be accessed from another module.
You have a module name the same name as the function (so Access gets confused,
understandably!). Change the module name.
Back to Top

27. What does the message "Table 'TempMSysAccessObjects' already exists" mean?

This message occurs when you try to close your database with 'compact on close' or when you
use the menu Tools-->Database Utilities to compact the database.

When you make changes to data, objects or code in an Access database, new space is
allocated for the new information. Deleted or old information is merely made 'unavailable', but it
still occupies space. Thus, your database can grow very large during development but contain a
lot of wasted space. During live use, changes and additions to data can slow down the database
as access times increase. By compacting the database, you release the wasted space and tidy
up (reorganise) the database.

Access compacts your database by creating a new version, copying across the current
information and ignoring the old stuff, then deletes the old version and gives the new
(compacted) version the name of your original database. But it needs space available on your
disk to be able to do this. Access Help has some useful information; use the Answer Wizard
with the keywords 'compact and repair'.

The message above appears (though this is guesswork) to be caused when there is not enough
space to complete the compacting, and seems to happen when students are very close to their
limit on University or College networks. (This, of course, happens nicely at the end of a
semester/year, when project and assignment work is reaching deadlines!). Access does not
give a message to say that the compact process has been cancelled, but just appears to stop
without any indication that something was wrong. Next time you try it, the process is unable to
continue as a temporary table (named in the message) was not deleted in the previous
compaction.

I have been unable to find out how to locate the table and delete it.
If you are happy with the database being large (and getting ever larger) then simply don't
attempt to compact it again.

If you need to overcome the problem (due to lack of space on your machine, or because it is a
project for a real client) then the only solution that I can think of seems to be to:

Create a new (empty) database.


Copy across all objects (tables, queries, forms, reports, modules, etc) in your current
database to the new database. [The associated code modules for forms and reports will
be copied automatically with the object].
Recreate the relationships in the new database.
This method is long-winded, but works.
You should then be able to use the new database in place of your old one, and carry on
with compacting it as required.

Later - the link at http://support.microsoft.com/kb/818099 gives further information,


including how to delete the table.

Back to Top

28. Why cant I enter data into my form?

With a form based on a table, there is usually no problem entering data, unless the AllowEdits
and/or AllowAdditions property has been set to False.

If the form is based on a certain type of query, then data entry and insertion of new records is
not allowed on the form (or via the underlying query). You can see if this applies to a query by
looking at the navigation bar at the bottom of the query; if the new record icon on the bar is
greyed-out then this query will not allow data entry or addition. The query types include:

SELECT queries without a join (Cartesian product queries).


SELECT queries using DISTINCT.
SELECT queries using WHERE for the SQL join, rather than the
INNER/LEFT/RIGHT join as used in Access.
Aggregate Queries (those using COUNT, SUM, MAX etc).
CROSSTAB queries.
UNION queries.
Self-join queries.
Queries with complex joins, perhaps based on other queries.
I would guess that the reason is that Access cannot easily identify the table row(s) that would
need to be edited, so no editing or additions are allowed.

The problem can also occur if your ERD/FD is incorrect. For example, the joins between tables
are incorrect or you are using cross-postings of foreign keys.

Queries such as the above are often required for reports, charts, list boxes, combo boxes etc,
where data is displayed rather than updated, so the lack of editing does not cause a problem.

They can also be used for forms where information is simply displayed. Click events can be
activated on some of these forms. Where the form is based on a Crosstab query, a click on a
field which has a value in it will trigger the click event (if coded) for that field; a click on a Null
field does not appear to do this. With some other query types, field click events may be
activated for Null values as well you will need to experiment with the query for your particular
application.

Back to Top

29. Why cant I use the combo box wizard to find a record on a form? The third option
that should be there isnt listed.

This wizard is available via the form design toolbox and normally gives the following three
options:

1 I want the combo box to look up the values in a table or query.

o Use this for a combo box that provides a list from which the user can choose from a list
of values taken from a table or query.

o The RowSourceType property is set to Table/Query and the RowSource property is the
SQL that selects the required fields from the table/query.

o Set the LimitToList property to Yes if you want the user to be limited to the list shown.

o You can use VBA code to allow the user to update rows in the table with new list items;
see the Getting Started with VBA Trainer version 5 section 6.3).
o No VBA code is generated.

2 I will type in the values that I want.

o Use this for a combo box that provides a list from which the user can choose from a list
of values.

o For this method you type the list in yourself, and it is stored in the RowSource property
of the combo box. The RowSourceType property is set to Value List.

o Set the LimitToList property to Yes if you want the user to be limited to the list shown.

o This method is not as flexible as the method (above) that uses a table or query, as the
list is fixed and can only be changed by the programmer/designer.

o No VBA code is generated.

3 Find a record on my form based on the value I selected in my combo box.

o This third option creates a combo box with items selected from the table/query on
which the form is based. When the user chooses an item from the list, the associated
record becomes the current record on the form.

o The RowSourceType property is set to Table/Query and the RowSource property is the
SQL that selects the required fields from the table/query.

o See also the Getting Started with VBA Trainer version 5 section 3.4.2.

o VBA code for the combo box AfterUpdate event is generated to find and move to the
required record.

However, the third option will only show for a form that is based directly on a table or query. If
the form was created via the form wizard, and fields were selected from two or more queries,
then the third option for the combo box is not available.

Solution:

Look at the RecordSource property for the form (Data tab). This should show the
SQL that selects the data for the form.
Create a new query, not based on any table/query and open the SQL window for the
query.
Copy the form RecordSource SQL and paste it into the query SQL window.
Save the query with an appropriate name.
Change the form RecordSource property so that it now uses the new query (delete
the form RecordSource SQL and choose the query from the drop-down box to the
right of the property row).
You should now be able to use the combo box wizard and have all three options
available.
Note: it is more flexible to base forms (and, indeed, reports) directly on tables/queries. Queries
can be tested before the form/report is created, and any change to a query is then automatically
reflected in the form/report. New fields added to a table/query can be added to a form/report
using the Field List.

(Note the third option above is also not available for unbound forms, as it is not applicable to
such forms).

Back to Top

30. Why dont my query criteria work when I use an input mask to attach a prefix
character to a field?

Some students use an input mask of (for example) the type M0000 in order to generate key
values of M0001, M0002 etc, requiring the user only to enter 0001 and the mask will
add the M.

However, this prefix character (or it could be more than one character) does not exist in the
database table, but only in the mask for the user to see for data entry.

Therefore, when you have a criterion for a field like this you must enter only the numeric
characters for your criterion. If the criterion uses a parameter field on a form then you could
make this a combo/list box for the user to select from, or (for a textbox) set an input mask that
automatically adds the prefix so that the user simply enters the numeric part.

See also the Custom Keys example database.

Back to Top
31. Why is my event code ignored? (e.g. click on button but nothing happens)

Check the property box for the control.

This should have [Event Procedure] against the appropriate event (e.g. Click event for a button,
AfterUpdate event for a combo box) in order to provide the link between the control and the
code (the code could be wizard code or code that you have written, or wizard code
subsequently amended - it does not matter how the code was generated).

If the row is blank, choose to create the event (click ... at the end of the event row) and you
should then be positioned in your event code. If this code consists just of a procedure header
and footer, then one of the following may apply:

You have changed the name of the control (this usually breaks the link). If the control
was created by a wizard, then the name you gave the control at that time will be used for
the event code behind the control (e.g. cmdClose_Click for a wizard Close Form
command button you called cmdClose). If you then change the control name the event
name will no longer match. So - find the code for the original name and change the old
name to your new one (or change the name of your control back to what it was).
You are using the wrong event. Check through the code for the name of the control and
choose the correct event for the property box link and try again.
If you now look at the property box, the event link should be present and the control should work
when activated.

Back to Top

32. How can I lock part of a form?

This is easily done (though can be time-consuming), as each field can be individually locked:

(a) in the form design view [see Crash Course in Access Basics section 5.3, Exercise Frm2(c)],

or

(b) via VBA code in an appropriate event (for example, the Form_Load event if wanting to set
these properties for the form when it first opens).
Some useful properties for non-data-entry fields are:
set Locked property (Data tab on field property box) to Yes
set SpecialEffect (Format tab on etc) to Flat
set BackStyle (Format tab on etc) to Transparent

It can also be useful to move these fields to the end of the tab order (View-->Tab Order).

If using VBA code, then code as follows (where FieldName is the name of a form field):
FieldName.Locked = True 'note - use True, not Yes
FieldName.BackStyle = 0 'transparent - colour of form will show through
FieldName.SpecialEffect = 0 'flat
Use VBA Help to explore the settings further.

You may also like to look at the 'Getting Started' VBA Trainer sections 2.1-2.3, as this discusses
using the form AllowEdits property.

Back to Top

33. How can I order records in logical day of week order?

If you have a table or query with a field for the weekday name, and sort (ascending) on it, you
will get the results in alphabetic order; Fri, Mon, Sat, Sun, Tue, Thu, Wed.

If your table contains dates, you have to create a query with the weekday names first.

The document linked here shows how you can get the data sorted in logical weekday order;
Sun, Mon, Tue, Wed, Thu, Fri, Sat.

The Access database linked here contains the examples in the document.

Back to Top
34. Should I embed or link images into my database?

There is a lot of useful information this in Access 2003 at http://office.microsoft.com/en-


us/access/HA011472041033.aspx in an article called Use images in your Access forms,
reports, and controls.

The article also has two videos showing:

Demo: How to add a background image to a form or report

Demo: How to add a static image to a form or report

The article recommends using linked images for Access 2003, for various reasons concerned
with:

The number of images to be stored.


Application size (Access databases have a two-gigabyte size limit.).
Performance.
Ability to handle more image file-types.
The necessity of having MS Photo Editor on each machine using the application (MS
Photo Editor appears to have been removed from MS Office 2003, I think).
Linked images require the use of a little VBA, though it's not difficult; look at Access Help with
Add a picture or object. They also mean that you need to refresh the image path if the
image folder is moved. But these seem to be the only disadvantages of linking.

One way to avoid having to refresh the image paths with linked images could be:

Have all images in the same folder.


Store the path in a separate table in the database. This is best as linked table,
separate from the application front-end.
Store just the filename in the link.
Concatenate the path and the filename when opening the form/report that shows the
image.
If the images are moved, you simply have to change the pathname in the new
database table. The application needs no changes.
This method is also very useful when testing the application on several different machines;
simply change the path to match the location of the files. February 2008 - example database
available.
Another advantage of linked images is that, if you have a logo that appears on all forms, reports,
letters etc produced by the application, then you simply replace the old logo file with a new one
(but with the same name) and the application itself needs no changes.

June 2008 - see comments in the Access 2007 What's New document and information about
logos and attachments.

See also VBA FAQ 21 How can I search for files outside my database?

Back to Top

35. What does the message "The expression <event name> you entered..." mean?

This message will probably be part of a longer message similar to:

"The expression <event name> you entered as the event property setting produced the
following error: Object or class does not support the set of events".

The causes for this include:

1. A compilation error. You should always clear all compilation errors before attempting to
run any code. Even better, clear all errors as they arise (code a bit, compile it, test it,
repeat...).
2. Your database is corrupted. This can happen if there is insufficient room on the disk
for your database. So Compact your database (save a copy somewhere else first) to
remove deleted items and keep the size to a minimum (see also the notice at the top of
this page). I have managed to clear the error from a student database by creating a new
database and copying each object across from the error database to the new one. I
compacted the error database first.
3. Incompatibility between Access and Office. This error has also occurred with me
when running Access 2002 on a machine that had Office 2007 (but not Access 2007)
installed. So - ensure that your version of Access and your version of Office are the
same.

Back to Top
36. What does the message "You entered an expression that had an invalid reference to
the property Dirty" mean?

It appears that the Access 2007 command button wizard generates the following code for the
Close button:

Private Sub cmdClose_Form_Click()

On Error GoTo Err_cmdClose_Form_Click

If Me.Dirty Then Me.Dirty = False

DoCmd.Close

Exit_cmdClose_Form_Click:

Exit Sub

Err_cmdClose_Form_Click:

MsgBox Err.Description

Resume Exit_cmdClose_Form_Click

End Sub

The line shown above in bold was not generated by the command button wizard in Access 2003
or earlier and now sometimes causes the above run time error if you are using a database with
an Access 2000-2003 file format (a .mdb file).

According to http://support.microsoft.com/kb/121677 this error occurs with unbound forms


(which makes sense, when you think about it). Their solution is to bind the form (using the
RecordSource property) to a table, query or SQL statement. But I can't see why you need to do
this - if your form is unbound then that's what you want - a menu, for example, is a common
version of an unbound form.

My solution is to remove the line shown above in bold.


Back to Top

37. Why doesnt a formatted prefix for an AutoNumber ID show in a combo box?

It is important to realise that using a format does not change the data itself, only how it is shown.
Access Help states: format: specifies how data is displayed and printed.

A format used to add a prefix to an AutoNumber key therefore does not store the prefix with the
key value in the data table. The prefix is only added when the value is displayed - but not
always, as when the value is the bound field in a combo box. Unless you realise this it can be
difficult working out what is going on. An AutoNumber value is numeric, and is entirely under the
control of Access, so cannot include any other characters when it is stored - logical when you
think about it.

When you want to use the value in a query, you must use only the numeric part, not the version
with the prefix. This might be one of the reasons why the combo box value does not show the
prefix, so that you can use a Forms Collection reference for the value (see point 3 below).

The database linked here contains the Chelmer Leisure Member and Category tables.

1. The two tables are joined by [Category No] with referential integrity enforced. The [Category
No] in the Category table has had a prefix format added to the property for the AutoNumber
Primary Key, but the Member table [Category No] Foreign Key has not got such a format.
But the two tables still join correctly with referential integrity enforced, showing that the prefix
is not part of the data, but just used for display.

2. Form frmMember1 is a simple wizard form, based on some of the fields in the Member
table. The Category field has been changed to a combo box based on the Category table,
with LimitToList = Yes and ColumnHeadings = Yes. The dropdown list for the combo box
shows the category number with a prefix, but the category number in the [Category No]
combo box displays as a number, without a prefix. You could display it with a prefix by
entering the same format (\C00) for the combo box as is used for the [Category No] in the
Category table, but this then displays "C00" for a new record. Removing the default value of
zero for this field on the Member form before creating the form control may remove this (but
I've not tried it).
3. Form frmMember2 is a copy of frmMember1 with the [Category No] combo box changed to
hide the category number value (the ColumnWidth property has been set to zero for this
column) so that the second column (the [Category Type] description shows in the combo
box field. There is also a new unbound textbox txtCategoryNo and VBA code is used to
show the category number value with a prefix added to it. The command button on the form
will open a query qryMembersForCategory that selects all members in the Member table
with the same [Category No]. If you look at the query you will see that there is a Forms
Collection criterion referencing the combo box not the new text box, this picks up the
numeric value in the bound (and hidden) column of the combo box.

4. Form frmMember3 is a copy of frmMember2 without the command button and with no VBA
code. This uses the IIF Access built-in function to put the formatted [Category No] in
txtCategoryNo so is an alternative version for those who dont like using VBA. The code is
in the RowSource property for the text box txtCategoryNo. Look up the IIF function in VBA
Help its a very useful function.

Finally, if you want to store the prefix with the AutoNumber ID in the table, then see the Creating
custom primary keys example database.

Back to Top

38. How can I prevent a report field from being truncated?

If the field is for something like 'Comments' or 'Details' then you might like to consider using a
Memo datatype. This will allow you to enter a lot of detail in the field and on the report it will
automatically be sized to match the data over as many lines as are required. (See also the
example database Opening Word (and other) Documents - this shows an alternative method
from keeping large details within the database).

If the field is for something like 'Description' or 'Sporting interests' (the latter is an example from
the Chelmer Leisure database), then do one of the following:

Set an appropriate field size in the table/form for the field, and ensure that the report field
is large enough to show all details. This may not be possible in all cases if the report
shows a lot of other fields as well.
Change the report field 'CanGrow' property to Yes (look at the field property box Format
tab; the property setting is usually No by default). The contents of the field will now wrap
round and be displayed in the same field width but over as many lines as are required, in
a similar fashion to Memo fields.
Back to Top

39. Can I save a report as a PDF file?

Yes. See the document attached here. I think this is a new feature for Access 2007 (or else I
missed it before...).

Back to Top

40. What do the different RowSourceTypes for list and combo boxes mean?

There are three possible values ('Table/Query'. 'Value List', 'Field List') that can be used for this
property. The document linked here gives an overview.

The document here is from MS Access 2007 Help and gives some more detailed information.

The database attached here shows how to use these properties with some VBA code.

See Access FAQ #4, the Multi-purpose query database, for a further example.

Back to Top

41. Why do I get a dialog box Enter Parameter Value?


This dialog box is usually Access's way of saying that you are referring to the name of
something that it does not recognise.

The attached document and database may help you to understand this and to spot why this
problem is occurring with your database and help you to fix things.

Back to Top

42. Why doesn't Access 2010 give me the option to select a Style for new forms or
reports?

See information on the Access 2010 page of this site.

Back to Top

43. What does the message "Missing or broken reference to the file 'MSCAL.OCX' "
mean?

The reference is to the library for the Calendar Control that was available in previous versions of
Access.

It has been removed from Access 2010.

See information on my Access 2010 page.

Back to Top
***********************End of Access Q&A**********************************

1. What does a "type mismatch" error mean?

It means that you are trying to compare apples with oranges!

You may have a statement such as:


If member-ID = user-request-ID THEN...
where you are trying to compare two data items.

The error means, quite simply, that the two values are not the same data type. Possibly
one is text and the other is numeric.

The same error will occur for assignment statements where you are assigning a value to
an item of a different data type, or if you are calling a procedure which is expecting a
certain datatype but the value passed is not of the expected type (e.g. a form textbox
value that is null or not date/numeric, and which has not been validated first). There will
be many other situations when this can occur! Use the debugger to check the values in
the variable(s) concerned.

The error can also occur when using Recordsets. See VBA FAQ 2 Why do I get a
"Type mismatch" error trying to use Recordsets in Access 2000?

Back to Top

2. Why do I get a "Type mismatch" error trying to use Recordsets in Access


2000?

The "Further VBA" Trainer was developed using Access 97, which used Data Access
Objects when accessing tables in VBA code. In section 6, for example, the code in
Figure 6.1 contains the line

Dim BookingTableRecords as Recordset.

This is fine in Access 97 but will cause the "Type Mismatch" error in Access 2000, as
Access 2000 uses ActiveX Data Objects (with, confusingly, very similar initials).

To adjust code so that it works in Access 2000, do:


Add the letters DAO so that the code reads like:
Dim <Recordset name> as DAO.Recordset
(replacing <Recordset name> with the correct name)
Still in the code window, choose Tools-->References then ensure that the item
'MS DAO 3.6 Object library' is selected in the list presented; this is not referenced
by default.
The code shown in the "Further VBA" Trainer should now work in Access 2000.

See also:
Access VBA Help, keywords 'Converting DAO Code to ADO'. This is the source
for the information above.
Explanation in section 3.1.4 of the 'Further VBA' Trainer v5.0.

Back to Top

3. Why does my list box click event code no longer work?

If you have created a form object such as a command button, then delete the button,
the code is left in the form module. If you create another button with the same name, the
new button click event will be linked to the code, as the names are the same. This can
be handy if you want to redo a form object, as you do not have to redo code.

However, if you delete and recreate a list box, the old code may not always be picked
up. So, to re-link it to the list box, go to the object property box and simply recreate the
relevant event; this should then link to the code.

Back to Top

4. How can I create a multi-purpose query/report which allows the user to enter a
variable number of values each time?
Note - the suggestions below mainly use Query Design and the Forms Collection - VBA only really comes
into play for checking date ranges or for setting the sort order at run-time for the report.

Click here for an Example database - this is the result of following the instructions
below, plus some extra bells and whistles.

Click here for version 2 of Example database - 30/3/2010, showing how to use a Field
List combo box (see Access FAQ #40) and how to search through controls on a report
page.

Click here for explanatory notes - this explains about the extra bells and whistles.

The Query
When a system is up and running, the user may want to do various one-off queries. The
information from these queries may be wanted quickly, and the user will not want to go
through negotiations with the system developer to produce the report and arrange a
price. It is useful to provide a general-purpose query if possible. For example, the
Chelmer Leisure Management (see scenario in Access Further Skills textbook) may
want queries such as:
Details of all members with a particular category, with certain dates of birth, with certain
sporting interests, by surname, by gender, etc.
Rather than having lots of separate queries, it is possible to create a query that picks up
the required values from a form via parameter values in text and combo boxes, etc.

30/3/2006. See the Getting Started VBA Trainer section 7.3.5 for how to save this query
dynaset to an Excel spreadsheet.

Try the following:


Create a form with unbound text boxes that are to contain the user's criteria for a
selection of fields from the membership table. Make sure that the text boxes are
the same data type as the corresponding field on the membership table.
Create a query to select all the fields from the membership table.
Add a command button to the form to run the query. Clicking on the button will
bring up a list of all the members.
The user can then simply look at this, or copy/paste it into a spreadsheet for further
analysis. You could also use VBA code to export the data to an Excel spreadsheet; look
up DoCmd.TransferSpreadsheet - it's very easy to use.

Querying on a numeric field:


Enter [forms]![Memb query]![category no] as the criterion for the category number
field, enter the number 2 in the category field on the form and run the query
again. Only those records for members with category number = 2 will now be
listed. But if you delete the category value and run the query, nothing at all is
listed! (as there are no members with a category number field that is null). To
correct this, change the query criterion to:
Like [forms]![Memb query]![category no] & * (* is the wildcard character)
Now, leaving the field blank will list all categories and entering a number will list
just the required category. Have a look at the SQL to see how the query works.
Note that this uses the 'Forms Collection'. This is how Access allows you to
reference fields on an open form. If you try running the query when the form is
closed, little parameter boxes will pop up for you to enter the values in.
The example database shows a method using a drop-down box based on a
Union query.
Querying on the starting characters of a text field:
Enter the following for the criterion for the last name:
Like [forms]![Memb query]![Lastname] & "*"
Now, entering a category of 1 and a lastname of J will list all members with a
category of 1 and lastname beginning with J.
This is also useful for postcode analysis, e.g. listing all members in the CH1 area
of Chelmer.
Note that if the user leaves the parameter box blank then this criterion will not
select rows where this field is Null as "LIKE '*' " does not select Null values.
There must be a non-Null entry in every row for this field. It would therefore be
useful to set a default value for the field and to set the Required property to Yes.
This comment amended 30/3/2006.

Querying on characters within a text field:


Enter the following for the criterion for the sporting interests field:
Like "*" & [forms]![memb query]![sporting interests] & "*"
and try this out with, say, aerobics (or even 'aer').
Note that if the user leaves the parameter box blank then this criterion will not
select rows where this field is Null as "LIKE '*' " does not select Null values.
There must be a non-Null entry in every row for this field. It would therefore be
useful to set a default value for the field and to set the Required property to Yes.
This comment amended 30/3/2006.

Querying on a yes/no field:


Enter the following for the criterion for the sex field:

Like [forms]![memb query]![sex] & "*"

This field is (confusingly!) specified as a yes/no field in the book, so the entry in
the form field has also to be yes/no here. It would be better if this was simply M
or F in a single-character field, and the user would then select via a combo box.
The example database shows a method using a drop-down box based on a
table.

Querying on a specific value in a date field:


Enter the following for the criterion for the date of birth field:
Like [forms]![memb query]![date of birth] & "*"
Now you can specify a particular date or all dates.
Querying on a range of dates.
In some cases, the user may want a range of dates, for example:
Between [forms]![memb query]![date of birth1] And [forms]![memb query]![date
of birth2]
but in this case the user must enter values in both dates. It is not possible to use
the wildcard * with 'between' or <, =, > for a date field. Access Help states:
"Wildcard characters are meant to be used with text data types, although you can
sometimes use them successfully with other data types such as dates, if you
don't change the regional settings for these data types".

However, the following is a way round this, by using hidden fields on the form, in
addition to the ones above, and VBA code:
(i) create two new text fields on the form, dob1 and dob2 and delete the labels.
Format as date fields.
(ii) change the query criterion for the date of birth field to
Between [forms]![memb query]![dob1] And [forms]![memb query]![dob2]
(iii) code the following in the command button click event code, before the
command to run the query:
If Not [Date of Birth1] Then ' put the user's value in the
dob1 = [Date of Birth1] ' query field
Else ' or set a default early date
dob1 = #1/1/1001#
End If
If Not [date of birth2] Then ' as above, but set a
dob2 = [date of birth2] ' default late date
Else
dob2 = #12/31/9999#
End If
Now run the query and experiment - watch the values that get set in the dob1 and dob2
fields.
Finally - change the 'visible' property for dob1 and dob2 to 'No', so that the fields are
now 'hidden'.

Querying on a mixture of parameters or none.


Now try entering a mixture of values in the fields on the form, and see how the
query picks up the values and selects appropriate records. Leaving all fields
blank will select all records.
All the above has been based on just one table, but it is also applicable to a form based
on a query joining two or more tables.

The Report
As a report can be based on a query, then, instead of having the form command button
run a variable parameter query, as done above, choose to run a report instead.
The report header should list the parameter values that the user entered in the form
fields. This is very straightforward. Create unbound text box field controls in the report
header and enter Forms![form name]![field name] in the control to pick up the value from
the form (with the appropriate form and field names, of course!). If there is no value in
the form, then this will show as blank.

The example database demonstrates all this, with the parameters shown in the report
header and with an option for the user to specify the sort order at run time.

Back to Top

5. How do I update a table value via a form? For example, subtracting quantity
sold from the stock total.

The form shown above is a very simple form based on a table and using three fields,
StockNo, Description and QtyInStock. The form is to be used to record sales data.

The form fields for the table fields are locked (by setting the appropriate field property to
No) to prevent the user changing them. As these form fields are bound to the table, any
change to the value on the form will also change the underlying table row.

The AmtSold field is an unbound text box - i.e. it is not bound to any table.

The ConfirmSale button is a non-Wizard command button (use non-Wizard buttons for
purposes that the Wizards do not cover).

The VBA code is as follows:


Form Load event (for when the form is opened):
[AmtSold].SetFocus 'move cursor to total sold field
[ConfirmSale].Enabled = False 'disable sale button until sale entered

Before Update event for AmtSold field (for when user enters a value in the
amount sold field):
[ConfirmSale].Enabled = True 'enable sale button

Click event for the ConfirmSale button: (for when use clicks on the button)
[QtyInStock] = [QtyInStock] - [AmtSold] 'adjust stock total
[AmtSold].SetFocus 'move cursor from button to
[ConfirmSale].Enabled = False 'stop user hitting button twice
So, when the form is opened the sale button is disabled. When a sale is recorded, the
button is enabled so that the user can click on it to confirm the sale. This activates code
that updates the quantity in stock; as the form field is bound to the table row, this will
automatically update the table. The button is then disabled to stop the user from clicking
on it again; alternatively, the form could be closed.

It is also normal to have the unit price on the form plus a calculated field to show the
value of the sale (quantity x unit price). See Access FAQ 10 How do I make a
calculated field in a query, form or report?

In a properly designed system, the stock code number would be typed in (simulating a
scanner) and the form opened showing just that record. There would also be checks (in
the ConfirmSale click event) such as:
AmtSold > 0
AmtSold not null
AmtSold <= QtyInStock
The 'Getting Started' VBA Trainer covers validation of data entered into fields on a form.

Back to Top

6. How do I create my own keys? For example, membership key = M123456.

See the creating custom primary keys example database.

Back to Top

7. How can I change the size of a form at run-time?

Example - suppose you want a form to open so that it is always maximised:


In the Form_Load event, code: DoCmd.Maximise
This will maximise the size of the form - and of all other windows (apart from pop-
up windows).
In the Form_Close event, code: DoCmd.Restore
This will restore the form (and all other windows) to their previous size.
Look up Maximise and Restore in Help.
Also look up Minimise and SelectObject.
Look also at section 4.3.8 in the Getting Started VBA Trainer; this uses the InsideWidth
property to set the width of a form at run-time. This bit added 15/1/2007.

Back to Top

8. How can I cater for production of (mailing) letters? changed 15/12/2003

Using a fixed letter set up as a report is a method often used by students. The report is
designed with the letter text in a text box on the report, and with the variable data picked
up from a bound table or query. This is very inflexible, as the user will have to go back
to the developer to get the letter changed. This method may or not require VBA,
depending on the complexity of the report.

The Mailing Letter example database demonstrates how to:


create individual and bulk letters by typing the text in a form, picking items from
drop-down boxes, etc.
use Mail Merge (with a simple query and one that picks up a parameter value
from a form)
All except the simple query Mail Merge use VBA.

Back to Top

9. I'm using the debugger for VBA code and get the message "The value in the
field or record violates the validation rule for the record or field". What does this
mean?

This has happened when one decides to stop the debugger, after replying 'Yes' to 'This
command will stop the debugger'.
If you then run the code without the debugger everything is OK.
So it would appear to be caused by the stopping of the debugger, not an error in your
code (I think...).

Back to Top

10. How do I pass an array as a parameter?


The two methods below show how to specify and use an array as a parameter in a
private or public sub procedure or function. The example given is of a Public procedure,
but this method also applies to Private procedures and/or Functions.

Method 1:

Public Sub myProc(prmArray() As <datatype>)


Where <datatype> = the datatype as in the declaration of the array, or Variant.
Note that the actual bounds of the array are not specified; the open and close
brackets () indicate that this is an array.
The parameter as passed to the procedure must be an array or else the calling
code will not compile: "Type mismatch: array or user-defined type expected".

Method 2:

Public Sub myProc(prmArray as Variant)


A Variant variable can cope with any datatype, including an array. Note that there
are no () after the array name.
The calling code will compile if the parameter passed to the procedure is not an
array (compare with Method 1).
The procedure must therefore check at run-time that the parameter is an array:
If [Not] IsArray(prmArray) then ...

Both Methods:

The array definition in the procedure header does not specify the bounds of the array,
but Access provides two useful functions LBound and UBound which determine these at
run-time:
For IntCount = LBound(prmArray) to UBound(prmArray) ...

Back to Top

11. What does the message "Compile Error: Expected variable or procedure, not
module" mean?

This can occur when you have a module name the same name as a function (so Access
gets confused, understandably!). Change the module name.

See also Access FAQ 26 What does the message Undefined function '<name>' in
expression" mean? .

Back to Top
12. What does the message "Run Time Error 2001 - You cancelled the previous
operation" mean?

This message is far from helpful, as it bears no obvious relation to the problem!

It can occur in VBA when Access cannot make sense of part of an embedded SQL
statement, or when elements within a Domain Aggregate Function are incorrectly
specified.

Example:
Look at the Staff Holiday Booking example database. The Holiday form uses a DSum
statement to add up the total holiday days booked:
Forms![Staff]!txtSumOfDays = DSum("days", "qryHolDates", "[staffId] = " &
Me!staffId)
If you change the "days" to "day" for the first parameter to the DSum statement then you
will duly get the error message, as there is no field called "day" on qryHolDates.

The solution is to look carefully at each element of the SQL or Function, and check that
they are entirely correct. Put all SQL in string variables, then you can check the
contents at run (i.e. failure) time in the Debugger. It could also be useful to put the 3rd
parameter (the SQL criterion) for a Domain Aggregate Function in a variable for
checking at run/failure time.
Tip. it can be useful to try the function without the optional 3rd parameter (the SQL
criterion). If it does not fail, then the fault is in the criterion, so check that carefully. If it
still fails, then the fault lies with one (or both!) of the first two parameters.
See the end of section 6.6 of the 'Getting Started' VBA Trainer for a list of things that
cause errors in embedded SQL - many of these also apply to Domain Aggregate
Function code.

You may also get this error message when you hit OK on an unexpected parameter
box, without actually entering a value. The parameter boxes (as you should know) pop
up when Access cannot find the item specified - the usual cause is a misspelled name,
or an incorrect name for a form or field.

Back to Top

13. Why doesn't the Round function round up numbers all ending in 5?
Sometimes it rounds up and sometimes it rounds down.

Examples: Round(4.5,0) returns 4


Round(3.5,0) returns 4

The answer can be found at http://www.tek-tips.com/faqs.cfm?fid=3734 . The text at this


site as at 11:13 6/12/2004 is copied below (as links can sometimes be removed).
(My thanks to Matthew Dean for pointing this site out to me, when I asked him why
Round was apparently inconsistent/wrong).

http://www.techonthenet.com/access/functions/numeric/round.htm has a really neat


solution! 8/3/2005.
"If you wanted to round 12.65 to 1 decimal place in the traditional sense (where 12.65 rounded to 1
decimal place is 12.7, instead of 12.6), try adding 0.000001 to your number before applying the Round
function:
Round(12.45+0.000001,1)
By adding the 0.000001, the expression that you are rounding will end in 1, instead of 5...causing the
Round function to round in the traditional way.
And the 0.000001 does not significantly affect the value of your expression so you shouldn't introduce any
calculation errors."

Start of text from tek-tips site....................................

The Round() function rounds 2.45 to 2.4 and is correct. Why?

faq705-3734

Before you use the Round() function in Access, please read this FAQ or you may introduce
calculation errors into your application:

Syntax: Round(expression[, numdecimalplaces])

The Access Round() function appears to be a handy way of rounding decimal values to a given number of
decimal places. For example, Round(2.341, 2) returns 2.34.

However, it does not perform rounding the way you might expect. Take this example:

Round(2.385,2)

You would expect this to return 2.39, but if you open an immediate window and type ?Round(2.385,2)
you will get the following output:

2.38 (not 2.39)

Even though the last digit was 5, it rounded DOWN.

If this is not the behaviour you expected, then heres the explanation:
The Round() function does a round-to-even, not the more well-known round-to-larger. If the argument
ends in 5, the number may be rounded up or down to achieve an even rightmost figure.

So in our example above:

2.385 could be rounded to either 2.38 or 2.39. The former has an even rightmost figure, so this is the
result.

The reasoning behind this is to eliminate cumulative errors over a series of calculations. Put another way,
100 half pennies should round to be equal 50 cents, not 100 cents.

A RoundToLarger() function:

Public Function RoundToLarger(dblInput As Double, intDecimals As Integer) As Double

'Implements a variant of the Round() function, that rounds-to-larger


'rather than rounds-to-even, like in Excel:

Dim strFormatString As String 'Format string


Dim strResult As String

'If input is zero, just return zero. Else format as appropriate:


If dblInput <> 0 Then
strFormatString = "#." & String(intDecimals, "#")
If Right(strFormatString, 1) = "." Then
strResult = Format(dblInput, "#")
Else
strResult = Format(dblInput, strFormatString)
End If

Else
strResult = "0"
End If

'If the result is zero, Format() will return "." - change this to "0":
If strResult = "." Then
strResult = "0"
End If

RoundToLarger = CDbl(strResult)

End Function

Acknowledgement: Thanks to hnawebmaster for help in compiling this FAQ.


Dave Mc Donald
www.mcdonaldit.com
End of text from site....................................

31/1/2005. I think there is an error in this function if the result is zero. The lines:

'If the result is zero, Format() will return "." - change this to "0":
If strResult = "." Or strResult = "" Then

need changing as shown above in red, or the run time error 13 'Type Mismatch' may occur.

I have also had a go at my own function, but it's dependant on the maximum values allowed by
the data types, so will not work for numbers with more than 15 digits in total. The code is shown
below, for those who are interested.

Public Function myRound(prmNumber As Double, prmPlaces As Integer) As Double


'own function to round 5-9 up and 0-4 down
'VBA Round function rounds-to-even for .5.
'IMPORTANT - if prmNumber has more than 15 digits (regardless of the where the dec. pt is)
' then the Double datatype would appear to truncate the least significant digits
'try testing with ?myround(12345678901.12345,2) and look at the value passed in prmNumber

Dim dblIntegerPart As Double 'to store the required digits


Dim dblDecimalPart As Double 'to store the surplus decimal places
Dim dblTemp As Double 'for intermediate calc only

'move the decimal point by the required number of digits


'example, 4.45 required to 1 decimal place gives 45.5
dblTemp = prmNumber * (10 ^ prmPlaces) 'note: 10^0 = 1

'truncate the value to get rid of the unwanted decimal places


dblIntegerPart = Fix(dblTemp)
'subtract truncated value from temporary number to find out what the unwanted digits are
dblDecimalPart = dblTemp - dblIntegerPart

'are the unwanted digits +0.5 to +0.99999etc or -0.5 to -0.99999?


If Abs(dblDecimalPart) >= 0.5 Then
If prmNumber < 0 Then
dblIntegerPart = dblIntegerPart - 1 'subtract 1 for -ve number
Else
dblIntegerPart = dblIntegerPart + 1 'add 1 for +ve number
End If
End If

'put decimal point back in original position and return the rounded value
myRound = dblIntegerPart / (10 ^ prmPlaces)
End Function

Back to Top

14. How can I add a criterion to a Crosstab query?

See also Access FAQ 17 What is a CROSSTAB query?.

NOTE added 12/4/2005 - this item also applies to 3-D charts. If you look at the SQL generated
by the Chart Wizard you will see that it is a TRANSFORM query. If you wanted to add a
criterion, then see the information below.

Simple literal criterion.

To add a criterion with a literal value specified in the query is fairly simple. Add the column to
the query, set the grouping to Where and add the value in the criteria cell. The SQL shown
in Access FAQ 17 with a criterion of [Category No] = 1 will then be (Where clause shown in
bold):

TRANSFORM Count(Membership.[Category No]) AS [CountOfCategory No]

SELECT Year([Date of Birth]) AS [Year of Birth]

FROM [Membership Category] INNER JOIN Membership ON [Membership


Category].[Category No] = Membership.[Category No]

WHERE (((Membership.[Category No])=1))

GROUP BY Year([Date of Birth])

PIVOT [Membership Category].[Category Type];

Parameter criterion.

However, if you used a criterion that used a parameter such as [Please enter Category No] or a
Forms Collection reference such as forms!frmcategory![Category No], your query would fail with
a message similar to:
The Microsoft Jet database engine does not recognise [Please enter Category No] as a
valid field name or expression.

or

The Microsoft Jet database engine does not recognise forms!frmcategory![Category No] as
a valid field name or expression.

A way round this is to put the criteria value(s) in a table and use IN for the criterion expression.

Example (using the query from Access FAQ 17 as above):

1. Create a new table called TempCat, with a numeric field called Category No.

2. Create a form with an unbound textbox called txtCategoryNo.

2.1 In the txtCategoryNo_AfterUpdate event code:


DoCmd.RunSQL "DELETE * FROM TempCat"
DoCmd.RunSQL "INSERT INTO TempCat VALUES (" & txtCategoryNo & ")"
This will delete any previous rows from the table, and add the new value from the textbox to
the table. See Part 6 of the Getting Started VBA Trainer for information about the
DoCmd.RunSQL statement (which includes information about suppressing the various
information messages that you will get when deleting/inserting table rows)..

3. Alter the Crosstab query criterion to IN (SELECT [Category No] from TempCat), so that the
SQL now looks like:

TRANSFORM Count(Membership.[Category No]) AS [CountOfCategory No]

SELECT Year([Date of Birth]) AS [Year of Birth]

FROM [Membership Category] INNER JOIN Membership ON [Membership


Category].[Category No] = Membership.[Category No]

WHERE (((Membership.[Category No]) IN (SELECT [Category No] from TempCat)))

GROUP BY Year([Date of Birth]), Membership.[Category No]

PIVOT [Membership Category].[Category Type];

The query will now pick up the required parameter value, which can be varied by changing the
value in the textbox.
Tables used to store parameter values do not have to have just one row (though the SELECT
SQL in the IN clause must select only one column). The SQL statements can generate several
rows in a table. For example, if you wish to select values between a pair of dates, and if the date
parameters on a form are called txtStartDate and txtEndDate, then the code to generate rows in
a table called TempDate which has just one (date datatype) column could be as shown below.
Note that dates in SQL statements must be in USA format!

Dim dtDate As Date

Dim strDate As String

'delete previous rows from table

DoCmd.RunSQL "DELETE * FROM TempDate"

dtDate = CDate(txtStartDate) 'set to start date on form

Do Until dtDate > CDate(txtEndDate) 'loop until end date has been passed

'dates in SQL statements must be in USA format

'so must reverse day and month before putting in SQL statement

strDate = Month(dtDate) & "/" & Day(dtDate) & "/" & Year(dtDate)

'write date to temp table

DoCmd.RunSQL "INSERT INTO TempDate VALUES (#" & strDate & "#)"

dtDate = DateAdd("d", 1, dtDate) 'add one day

Loop

Access Help.

Look up Create a parameter query in Access Help.

Additional note - 1st March 2005


A possible public function to do this date-reversal (and to be used wherever needed) is:

Public Function myUSADate(prmUKDate As Date) As Date

'Convert date from dd/mm/yyyy (UK) format to mm/dd/yyyy (USA) format

Dim strDate As String

strDate = Month(prmUKDate) & "/" & Day(prmUKDate) & "/" & Year(prmUKDate)

myUSADate = CDate(strDate)

End Function

And it would be used in an embedded SQL statement as follows:

DoCmd.RunSQL "INSERT INTO TempDate VALUES (#" & myUSADate(dtDate) & "#)"

Use the Debugger Immediate Window to test the function, and specify dates as dd mmm yyyy
to avoid confusion, as Access also dates dates specified as dd/mm/yy in this window to be USA
format. For example:

?myUSADate(#1 mar 2005#)

Further note - 6th April 2006

If you create a wizard combo box to find records using a date field, then Access generates the
following code to convert the dates to USA format:

"#" & Format(Me![cboFindDate], "mm\/dd\/yyyy") & "#"

(where cboFindDate is the name of the combo box)

Back to Top
15. Why does a calculated date give the wrong result in an SQL statement?

Access 2002 Help says:

You must use English (United States) date formats in SQL statements in Visual Basic.
However, you can use international date formats in the query design grid.

(Search with dates in SQL)

If you have a form with a date field called txtStartdate, a variable called dtDate of Date datatype,
and a table called TempDate with just one column for a date, then the following statements will
all insert the correct date in the destination table:

dtDate = txtStartDate

DoCmd.RunSQL "INSERT INTO TempDate VALUES (#" & dtDate & "#)" from
variable

DoCmd.RunSQL "INSERT INTO TempDate VALUES (#" & txtStartDate & "#)" from form

DoCmd.RunSQL "INSERT INTO TempDate VALUES (#" & Date & "#)" todays
date

However, if you want to do a calculation on a date (calculate a date a library book is due back,
for example) statements such as

dtDate = DateAdd("ww", 2, Date) add 2 weeks to today

'dtDate = DateAdd("d", 14, Date) alternative method

DoCmd.RunSQL "INSERT INTO TempDate VALUES (#" & dtDate & "#)"

will treat the date returned from the DateAdd statement as being in mm/dd/yyyy format (I.e. USA
format). So you will need to reverse the day and month elements of the date, as demonstrated
in VBA FAQ 14 above. Putting the date in a textbox on a form and then using the value from
that textbox does not work, even though the textbox displays in correct UK format!

If the day number value of the date is greater than 12 (20/2/2005 for example), Access
seems to realise that the date is in UK format and will make adjustments itself (20 th
February 2005). But if not (3/5/2005 for example), it will assume USA format (5th March
2005 rather than 3rd May 2005).
Back to Top

16. Why don't the Date and Time functions work in my module?

Some students have experienced problems where a call in VBA code to the Date() or
Time() function returns Null or an invalid/incorrect value (and this can cause a run-time
failure 'invalid use of Null' in some cases).

The problem seems to occur in a form or report module where there is a table, report or
form field called Date or Time. If you code something like:
Dim dtDate as Date
dtDate = Date() 'get system date
then Access appears to refer to the field called Date, not to its own function. (It would be
handy if this situation gave rise to a compilation error or a specific run-time error, then at
least you know what was going on).

Solution 1.
Don't use the names Date and Time for table, form or report fields.
(The Chelmer Leisure database from McBride does use these names, unfortunately).

Solution 2.
Create your own functions in a separate Access module. As the module is not bound to
a table or query, there is no conflict between names, and Access will use its own
functions correctly. Code the following two procedures:
Public Function myDate() As Date
myDate = Date
End Function
'-----------------------------------------------------------
Public Function myTime() As Date
myTime = Time()
End Function
Then code as follows to get the system date and time:
Dim dtDate as Date
Dim dtTime as Date
dtDate = myDate() 'get system date
dtTime = myTime() 'get system time

Back to Top

17. Why doesn't my 'On Error' code trap the error?

Check that you are using the same version of MS Access as MS Office.
For example, if you are using MS Access 2003 with MS Office 2002, then the 'On Error'
code does not appear to be invoked; any error condition is intercepted by Access with
the usual Access error message and the code will fail.

However, if you use an Access 2002 MDE file created with Access 2002, and then run it
on a machine that has Access 2003 with Office 2002, all appears to work OK.

Back to Top

18. How can I get totals on a form?

You may have something like an Order form with a separate (or sub) form for each
Order Line, and want to show the order totals (from counting/adding information from
the order lines) on the Order form.

Look at the 'Crash Course' in Access Basics document.

The relevant bit is section 5.5, Exercise Frm4, 'put totals on a form', part (b). The
example here counts up a total number of attendees at a class (using the Chelmer
Leisure scenario), using DCount. If you want to add up order totals (i.e. total cost of the
order) you will need to use DSum to sum up the appropriate value.

Look also at the VBA Trainers and the Example Databases for examples of use of these
functions.

Back to Top

19. How can I copy details from one form to another?

This is very easily done using the Forms Collection.

There are examples of use in sections 4.3.8 and 8.4.6.2 of the 'Getting Started' VBA
Trainer (available from the Student Advice Centre) and Appendix I discusses this
Collection briefly.

Suppose (for example) you have a customer form which opens an Order form, and you
want to copy customer details to the Order form automatically. You would code the
assignment statements in the Form_Load event for the Order form.

Look also at the Example Databases for examples of use of the Forms Collection.

Back to Top
20. What does Run-time error 3061: Too few parameters. Expected 1
mean?

I have had this error when using the OpenRecordset method (DAO code) when I have
misspelled a table field name in the SQL. After experimenting a bit, I found that it also occurs
with some SQL syntax errors. So - the error probably means that the SQL is incorrect and
cannot be run.

If you misspell the table name with SQL in DAO code then you may get run-time error 3078
instead; this has a very clear error message explaining the likely cause of the error.

Look at the end of section 6.6 of the Getting Started VBA Trainer for a list of common
mistakes when writing embedded SQL using the DoCmd.RunSQL method; this list also
applies to SQL embedded in DAO code.
Back to Top

21. How can I search for files outside my database?

This is very easily done using the Search Folders Collection. Look in Access VB Help using
Search Folders and at the article at http://msdn2.microsoft.com/en-
us/library/aa164017(office.10).aspx

The FileSearch item apparently is deprecated in Access 2007. I haven't tried it in 2007 yet, so
don't know what this means in practice. See http://allenbrowne.com/Access2007.html .

In order to use the various methods and properties you first need to install the MS Office 10.0
Object Library (via Tools-->References from a code window).

Access VB Help has example code that shows you how to use the Collection, and display the
found filenames in message boxes (but it omits to show you that you need to declare some
variables first).

The code shown below has been used by me to locate linked image files. The path of the
images folder is in a table called Path which has just one field called Path (and just one row).
The code reads the filenames (excluding the full path) and puts them into a table called
ImageName which has one field called ImageFileName. This code is called when the
application starts, so the ImageName table is refreshed to show the list of images currently
available.

Public Sub myFindImages()

'must install Microsoft Office 10.0 Object Library to use this

'install via Tools-References from a code window

'code adapted from VBA Help for SearchSubFolders Property


Dim i As Integer 'loop counter for the files found

Dim fs As FileSearch 'FileSearch Object

Dim strLookIn As String 'path to search in

Dim intLen As Integer 'length of folder path

Dim intLen2 As Integer 'length of path + filename

Dim strSQL As String 'SQL to add filename to table

Dim strFilename As String 'filename (no path)

'get path of folder from path table

strLookIn = DLookup("Path", "Path") 'get path of images folder

intLen = Len(strLookIn)

strLookIn = Left(strLookIn, intLen - 1) 'remove backslash at the end

'delete previous entries from image list table

strSQL = "DELETE * FROM ImageName"

DoCmd.SetWarnings False

DoCmd.RunSQL strSQL

DoCmd.SetWarnings True

'find each file in images folder and add filename to image list table

Set fs = Application.FileSearch 'assign this application's file search property to the FileSearch Object

With fs

.LookIn = strLookIn 'specify the folder to be searched

.SearchSubFolders = True 'if want to look in subfolders as well

.Filename = "*" 'look for all folders - won't find anything if this line missing

If .Execute() > 0 Then 'do the search - returns 0 if no files found

For i = 1 To .FoundFiles.Count 'for each file found...

intLen2 = Len(.FoundFiles(i)) 'full path for file


strFilename = Right(.FoundFiles(i), intLen2 - intLen) 'strip off just the filename

strSQL = "INSERT INTO ImageName VALUES('" & strFilename & "')"

DoCmd.SetWarnings False

DoCmd.RunSQL strSQL 'put filename into table

DoCmd.SetWarnings True

Next i

Else

MsgBox "There were no files found."

End If

End With

End Sub

Back to Top

22. How can I capitalise the words that make up a name?

See below for a function to capitalise the initial letters of words. This takes into account the
following characters:
(apostrophe) as in OHara
- (hyphen) as in Parker-Bowles
(space) as in Burton On Trent

To use the function code something like: Name = myWordCase(Name)

in the After_Update event for the field Name.

Access 2003 (and after) has a constant vbProperCase which can be used to convert names
with spaces in them:

Town = StrConv(Town,vbProperCase)

But this doesnt appear to take account of names with apostrophes or hyphens.
Public Function myWordCase(prmString As String) As String

'takes a given string and changes the start letter of each word to uppercase & the rest to lower case.

'looks for space, apostrophe and hyphen to denote start of a new word.

Dim intLen As Integer 'stores num of chars in prmString

Dim intCounter As Integer 'counter for position within the string

Dim strString As String 'variable for working on the given string

strString = LCase(prmString) 'start by converting all chars to lower case

'Left(strString, 1) = UCase(Left(strString, 1)) 'can't use this - get rt-error 424 'object required'

Mid(strString, 1, 1) = UCase(Mid(strString, 1, 1))

intLen = Len(prmString)

For intCounter = 1 To intLen 'check each char in turn for space, apostrophe or hyphen

If Mid(strString, intCounter, 1) = " " _

Or Mid(strString, intCounter, 1) = "'" _

Or Mid(strString, intCounter, 1) = "-" Then

If intCounter + 1 > intLen Then 'is next position outside end of string?

Exit For 'yes - exit loop

Else

'convert char after found char to upper case

Mid(strString, intCounter + 1, 1) = UCase(Mid(strString, intCounter + 1, 1))

End If

End If

Next 'go round again

myWordCase = strString 'return the converted string


End Function

Back to Top

23. What does "The current field must match the join key '?' in the table..." mean?

The full text of the message is: "The current field must match the join key '?' in the table
that serves as the 'one' side of the one-to-many relationship. Enter a record in the 'one'
side table with the desired key value, and then make the entry with the desired join key
in the 'many-only' table".
(It really would help if the message identified the field and the table...)

This occurred with a student final year project and took me several hours to sort out.
Details are below:

Background
The project had an order form based on a query joining the orders and customer tables:
tblCustomer (CustID, Forename, Surname, CustomerType,...)
tblOrder (OrderID, CustID, OrderDate, ...)
qryOrder (SELECT tblOrder.OrderID, tblOrder.CustID, tblCustomer.Forename, ...)
The idea was that the CustID field on the order form be a combo box based on
customer details, the user would select the customer who is placing the order, and the
customer detail fields would then be populated on the form.
The error message above occurred when attempting to place a new order and selecting
a customer from the combo box.
The student database was a .mdb database, and the error occurred when running
under Access 2002, 2003 and 2007.

Cause of the error


The form used an option group for the CustomerType, bound to the field on the
Customer table, but the Orders table was (correctly) the table with the primary key in the
query qryOrder. It appears that this binding causes the error - I'm guessing this is
because of the way Access handles option groups and tries to match values in the field
with values specified in the option group.
When the binding was removed, the error no longer occurred.
If a combo box, or a simple text box, was used for the field, even if bound, the error did
not occur.

Solution
The option group should be unbound.
In the Form_Current event write code to move the CompanyType value (perhaps from a
hidden field on the form, or use something like DLookup) to the frame for the option
group:
IF Not IsNull(OrderID) Then 'existing record
Frame99 = CompanyType
End If
Write the same line in the CustID_AfterUpdate event:
Frame99 = CompanyType
This worked in the project mentioned above.

Back to Top

24. How can I send emails from my database?

Three possible methods of doing this are listed below:

(a) Hyperlink datatype


It is possible to use a hyperlink datatype for an email address in a table (and thus for the
associated field on a bound form). Clicking on the address in the form field will open
your default email client with the email address inserted in the To row ready for you to
complete the email.
If the user wishes to edit the field then he/she must click and hold in order to be able to
do this.

(b) Hyperlink button


Create your email address field as a standard text field.
Create a non-wizard command button on the form. Set this to be a hyperlink by typing
anything (doesn't have to be a valid email or anything sensible) in the hyperlink
property.
Then, in the button click event type something like:
cmdSendEmail.HyperlinkAddress = "mailto:" & txtMemberEmail
When the user clicks on the button, the button hyperlink address will be set to the
appropriate value for the value in the email field text box, and the default email client will
open as before.

(c) DoCmd.SendObject method


This needs a bit more VBA code but can be more flexible as you can set up various
parts of the email (address[es], subject, message, etc) and can choose to have the
email open in the default email client or be sent automatically. The example database
Sending Emails uses this method.
Feb 2009. The example database attached here shows how to send an attachment with
an email. This document shows Access 2002 Help for DoCmd.Send Object (this gives a
bit more information than the Help in Access 2007).
You might also like to look at
http://www.utteraccess.com/forums/showflat.php?Board=84&Number=1597715

Back to Top

25. What does "Run-time error '3251': Operation is not supported by this type of
object" mean?

You are using a property or method that is not available at this time (though the line that
fails has compiled).

This occurred for two students who were attempting to use the FindFirst method for a
Recordset. When declaring the Recordset the second parameter had been omitted. In
Access 2003 (or earlier) this did not matter as the default was (or appeared to be)
dbOpenDynaset. However, these databases were created with Access 2007. It may be
that the Access 2007 default is now something else.

So code the open command as:


Set rstName = dbName.OpenRecordset("tblName", dbOpenDynaset)
not
Set rstName = dbName.OpenRecordset("tblName")

Back to Top

26. Why does my loop code cause Access to hang?

I recently (March 2009) hit this problem with a couple of loops using DAO Recordsets. The loop
processing was quite complex, with a lot going on for each record, involving further loops (to
process further Recordsets and strings) and DLookup statements..

When I tested the loops initially using breakpoints and MsgBox statements to trace execution all
was well. As soon as I removed the breakpoints and MsgBox statements the code just hung
at the start of the main loop.

My colleague Matthew Dean supplied the answer; he thought that this could be a disk cache
problem. Having the MsgBox statements allows the cache to clear any writes to take
place. What could be happening is that the loop is hogging the system and the code is failing
as a result. He suggested that I try coding the command called DoEvents which tells the
system to do what it needs to do. This worked a treat under both Access 2002 and Access
2007.

All I did was code just DoEvents at the point in the code where previously I was using the
MsgBox statements (thus ignoring the value retuned by the function) so that it executed every
time through the loop.

Access 2002 and 2007 VBA Help have the information shown below about the DoEvents
Function:

(Access 2007 also has an example which stores the value returned by the function, and
executes the command every 1000 times around the loop)

Yields execution so that the operating system can process other events.

Syntax

DoEvents( )

Remarks

The DoEvents function returns an Integer representing the number of open forms in stand-alone versions
of Visual Basic, such as Visual Basic, Professional Edition. DoEvents returns zero in all other
applications.

DoEvents passes control to the operating system. Control is returned after the operating system has
finished processing the events in its queue and all keys in the SendKeys queue have been sent.

DoEvents is most useful for simple things like allowing a user to cancel a process after it has started, for
example a search for a file. For long-running processes, yielding the processor is better accomplished by
using a Timer or delegating the task to an ActiveX EXE component.. In the latter case, the task can
continue completely independent of your application, and the operating system takes case of multitasking
and time slicing.

Caution Any time you temporarily yield the processor within an event procedure, make sure the
procedure is not executed again from a different part of your code before the first call returns; this could
cause unpredictable results. In addition, do not use DoEvents if other applications could possibly interact
with your procedure in unforeseen ways during the time you have yielded control.

Back to Top

27. What does "Runtime error 3027 - cannot update. Database or object is read-
only" mean?
This error has occurred with students using DAO code where the Recordset SQL has
involved a standard SQL join as a WHERE clause. Queries with this type of join cannot
be updated by Access (I don't know why!) - Access can only update queries where the
table join is coded using its own version of INNER/LEFT/RIGHT JOIN (an Access join).

See also Access FAQ 28 Why cant I enter data into my form? - the problem is the
same.

A way round the problem in DAO code is as follows:


1. Create a query to select the records for the recordset.
2. If necessary use the Forms Collection for criteria to pick up the required records
(the criteria values can be put in hidden fields on a form if they are not on a form
already).
3. Make sure the table join is an Access join (remove your WHERE criterion and
draw the usual line to join the tables in the query design window).
4. The SQL for the recordset will now be of the form: "SELECT * FROM Query1".
This method also has the advantage that you can test out your query before using the
recordset.

Back to Top

28. Why does DoCmd.SendObject to send emails cause Access 2010 to crash?

I don't know why this occurs but I found a fix that worked in my database.
I was checking the library references (via Tools-->References) in a code window and
noticed that the ActiveX Library was above the DAO library. I only use DAO code and
usually have these library references the other way round (so that DAO takes
precedence). So I swapped the references and sending the emails now worked OK. My
default email client is Outlook Express.

I found some items on the web from people who also had this problem but none of the
first few I checked seemed to suggest why this was happening or how to fix it.
http://www.utteraccess.com/forum/DoCmdSendObject-t682420.html looks a useful
alternative method. I paste the code below in case the link changes or is removed:
Function MailParameters()

'this code was posted by Ricky Hicks April 16th 2005

Dim outApp As Outlook.Application, outMsg As MailItem


Set outApp = CreateObject("Outlook.Application")
Set outMsg = outApp.CreateItem(olMailItem)
With outMsg
'.Importance = olImportanceHigh
.To = Me.eMailAddress
'.CC = "CC EMAIL ADDRESS GOES HERE"
'.BCC = "BCC EMAIL ADDRESS GOES HERE"
' .Subject = "YOUR SUBJECT GOES HERE"
' .Body = "YOUR_E-MAIL_MESSAGE_GOES_HERE"
'.Attachments.Add "YOUR FILE PATH AND NAME", , , "YOUR FILES NAME"
' If you want the screen to be seen then add the following line
.Display
'.Send
End With

Set outApp = Nothing


Set outMsg = Nothing

End Function

Back to Top

29. How can I change a report or chart RowSource SQL at run-time (dynamically)?

If you have a report based on form parameters, and/or one that uses the TOP clause,
then you can set the RowSource property SQL in the Report_Open event. See Access
FAQ 24 How do I select the top/bottom rows of a query dynaset?, the extra bit
added April 2010.

Me.RecordSource = strSQL
'where strSQL = a string variable in which you have set up the required SQL

However, setting the SQL in the RowSource property for a chart isn't as simple. I tried
using various events to set this property, but without any luck. then I came across the
following page which provides a simple solution that does the trick:
http://www.pcreview.co.uk/forums/error-setting-rowsource-using-vba-chart-
t3417699.html
1. Create a query for the chart - it doesn't really matter what it does as it will be
changed later (see point 3 in this list).
2. Go to the property box for the chart and change the RowSource to use the new
query.
3. In the Report_Open event code the following:
CurrentDb.QueryDefs("qryForChart").SQL = strSQL
If the chart is based on the data for the report then you can use the same strSQL
variable
Back to Top

************************************End of VBA Q&A*************************************


Some useful new features for Access 2000
Date last changed: 26/03/11

home

1. Compact on Close
2. Name AutoCorrect
3. Subdatasheets
4. Show 4-digit years for Short Date
5. Conditional Formatting
6. Data Access Pages

Compact on Close

Instead of having to remember to repair/compact your database, you can now specify that you want
Access to do this automatically whenever you close the database.

Click the 'compact on close' box on Tools Options: General tab.

See also What does the message "Table 'TempMSysAccessObjects' already exists"
mean?
Name AutoCorrect

The Name AutoCorrect option allows you to propagate field name changes in tables in fields to queries,
forms and reports. Previously you would have had to make the changes separately in each area affected.

Click the required boxes in the 'Name AutoCorrect' option on Tools Options:
General tab.
Subdatasheets

Subdatasheets in table datasheet view now let you see information from related tables.

Use the + sign by the ID field. See also Format Subdatasheet and try the options.
Show 4-digit years for Short Date

Provides the ability to show 4-digit years for Short Date, rather than the default 2 digits, via Tools
Options: General tab.

See also Help for 'Use four-digit year formatting'.

Now that we are just past the start of a new century it is important to show many dates in a 4-digit-year
format.
4-digit year formats should always be used for dates of birth.
See below to see the change in the property box for date fields when this option is set.
Conditional formatting

This feature gives you the ability to define conditional formatting of form and report controls based on
values in the current row, without writing VBA code or macros. It is very similar to that in Excel, and as
easy to use.

Some examples of situations where this can be used are:


Highlighting overdue membership on Membership form
Highlighting free slots on BookingGrid form
Highlighting overdue membership renewal on a report
Highlighting negative amounts on a financial statement

Highlighting overdue membership on Membership form


Open the form in design view, click on the required control (in this example it is the [date of last renewal]
field), choose Format-->Conditional Formatting, and set the condition and formatting as required. In the
example below, the condition is that the last renewal date is before (less than) a year ago (today's date
minus 365 days). The formatting chosen has been to use bold font with a red background.

This is an example of comparing the field value with a numeric expression, here using the built-in function
Date(). You could also use a function of your own; see Highlighting overdue membership renewal on a
report - this method uses a function that will also allow for leap years.

And this is what the form looks like:


Highlighting free slots on BookingGrid form

In the BookingGrid form used in Part 6 of the Further VBA Trainer, it is now possible to show booked slots
as grey so that the free slots stand out better. It was not possible to do this in Access 97, even with VBA
code.

Open the form in design view, click on the required control (in this example it is the [FSuite] field), choose
Format-->Conditional Formatting, and set the condition and formatting as required.

It is not possible to use 'Null' or '=Null' here as a direct comparison with the field, as what you enter will
then be taken as a string text for comparison. You need to use an expression with Null.
And this is what the BookingGrid form now looks like, with the booked fields showing with a grey
background. If you wanted to remove the class and membership numbers as well, a simple method would
be to set the font to the same colour as the background.
Highlighting overdue membership renewal on a report

This example uses the 'member for n years' report from Section 2.11 of the Getting Started VBA Trainer.
That report used VBA code to set the formatting to highlight members listed whose last renewal date was
a year or more ago.

The example below sets the font to blue if the renewal is overdue. The expression is that from the VBA
code shown in Fig 2.11.3 of the Getting Started VBA Trainer, and shows that it is possible to use a user-
written function (in this case myCalculateAge) in a conditional formatting expression.
And the resultant report looks like:
Highlighting negative amounts on a financial statement

The example here is a very simple 'bank statement' report. There are three places in the report where a
negative balance can show, the brought/carried forward balances, and an intermediate balance during
the statement.

The screen below shows how to use conditional formatting to test the bound report field [last balance] for
a value less than zero:
And the result of this is:
The running balance and the carried-forward value are both unbound text fields, with the values in them
calculated using VBA code. Applying conditional formatting here does not seem to have any effect,
possibly because the field is a textbox (although defined as currency) and is being compared with a
numeric value? This therefore has to be coded using VBA:
If txtBalance < 0 Then
txtBalance.ForeColor = vbRed
txtBalance.FontBold = True
Else
txtBalance.ForeColor = vbBlack
txtBalance.FontBold = False
End If

Data Access Pages

You can now create Data Access Pages (objects that include an HTML file) for users to view, browse and
edit database information via the Internet or over a company's local Intranet. This feature requires that the
user has MS Internet Explorer 5 or higher on their machine plus an Office 2000 licence, so the pages will
not be suitable for full use over the Internet with all browsers.

This replaces previous publishing facilities in Access 97.

It provides the ability to create dynamic HTML data access pages for publishing. See database window -
data access pages are created/edited via the usual tables/queries/forms/reports/modules list.

See also Data Access Pages.


Example Databases
Last Updated 24/03/11
home

There are various little databases on, or linked to, this page for students to access and
look at.

The HCI is pretty basic, as the databases are only 'quick and dirty' ones created to
illustrate a way of solving various problems.

Creating custom primary keys


Car Booking (method will also work for other situations where an item is booked
rented, hired... for a period of whole days)
Mailing Letters
Multi-purpose queries amended 30/3/2010
Staff Holiday Booking
Cinema Seat Booking
School Tests
CD Collection
Birthdays
Lucky Numbers
Bingo
Listbox97
Attendance Registers
Orders database
Event History demonstration
List Box Filter
Sending Emails
Linking Images
Opening Word (and other) Documents
Importing/Exporting Spreadsheet Data
Subform Referencing
VBA Wizard Code New March 2011

Some other links with example databases are:


http://www.databasedev.co.uk/downloads.html
http://office.microsoft.com/en-us/help/HA011201381033.aspx
http://www.access-programmers.co.uk/forums/forumdisplay.php?f=64
http://www.rogersaccesslibrary.com/OtherLibraries.asp
Creating custom primary keys
Points demonstrated:
Using a Recordset to control a 'last used key' table (see code for Student and
Class forms).
Using a Recordset and the Seek command to check if a user key already exists
(see code for Stock form).
Displaying a message on three lines (see code for Stock form). 5/12/2003 - this
works in Access 97 but not in Access 2000/02. Use VB Constant vbCrLf to start a
new line in a message.
Combining an AutoNumber key with a prefix (see code for Member form).

The methods that you have probably used so far in labwork and assignments is to use
either an AutoNumber key or to enter your own key values. Some of you may also use
the field format to 'add' a prefix letter to an AutoNumber key, but this method can cause
problems if you do not realise that the prefix only appears on the format, not on the
actual data!

Sometimes you would like an AutoNumber key with a prefix (e.g. Member No =
M123456 or Student No = 03123456 [where 03 = the year of registration] ), or to have
your own control over a 'last used key' value.

Allowing the user to allocate their own keys can also be problematic as Access does not
check to see if the key already exists until after the user has completed the form and
then tries to save it - most annoying! So you will need to do the check yourself.

All this really quite easy. Click here for example Access 2000 database which
demonstrates methods of doing different types of keys. Look at the code for each form
module to see comments and code.

Class form: where "C" = 1st char of key and "123456" = value from a table which
keeps track of last key used

Member form: where "M" = 1st char of key and "123456" = value from
AutoNumber field

Stock form: User key - coding to here to show how to check if key is already in
use. Key construction and allocation here will be under the control of the user.
(for stock, key could be made up of several factors - item, size, colour, etc).

Student form: where "yy" = year digits as 1st 2 chars of key and "12345" = value
from a table which keeps track of last key used. This table would normally be
reset to start again from 1 for each academic year, so AutoNumber is not
appropriate here.

If you wanted to show AutoNumber keys with leading zeros, then simply change the
field format property in table design view. For example, set the format property
to 000000 if you wanted the number to show always as 6 digits.

Car Booking
Points demonstrated:
A query with several lines for the criteria
Using a NOT IN subquery.
Setting a listbox to Invisible initially, and changing it to Visible and requerying it
(to show the latest results) when a command button is pressed.
The example here can also be adapted for booking, hiring, renting... items that are
booked for whole days between two dates, such as hotel room bookings.

See the example database and explanation document on the FAQ page.
This example is the second of three examples showing how to use NOT IN sub queries.

Mailing Letters
Points demonstrated:

Individual letter, saved with date- and time-stamp. Details entered via a form. Drop-
down boxes used to include set information. Enabling/disabling of command buttons.
Hidden fields on report, combined (concatenated) into one field for the letter.
Individual one-off (not saved) letter. Details entered via form.
Reminder letters for missed appointment where letter details are entered via a form and
details saved for reference/re-use. Date- and time-stamped.
Mail merge with query based on system date where command button calls Word for user
to open and print the letters.
Mail merge with query based on date parameter on a form, demonstrating how to do
this via a Make Table query, deleting the table after it has been used and suppressing
various Access information messages. This process calls the code to open Word, used by
the previous process.
General: Use of forms collection to transfer data between forms; Date- and time-
stamping of records; putting database version number on forms; opening forms in
Add mode (blank record).
This example arose out of a query from an HNC Project student who was designing a
system for an Optician's Practice and was then extended following a request from an
MSc student. Examples of using mail merge with Word were also added.

You can find an Access 2000 example database here and an explanatory document
here.

You might also like to look at How do I reconnect a mail merge Word document
when I have moved the Access database?

Multi-purpose queries
Points demonstrated:
Using the wildcard character ( * ) to create variable parameter queries.
The wildcard cannot be used with date ranges, so an alternative method is
demonstrated.
Use of the Forms Collection to reference fields on another form.
Setting the sort order for a report at run time.
Using colour on a report for fields determined at run-time.
Using a 'Field List' combo box so that the user can select column names for
sorting the report version 2 of database 30/3/2010
Searching through controls to find a specific text box (rather than hard-coding the
name) version 2 of database 30/3/2010
(The method shown here may not work if you are using a calculated value or a value
from a function. You may have to use the IIF function in the query criteria. See the
Birthdays example database for an example of how to do this).

This example arose out of a query from an HND project student who was doing a
project for a local hospital. The hospital wanted to analyse data by a number of criteria
such as date of birth, postcode, nature of illness. They wanted to vary the criteria each
time the query was run.

See example databases, discussion and explanation document on the FAQ page for
VBA FAQ #4.

Note: There is a procedure in the Getting Started VBA Trainer that shows how you can
calculate a person's age from their date of birth. If you put this procedure in an Access
module in your database you can then reference it in a query to provide a column that
will show the age. You could have a calculated column something like: Age:
myCalculateAge([the date])
Staff Holiday Booking
Points demonstrated:
Form and subform.
Use of the forms collection to reference fields on another form.
Use of a procedure in an access module (to calculate the total holiday days
between any two given dates). This procedure uses a While loop.
Using embedded SQL and a Recordset to check for the dates on the
BankHolDate table.
Combo box to find a record on a form (wizard).
DSUM VBA domain aggregate function, used to show the overall total days
holiday so far for each staff member.
Hidden textbox on a form used as a flag; set when a command button is clicked
and used by code elsewhere.

Click here for a copy of the database.

This example arose from an enquiry from a student on placement. The organisation
wanted a database to record and calculate staff holidays. It works only for one year; for
a real system it needs to be extended to have a Holiday and BankHolDate table
(and associated forms) for each holiday year, possibly with associated command
buttons on a main menu. This database probably needs yearly maintenance as well, to
remove old year forms and add new year forms. The Holiday table has field validation
conditions set for the dates to be in 2003 and a record validation condition set to check
that the end date is not before the start date.

The example database has three tables...


Staff contains very brief details for this example (could be extended as
required, for email address, room no, tel. no, job title, date joined, splitting the
name into two fields, etc)
Holiday records each period of holiday (start and end dates) booked for a staff
member
BankHolDate records each bank holiday etc date for the year.

...and two forms:


Staff based on the staff table, with the Holiday form as a subform. New staff
and holiday details can be entered via the form, and details can also be
amended.
Holiday based on a query (qryHoliday), which contains the details from the
Holiday table plus the number of days holiday booked. The number of days
holiday is thus calculated each time the form is displayed. Note that this total is
not stored in the holiday table, as it can be derived from the holiday dates, so
would constitute redundancy if it were stored. If the BankHolDate table has
changes made to it then these changes will be reflected automatically in all
calculations. The calculation is done by the procedure myCalcHolDays in a
separate Access module.
There is VBA code behind both forms, much of which you should be able to follow. But
there are two things that may need further explanation:
The txtSumOfDays textbox on the Staff form. This shows the total number of
days taken and is updated in the Holiday Form_Current event using the DSUM
function, so that it always shows the latest total of days taken.
The purpose of the hidden textbox txtAddRec on the Staff form. If the user
chooses to add a new record the DSUM function fails as there is no StaffID yet
available for the new member of staff. So the record navigators at the bottom of
the form are switched off and an Add Member command button is used instead.
This button sets txtAddRec to True when clicked, so that the Holiday
Form_Current event can know to avoid running the DSUM function. (Note
DSUM is one of several Domain Aggregate Functions available within VBA.
These are very useful.)

Cinema Seat Booking


Points demonstrated:
Disabling and Enabling a command button.
Use of the forms collection to reference fields on another form.
Use of the DSUM and DCOUNT VBA domain aggregate functions to work out
booking and seat counts.
This database arose from a query by a Final Year Project student. He wanted to know
how to work out availability of seats when a booking was placed. The cinema seats
were not numbered; customers just turned up and sat where they liked.

Click here for the example database.

The database here has four tables:


Customer - may not be relevant to all applications, though some details would be
useful if payment is made in advance, or if the cinema wants to contact
customers in the event of a cancellation or if the cinema is only a club for
members.
Film - the title (and possibly other details) of the film. A film could be shown more
than once.
Showing - for the dates and times of each showing of a specific film.
Booking - to record the customer details and the number of seats booked for the
showing.

There is one form, called Booking.


This has a list box showing only those film showings with a date after today.
There is a (greyed-out initially) command button to make a booking.
When a list box entry is clicked, the Make Booking button becomes active and
the form shows the availability of seats for that booking.
There is a procedure called CalculateSeats which uses the domain aggregate
functions DSum and DCount to work out the availability. This is called when a list
box entry is clicked (to show the current availability) and again when the booking
is made (to refresh the availability information on the form).
Enter a Customer Id, and click on the Make Booking button to see what happens.
Look at the VBA code behind the form.

School Tests
Points demonstrated:
Use of the forms collection to reference fields on another form.
Disabling and Enabling a command button when an entry in a list box is clicked.
Outer Join query upon which the Results form is based.
This database arose from a query by an HND Project student who was writing a
database for a school to record SAT results.

Click here for the example database.

The database shows a possible method of selecting the required test, then entering the
results against each student name. An Outer Join query is used for the results form, to
show existing marks and also where marks have not yet been entered.

The database uses the same class list for each test. The scenario probably needs to be
extended to allow the School to choose both the class and the test for the results form.

There is some VBA code behind each form.

CD Collection - example databases


Points demonstrated (in CD Collection version 2):
Form, subform and 'subsubform'.
Use of the forms collection to reference fields on another form, and on a
subform.
Fields set to Invisible initially and then changed to Visible by code. See Artist
form - code for Add Artist command button.
Using the AllowAdditions property on the Track and Artist forms to remove the
'new record' row at the end initially, but put it back if the user wants to add a new
track or a new artist.
Creating a command button, deleting it, but using the generated code for a
procedure. See code for Track form.
Using outer joins for queries by artist/title.
Suppression (i.e. not printing) of selected lines in a report.
Preamble

Explanation document (Word 2000)

Click here for a copy of CD Collection - version 1 Access 2000

Click here for a copy of CD Collection - version 2 Access 2000

Preamble

This page contains an explanation of, and links to, two example databases for a CD
collection.

The databases on this page were originally developed by Mary Spence following an
enquiry from a student who had just started the module COMP1003 (Systems and Data
Analysis for Database Design), and who was trying to apply his knowledge to a
database to record details of his CD collection.

They are linked here for the information and (possibly) interest of other students, to
provide further examples of the use of database design, implementation and code using
MS Access.

They are just 'quick-and-dirty' implementations, thus are not perfect (far from it). The
forms need to be developed further to provide a better, more error-proof, and more
attractive interface for the user. The attributes may need to be refined to fit the particular
requirements of a specific collection. You may like to consider making Title a separate
table.

Feel free to use these example databases for your own CD Collection. Possibly use
your skills to extend them to cover records, cassettes, videos, DVDs, etc. If you think
your extended version could be of use to others, and wish to make it freely available,
please send me a copy to post here.

Birthdays
Points demonstrated:
Starts with the Birthdays form opened and ready. This requirement is set in
Tools--> StartUp.
Use of the Forms Collection to reference fields on another form - VBA is used
to set up appropriate values on a form called from the Birthdays form. This code
also uses the MonthName function to convert from a month number to the
month in words. (Access 2000+ now has a WeekdayName function, but be
careful, you need to specify vbSunday as the first day in the week, or else the
result is incorrect).
Enabling a command button via VBA code when data is entered in a field.
Use of IIF function for a criterion in a query, to cater for optional parameter
entered (or not) in a field on a form.
Use of Month and Day functions for query criteria.
Setting validation conditions in unbound controls.
Setting a postcode to upper case using the UCase function on a labels report.
This database extends an example used in a CSCI1403 (Introduction to Database
Implementation) lecture. There is a Read Me table (and a Read Me report, to make
reading the table easier) explaining the database and the features.

Click here for the example database.

Lucky Numbers
These databases each generate 6 random numbers in the range 1-49, and present the
results in a list box on a form. They show alternative ways of achieving the same result.

Version 1 - No tables are used; there is just one form and the code behind the
Form_Open event.
Click here for the example database.
Points demonstrated:
One-dimensional array - elements initialised to 0 and set to 1 when the
corresponding number has been chosen.
Rnd function (and the Randomise statement) to generate random numbers.
For...Next loop to initialise an array.
Do...Loop to get each number.
Dynamic additions to the Row Source property of a form list box at run time.

Version 2 - Creates and drops a temporary table. This version is discussed in version 5
of the Getting Started VBA Trainer.
Click here for the example database.
Points demonstrated:
Using embedded SQL to CREATE and DROP a temporary table.
Using the DCount function to check for duplicate numbers.
Using embedded SQL to INSERT new numbers into the temporary table.
Commented-out code also shows how to CREATE and INSERT for a more
complex table.
Rnd function (and the Randomise statement) to generate random numbers.
Do...Loop to get each number.
Form has unbound list box which is bound at run-time by code to the Row
Source property to display the numbers in the temporary table.

Bingo

Points demonstrated:
Conditional formatting in frmBingo to 'remove' the numbers when they have
been chosen; font and background are both set to grey when the cell content = 0.
One-dimensional array to ensure that numbers are not chosen more than once
- elements initialised to 0 and set to 1 when the corresponding number has been
chosen.
One-dimensional array used for the field names of the columns on frmBingo.
The corresponding entry in here is then used for the embedded SQL to update
the chosen number in tblBingo to 0.
For...Next loop used to initialise the column name array (see frmBingo
Form_Load event).
While...Wend loop used while checking for next unique number. This uses a
Boolean variable for the loop control.
Rnd function (and the Randomise statement) to generate random numbers.
Mod operator used to work out the column from the number.
Embedded SQL used to update tblBingo, to set the entry for the chosen number
to zero. This SQL demonstrates how to use values from variables and how to
split an SQL statement over several lines of code. See frmBingo.
Redrawing (using Repaint) frmBingo after tblBingo has been updated, to show
the latest number 'removed' from the grid.
Deleting a table using embedded SQL. See frmStart.
Creating a table from another, via a Make table query.
Dynamic additions to the Row Source property of a form list box at run time.

This database has two tables and two forms.

Tables:
tblBingo - used for frmBingo and the game.
tblBingo bak - the master table, used to refresh tblBingo for each new game.
Forms:
frmStart - opens when the database opens. The code behind New Game button
deletes tblBingo, recreates it from tblBingo bak, and opens frmBingo for the new
game.
frmBingo - the actual game. This is a tabular form based on tblBingo. Conditional
formatting is used to 'remove' the numbers when they have been chosen.
Use Tools-->Options, Edit/Find tab, and then clear the Action Queries check box, to
suppress the various Access information messages when the make-table query is run.
Added later - you could also alter the code to use DoCmd.SetWarnings to suppress
these messages; see the end of section 6.2 in the Getting Started VBA Trainer. This is
probably the better method as it applies to the application rather than just the machine
on which the application is run.

Click here for a copy of the database.

Listbox97
Access 2002 has some new features for list boxes where the RowSourceType
property is Value List. These include the AddItem and RemoveItem methods.

The Listbox97 database linked here is an Access 97 database, demonstrating how to


add and remove rows using just the facilities within Access 97 (and Access 2000). It
uses the Len and Mid functions to count through the Rowsource property looking for
the semi colon (;) data separator.

The Listbox97-2000 database is as above, but converted to Access 2000 file format.

Attendance Registers
There are two example databases here, showing two different possible methods of
approaching the problem of recording and analysing attendances.

Common points demonstrated


Crosstab queries.
Building queries upon other queries.
Using the FormatDateTime function in a query to format the date as Short
Time.
Concatenating fields into one field for a query
Calculated columns in queries.
Use of the combo box Column property to reference values in a selected
combo box row.
The Forms Collection, in VBA code and for query parameters.

Attendance Register 1

Other points demonstrated:


Passing a label and a check box as parameters to a procedure.
Using the ABS function to get the absolute value of a total when adding up ticks
in checkboxes.
This uses a very simple method, and assumes each class occurs a fixed number of
times.

Click here for example database and explanatory document.

Attendance Register 2

Other points demonstrated:


Outer join queries.
Use of a NOT IN subquery to allow a Crosstab query to use a parameter
value on a form. See also VBA FAQ 14 How can I add a criterion to a Crosstab
query? and section 8.4 of the Getting Started VBA Trainer for a further example
of the use of a Crosstab query.
Embedded SQL to delete rows and add a row to a table. Also uses
DoCmd.SetWarnings to suppress Access warning messages.
Use of IsNull function to see if the user has selected a value on a form.
Use of DCount function to check to see if there are any students registered for a
class.
Deleting a selected record on a form by calling wizard Delete record command
button code, after deleting the button.
Requery of a form after bound data has changed in order to show the new data.
Use of the IIF function for a variable query criterion to select all pupils or just a
selected pupil.
Using a Crosstab query in another query and selecting all columns.

This is a more complex but more flexible method, allowing for varying occurrences of
classes.

Click here for example database and explanatory document.

Orders database
This database was originally developed to assist a FY Project student doing a customer
purchasing database.

It shows how to create Order and corresponding OrderLines, with stock quantity
updated as items are recorded as sold.
It restricts amendment of existing orders.
DAO and embedded SQL code are used to add stock back if an order is
cancelled (say, customers credit card not accepted).
I have not had time to develop this into anything more useful or write an explanatory
document, but there are extensive comments in the VBA code so I hope you can work
out what's going on. Note that the HCI is very basic and needs a lot of improvement.

Click here for the example database

Event History demonstration


The database attached here has been written by my colleague Dr. Peter Bounds to
show the events generated on a data entry form for recording membership of a leisure
centre. It shows how form and control (text box, button, etc) events are triggered and
the order in which they occur, and will help you understand how events happen and
how they can be used.

The database contains two forms:


1. EventHistory form. This form opens first and has a text box on it into which is
recorded details of each event that takes place on the second form. The second
form is opened in the Form_Load event of this EventHistory form.
2. Membership_Events form. This form is based on the Membership table of the
Chelmer Leisure scenario used in McBride. There is code behind most of the
form and control events which simply writes a line in the EventHistory form text
box to record which event has been triggered. Thus, when the database is first
opened, the textbox shows the events that occurred when the
Membership_Events form was opened. When you move between fields, press
buttons, close the Membership_Events form, for example, you will see the list of
new events being triggered. The Clear button on the EventHistory form can be
pressed to restart the list of events if it gets too cluttered with old events.

List Box Filter


The database attached here shows how to filter the contents of a list box with each
character entered into a text box.
The database opens with a form which has a list box using data from the
Chelmer Leisure Membership table.
The form has a textbox into which the user types the starting characters of a
member's last name, and the list box contents change with each character typed
(or backspaced). The Membership form (just a simple wizard form here) can then
be opened using the list box to indicate the required Member (double-click on the
selected list box row).
The form also has a Reset button which clears the textbox and restores the list
box contents.

Points demonstrated
Use of the Requery method on a list box.
List box SQL using Like for SQL WHERE clause.
Use of the Forms Collection in the list box SQL.
Use of the text box KeyPress event to get each character the user types, check
for backspace, and use the Chr function to convert the ASCII character code to a
string. This uses a hidden field on a form to build up the characters checked by
the list box SQL.
Use of the Len function to check the number of characters currently in the string
(need to know when to stop backspacing).
Use of wizard code for an 'open form' command button. The button was created
to open the form selecting records where the Membership No matched the entry
in the list box. The button was then deleted, and the wizard code used as a sub
called from the list box DoubleClick event.

Sending Emails
The database attached here is an extract from the CSE Student Monitoring database,
and shows the form used to show students on a selected Course and Year with their
total attendance for a specified time-period in the current academic year. This form is
used by year tutors to email students who have poor attendance. It can also be used to
email all the students. Students are selected for emailing by clicking on a tick box. The
email subject line is set to contain the student name(s), except when more than one
student is selected and BCC (blind carbon copy) is used.

Points demonstrated
Requery method on a form.
Use of wizard code for a 'save record' command button. The button was deleted
and the code used as a sub which could be called to force a save of selections
of records.
Enabled property to enable and disable a command button.
DCount function to check if at least one student has been selected.
OrderByOn property (can only be set in VBA, I think) and the OrderBy property
(set in the form property box) to set the order of records to the Student name
rather than the student ID.
DAO code to bookmark a record so can return to it after the form has been
requieried. This code uses the same method as that used by the wizard combo
box code to find a record.
DAO code to read the selected records to set up email addresses and subject
line.
DoCmd.SendObject to send the email. The user has the option of using a BCC
address list or a normal address list.
A combo box with contents based on the student records (attendance field)
shown on the form.
A common procedure to select/deselect records. This uses the IsMissing
function for an optional parameter value. The code then uses Embedded SQL
(and DoCmd.SetWarnings) to update the form table tick boxes if the user
wishes to select/deselect all, or select those with attendances <= the value in a
combo box.

Linking Images
This database implements the linking in of images to an Access form. The images are in
a separate folder from the database, as discussed in Access Q&A #34 "Should I
embed or link images into my database?"

Click here for a zipped folder which contains the images folder and the example
database.

Points demonstrated
Pathname for image folder stored in separate path table and read when form
opened. The data table stores just the filename for each image. If the image
folder is moved then just the pathname in the path table needs to be altered.
Use of image control Picture property to store the linked path and filename at
run time to display the picture.
Uses procedures (more flexible, especially if you have more than one form and
a separate images folder for each form) and a file picker window dialog using
FileDialog. added March 2008
File picker dialog window to allow the user to select image files from a given
folder (but I do not know how to prevent the user from changing the directory in
the file picker dialog). The Mid function is then used to strip the full path off to
get just the filename for storing in the table record. added March 2008

Opening Word (and other) Documents

The database attached here was created for a Final Year Project student who wanted
the user of her system to record certain details on a Word document rather than in a
'Comment' field in a table. This facility would enable the document to be formatted and
printed out, and could thus prove more flexible than recording these details in a table.

This facility could also be useful for reading files of other types, for example: PDF files
(scanned documents such as application forms, correspondence, plans - the
documents could be set to 'read only' if necessary); images (useful perhaps for estate
agent systems). Simply change/remove the coding in the attached database that checks
for documents with Word file extensions.

The method used here is similar to that for the Linking Images example, in that it is
assumed that all documents for a table are put into the same folder, however it is simple
to adapt it to allow documents from any location accessible by the database.
Click here for a zipped folder which contains the documents folder and the example
database.

Points demonstrated
Pathname for documents folder stored in separate path table and read when
form opened. The data table stores just the filename for each document. If the
document folder is moved then just the pathname in the path table needs to be
altered.
Changing a command button to be a hyperlink which then opens an existing
document with the Follow method, using the path and filename together to get
the full path for the document. The code was developed following an example
from Access 2002 VBA Help. This appears to work OK in Access 2007. Adapt
this code to open other file types if required, as mentioned above.
Using Access 2002 Command Button Wizard code for opening Word to create
a new document. This appears to work OK in Access 2007, although this wizard
facility is not available in Access 2007 (perhaps because Access 2007 now has a
facility for attachments?). The user must remember to save the document in the
required folder used by the database, and must then select the document in
order to store the name in the data table - this is all a bit 'clunky' but is the best I
can think of at present
Uses procedures (more flexible, especially if you have more than one form and
a separate document folder for each form) and a file picker window dialog using
FileDialog.
File picker dialog window to allow the user to select document files from a
given folder (but I do not know how to prevent the user from changing the
directory in the file picker dialog). The Mid function is then used to strip the full
path off to get just the filename for storing in the table record.

Importing/Exporting Spreadsheet Data

The example database attached here follows the example in section 7.3 of the Getting
Started VBA Trainer.

Click here for a zipped folder containing the database, an Excel spreadsheet to import
and a sub-folder into which the database will export.

Points demonstrated
Using the TransferSpreadsheet method to import and export data.
Using a data range area defined in the import spreadsheet.
Public Subs to import and export.
Attaching the system date and time to the export filename.
Checking for error conditions on import.

Subform Referencing

The example database attached here shows how to use the Forms Collection to
reference controls, properties and methods in a subform from the main form.

The database is based on a 'real-life' database where the client was creating a multi-
purpose query to allow the user to query data by different combinations of criteria
(similar to that demonstrated in the Multi-Purpose Queries database example).

The database has two forms: a main form with query criteria from which the user
chooses, and Search and Reset buttons; a tabular format subform which displays the
selected data.

There are just two query criteria in the example:


1. A simple criterion selecting member records by gender (Male/Female/All). This
criterion is on the query for the subform.
2. A more complex criterion to allow the user to select ages <, =, or > a selected
age. I don't think it's possible to do this with a query criterion (at any rate, I
couldn't work out how) so I added it to the query SQL in the subform
RecordSource property at run-time.

Points demonstrated
The Forms Collection to reference a control on the subform:
Me!SubformBasedOnQuery!txtTotal=...
The Forms Collection to reference a property on the subform:
Me.SubformBasedOnQuery.Form.RecordSource=...
The Forms Collection to reference a method on the subform:
Me.SubformBasedOnQuery.Requery
The Forms Collection with wildcards in query criteria to reference main form
fields.
DCount to add up the number of records displayed in the subform.
Using the same Where condition for the extended RecordSource SQL and the
DCount function criterion.

VBA Wizard Code


Microsoft used to discourage Macro use in favour of VBA code, but from Access 2007
this policy appears to have been reversed. The various form wizards now generate
macros rather than code. In Access 2007 it is possible to convert these wizards to code,
but there is currently a bug in Access 2010 that prevents this conversion.

I find this bug (and, indeed, the reversal of policy) highly annoying as I much prefer to
see, and edit if required, the VBA code. I find macros to be rather inflexible and non-
transparent.

On my Access 2010 page I suggested that if you want to use code for buttons you will
have to code it yourself from scratch. To help you do this I have created a simple .mdb
database in Access 2002 (using an old home PC with Office 2002) with loads of wizard
buttons and code. The 2002 code can be copied/pasted from here to your own
database, and adapted as appropriate. It should still work in Access 2010.

Anda mungkin juga menyukai