uk/Access/Example%20datab
ases.htm#Creating%20custom%20primary%20keys
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
Textbooks
Example databases
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.
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)
Electronic Copies:
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.
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
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).
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.
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.
Other websites
If you find any useful links please email the URLs to the site owner - thanks
VBA Tutor
Another site that you may like to look at (recommended by a Placement student) is
http://www.mvps.org/
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!
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)
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.
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 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 (?).
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)
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,
General:
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 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 .
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...
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 (!).
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:
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
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 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)
Using Access97
Roger Jennings, published by QUE.
Expensive (65!!) (2000)
Very comprehensive reference on Access features, but not too much on VBA.
Plus CD.
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.
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
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.
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.
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:
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).
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.
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
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
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
Access has many date manipulation functions - see Help for a full list.
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
Back to Top
5. I've chosen referential integrity when setting up a relationship, but get an error
message - why?
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
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.
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 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
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
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;
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.
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.
FROM tblDates;
The result of running the query is shown below. 28th February 2005 was a Monday.
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:
Else
End if
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.
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
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.
>=#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.
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.
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.
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 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.
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.
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.
FROM Membership
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.
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).
FROM [Month]
Note that must only select one column for the sub query.
UNION
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
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.
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.
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.
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.
3 Set the ForceNewPage property of the section to one of the following settings:
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.
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).
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.
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)
(b) Choose the Booking table, then the [Date] field for the row headings.
(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.
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).
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
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:
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.
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
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
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:
Mr J Perry Mr J. Perry
Mr D Harris Mr D. Harris
Mr I Shangali Mr I. Shangali
Mr G Weiner Mr G. Weiner
Mr D Ali Mr D. Ali
Ms A Young Ms A. Young
Mr I Gray Mr I. Gray
Mr A Everett Mr A. Everett
Mr L Locker Mr L. 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)
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:
counter)
exit for
else
end If
end If
Suggested logic 2:
Do
Exit Do
Else
End If
End If
Loop
Back to Top
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.
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.
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.
Back to Top
"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.
Back to Top
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!).
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.
FROM Membership
(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:
Back to Top
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:
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:
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.
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 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.
Back to Top
31. Why is my event code ignored? (e.g. click on button but nothing happens)
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
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
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?
The article recommends using linked images for Access 2003, for various reasons concerned
with:
One way to avoid having to refresh the image paths with linked images could be:
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?
"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".
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:
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).
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
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
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
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?
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.
Back to Top
***********************End of Access Q&A**********************************
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
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
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).
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
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.
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.
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'.
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).
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
Back to Top
Back to Top
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.
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
Method 1:
Method 2:
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.
faq705-3734
Before you use the Round() function in Access, please read this FAQ or you may introduce
calculation errors into your application:
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:
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.
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:
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
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.
'put decimal point back in original position and return the rounded value
myRound = dblIntegerPart / (10 ^ prmPlaces)
End Function
Back to Top
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.
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):
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.
1. Create a new table called TempCat, with a numeric field called Category No.
3. Alter the Crosstab query criterion to IN (SELECT [Category No] from TempCat), so that the
SQL now looks like:
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!
Do Until dtDate > CDate(txtEndDate) 'loop until end date has been passed
'so must reverse day and month before putting in SQL statement
strDate = Month(dtDate) & "/" & Day(dtDate) & "/" & Year(dtDate)
DoCmd.RunSQL "INSERT INTO TempDate VALUES (#" & strDate & "#)"
Loop
Access Help.
strDate = Month(prmUKDate) & "/" & Day(prmUKDate) & "/" & Year(prmUKDate)
myUSADate = CDate(strDate)
End Function
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:
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:
Back to Top
15. Why does a calculated date give the wrong result in an SQL statement?
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.
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
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
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
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.
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
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
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.
intLen = Len(strLookIn)
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
.Filename = "*" 'look for all folders - won't find anything if this line missing
DoCmd.SetWarnings False
DoCmd.SetWarnings True
Next i
Else
End If
End With
End Sub
Back to Top
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
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.
'Left(strString, 1) = UCase(Left(strString, 1)) 'can't use this - get rt-error 424 'object required'
intLen = Len(prmString)
For intCounter = 1 To intLen 'check each char in turn for space, apostrophe or hyphen
If intCounter + 1 > intLen Then 'is next position outside end of string?
Else
End If
End If
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.
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
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.
Back to Top
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.
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()
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
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.
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.
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.
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.
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
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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-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.
Attendance Register 1
Attendance Register 2
This is a more complex but more flexible method, allowing for varying occurrences of
classes.
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.
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
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.
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.
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.
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.