Frequently Asked Questions for MS Access and Access VBA

 

Last updated 17/04/11

 

home

 

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

 

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

 

Useful links:

http://support.microsoft.com/kb/146864 Error trapping with VBA

http://msdn.microsoft.com/en-us/library/aa264975(VS.60).aspx core (trappable) VBA Errors

http://msdn.microsoft.com/en-us/library/aa338172(VS.60).aspx miscellaneous VBA errors

http://msdn.microsoft.com/en-us/library/aa338178(VS.60).aspx additional VBA information

http://www.mdbrecovery.com/mdb-corruption.html some steps to avoid a corrupt database

Also use Google advanced search (type/paste in the 'exact wording or phrase' box) to look for entries for a particular error message.

 

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

 

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

 

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

 

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

 

 

Make sure that you have enough space on your disk!

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

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

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

 


 

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

 

 

Access Q&A

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

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

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

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

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

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

  7. I'm setting up a validation rule and get the message "Error evaluating CHECK constraint in the validation rule". What does this mean?

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

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

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

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

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

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

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

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

  16. How can I combine column values to form just one column in a query?

  17. What is a CROSSTAB query?

  18. What is an Outer Join?

  19. Can I compact my database automatically?

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

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

  22. How do you use the Calendar Control? amended November 2010.

  23. What is a UNION Query?

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

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

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

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

  28. Why can’t I enter data into my form?

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

  30. Why don’t 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 doesn’t a formatted prefix for an AutoNumber ID show in a combo box?

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

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

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

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

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

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

 

 

VBA Q&A

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

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

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

  4. How can I create a multi-purpose query/report which allows the user to enter a variable number of values each time?  

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

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

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

  8. How can I cater for production of (mailing) letters?

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

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

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

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

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

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

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

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

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

  18. How can I get totals on a form?

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

  20. What does “Run-time error ‘3061’: Too few parameters. Expected 1” mean?

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

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

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

  24. How can I send emails from my database?

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

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

  27. What does "Runtime error 3027 - cannot update. Database or object is read-only" mean?

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

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

 


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

 

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

 

Example - add 1 year to the system date:
=Date()  uses the Date function and will give today's date (the system date).

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

 

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

 

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

 

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

 

Back to Top

 

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

 

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

 

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

 

Back to Top


 

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

 

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

 

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

 

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

 

It is best to set up all relationships before entering data.

 

Back to Top


 

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

 

This can occur if...:

  1. ...you are joining two primary keys. A 1:relationship requires that one key only is a primary key. Check to see that you are joining the correct fields.

  2. ...you are joining a primary and a foreign key and the foreign key is specified as 'no duplicates' in the Index property for that field in the table.
    (a) If the foreign key can have duplicate values in the table (this is the normal situation) then change the Index property to show this.
    (b) If the foreign key really is a unique value in the table then check to see if you need to use a separate primary key for this table; perhaps you can use the primary key from the main table in both tables (as in point 1 above).

You should also check your design carefully. Sometimes a 1:1 relationship is correct (e.g. to save space in the database for information that that doesn't apply to all records, or to put sensitive data in a separate table in order to restrict access). But you need to be able to justify each 1:1 relationship that you have, so that you know that it is correct.

 

Back to Top


 

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

 

There are two common reasons for this:

 

1 - Existing data violates integrity (error message: "Microsoft Access can't create this relationship and enforce referential integrity" - this message is then followed by a nice clear example of what the problem might be).

The most likely reason that either or both of your tables already have data in them but that the data violates the integrity rule. 

Example A: You have data in your membership table but not yet in your category table. The tables will be joined via the category number. As referential integrity requires that all category numbers in the membership table are also in the category table, you must now set data in your category table before creating the relationship.

Example B: You have data in both the membership and the category tables. The likely reason is that you have a category number in your membership table that is not in the category table. Correct your data and try again.

It is safest to set up all validations and rules before entering any data.

 

2 - Key data types do not match (error message: "relationship should be on the same number of fields with the same data type")

The relationship joins two keys - one in each table. These keys should be of the same data type and size. If the primary key of one table is an Autonumber field (LongInteger), then the corresponding foreign key in the other table should be a Number data type, also LongInteger. If one key is a text field, then so should the other one (and of the same size).

 

Back to Top

 


 

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

 

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

If you reply 'No' to the conversion, then the database can be opened and data amended (I think), but no design changes can be made.

 

There is also information regarding conversions to/from different versions in Access Help. Use the keywords

       convert, access

to find the relevant pages.

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

 

Back to Top


 

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

 

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

 

Quotation marks are used in programming (also in Access SQL and expressions) to denote a string literal. The actual contents of these literals are not looked at by the software but are simply used as required. For example      Town = "Chelmer"     where Town is taken to be a data name and "Chelmer" is a string literal.

 

June 2003 (and updated January 2009). This error has also occurred with Recordset DAO code, where a student was writing a record to a table. The table had a field validation rule. This appeared to conflict with the Recordset DAO code and was the cause of the error. When the field validation rule was removed and replaced by validation VBA code then all was well. So, do not use field (or table) validation rules with Recordset DAO code; code all validations using VBA code. If you are coding everything via Recordsets then it would seem more logical to validate data via code anyway.
This error could also occur with embedded SQL with invalid data.

 

Back to Top

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

 

The Documenter gives you several options to choose from:

 

 

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

 

If you want to show all the field validations as well, choose the '...and Properties' option for Fields. Note, though, that this gives a much larger listing, with a load of extra stuff you may not want. You could cut the listing down by publishing it in Word then deleting the stuff you don't want.

 

If you have used the Table Planning Sheet to plan out your table before creating it, then the sheet and the shorter listing could provide a concise method of documenting the table details and field validations.

 

Back to Top


 

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

 

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

 

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

 

Back to Top

 


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

 

Query

 

Example 1

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

 

For example, suppose you have a stock table with entries for stock number, description, unit price and quantity in stock (there will probably be other fields in the table as well). The following will query the stock details plus the total value:

 

 

 

 

The SQL is:

SELECT stock.StockNo, stock.Description, stock.UnitPrice, stock.QtyInStock, [UnitPrice]*[QtyInStock] AS TotalValue

FROM stock;

     

    The result of running the query is:

    StockNo

    Description

    UnitPrice

    QtyInStock

    TotalValue

    1

    Socks

    £5.99

    6

    £35.94

    2

    Handtowel

    £7.95

    43

    £341.85

     

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

     

Example 2 New 8 March 2005 

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

 

The picture below shows a very simple query which uses the built-in Weekday and IIf functions to calculate such a target date.

 

 

The SQL is:

SELECT tblDates.ReceivedDate, IIf(Weekday([receiveddate])=5 Or Weekday([receiveddate])=6,[receiveddate]+4,[receiveddate]+2) AS TargetDate

FROM tblDates;

 

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

qryDates using IIF

ReceivedDate

TargetDate

28/02/2005

02/03/2005

    01/03/2005

03/03/2005

02/03/2005

04/03/2005

03/03/2005

07/03/2005

04/03/2005

08/03/2005

 

 

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

 

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

            IIf(expression, truepart, falsepart)

 

The logic of how it works can be expressed as:

            If expression is true then

               Result = value in truepart

            Else

                Result = value in falsepart

             End if

 

Thus, in this example,

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

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

 

Truepart is         [receiveddate]+4

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

 

Falsepart is        [receiveddate]+2

2 days are added to the (Monday to Wednesday) date for the required working date this week

 

 

 

Form or Report

 

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

 

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

These alternative methods are discussed in more detail in section 3.2 of the Getting Started VBA Trainer.v5.

 

 

See also:

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

VBA FAQ 5 How do I update a table value via a form?

 

 

Back to Top


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

 

When you are doing initial testing or if you make mistakes entering data and delete a row, the AutoNumber field keeps incrementing from the last number used. You may wish to start from 1 again (perhaps with existing data or perhaps after deleting initial test data).

This is very simply done as follows:

WARNING 1 - if you have a table joined to this one, with the second table using the AutoNumber field as a foreign key, then renumbering the first table will upset all the relationships, as the data will no longer correspond.

 

WARNING 2 - if you are using the AutoNumber key as a base for a second key field key of the form M000001, where you have VBA code on the form that affixes "M" to the front of the AutoNumber key, then the second key field will NOT be changed automatically by this method. You would need to do an Update Query to reset the second key field, for example:

UPDATE Member SET Member.[Membership No] = "M" & Format([Memb No Auto],"000000");

Where [Memb No Auto] = the AutoNumber key

and [Membership No] = the second key field

and the calculation is that already used on the form.

 

Back to Top


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

 

Consider the 'date of joining' field in the Membership table of the Chelmer Leisure database. The management may want to know answers to questions to such as:

- How many people joined in 1992?

- How many people joined in each month of 1992?

- How many people joined each year?

 

You specify the criteria as normal for the column in the Query Design screen, or the WHERE / HAVING section of SQL. The table below shows some examples. Note that some of the details have calculated columns that make use of the date functions, Date, Year and Month.

Access has many of these date manipulation functions.

For an example showing calculated columns and the functions, see after the table.

 

Criteria

Column(s)

Result

>=#01/01/92# And <=#31/12/92#

Date of joining

Selects data between the two dates shown

If used for a query requiring totals, will group by all the separate dates, not by the year.

Between #01/01/92# And #31/12/92#

Date of joining

As above.

Year(Date())-1

Date of joining

Selects data for last year.

Year(Date())-Year([date of joining])<4

 

Date of joining

Selects data where the year of the date of joining is less than 4 years ago.

<DateAdd("yyyy", -4, Date())

New - 8 March 2005

Date of joining Selects data where the date of joining is less than 4 years ago. The DateAdd function is used to 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

New - 8 March 2005

Year([date of joining]) Similar to above, but checks the value in a textbox called txtYear on a form called frmReports. This uses the Forms Collection.

none

Year([date of joining])

Use this to group for a count of members joining by year.

1992

and

none

Year([date of joining])

and

Month([date of joining])

This uses two calculated columns to select by month for 1992 - see example below.

 

 

Query Design screen for the last example, counting membership joins by month for 1992:

Experiment with some of the other examples above and see results.

 

SQL for the above example:

    SELECT Month([date of joining]) AS Month, Count(Membership.[Membership No]) AS Total

    FROM Membership

    GROUP BY Month([date of joining]), Year([date of joining])

    HAVING (((Year([date of joining]))=1992));

 

 

Result of running the query: 

(the year column is suppressed here as it will be the same for all rows).

Month

Total

2

1

4

2

6

3

7

1

8

1

 

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

 

 

The Forms Collection.   New - 8 March 2005

 

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

 

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

 

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

 

 

Date manipulation functions.   New - 8 March 2005

 

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

 

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

 

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

 

 

VBA Help   New - 8 March 2005

 

To see VBA help, you need to be in an open code window. (If you don’t 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:

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 don’t, follow the examples below to set up the full SQL.

 

 

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

 

Query1 - select the membership numbers of the members who did make a booking last year:

SELECT DISTINCT Membership.[Membership No]

FROM Membership INNER JOIN Bookings ON Membership.[Membership No] = Bookings.[Membership No]

WHERE (((Year([Date]))=Year(Date())-1));

You may need to add the word DISTINCT if creating the query via Query Design. It is not essential, but does reduce the size of the result of query1 and thus may (?) speed up query2.

 

Query2 - create a query to select the required fields, and in the criteria for the Membership No column do:

- enter : NOT IN (

- paste the SQL for query1

- replace the semi-colon (;) at the end of the SQL for query1 with a closing round bracket

- your SQL will now be of the form:

SELECT [Membership No] <,any other field(s) required>

FROM Membership <,any other tables required>

WHERE [Membership No] NOT IN (SQL for Query1);

The second select here is known as a subquery. Access may add loads of extra brackets here, which can be a bit confusing.

 

Actual SQL, selecting the three fields shown is:

SELECT Membership.[Membership No], Membership.Lastname, Membership.Firstname

FROM Membership

WHERE Membership.[Membership No] NOT IN (SELECT DISTINCT Membership.[Membership No]

FROM Membership INNER JOIN Bookings ON Membership.[Membership No] = Bookings.[Membership No]

WHERE (((Year([Date]))=Year(Date())-1)));

Alternative method, referencing intermediate queries directly, rather than using the full SQL:

    SELECT Membership.[Membership No], Membership.Lastname, Membership.Firstname

    FROM Membership

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

this might be a simpler method to use.

 

 

Example 2 - click here for an example car booking database (Access 2000). This has just 2 tables, Car and Booking, with a form in which to enter the two dates for the hire period. There are two queries; Booked (the 1st query) and Free (the 2nd query, which uses the SQL from the 1st query for the NOT IN subquery). Have a play with it and see how it works. I think it covers all conditions, but it is up to you to test it thoroughly in your application! There are two versions of the Free query (called Free and Free2; one with the full SQL, and one referencing the Booked subquery by name).

Click here for a Word document with further explanation.

There is just a small amount of VBA code behind the form, for the two command buttons. The Booked button code is generated by the 'run query' form wizard. The Free button code is my own, to operate a list box which shows the details of the cars that are free.

 

 

Example 3 - The Chelmer Leisure management want a graph showing numbers of members who joined in each month in 1992.

 

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

 

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

 

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

 

Stage 3 - create a new query ("months with no bookings") which uses a NOT IN subquery:

SELECT DISTINCT Month.Month, 0 AS Total

FROM Month

WHERE (((Month.Month) Not In (SELECT Month([Date of Joining]) AS Month

FROM Membership

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

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

The result of this new query is then

Month

Total

1

0

3

0

5

0

9

0

10

0

11

0

12

0

Note how to create a column with a fixed value in it. Look to see what the Query Design screen looks like.

Note also that the subquery SQL is the same as that for the 'totals by month in a year' query, but omitting the 'Total' column, as the subquery must have only one column.

 

Stage 4 - open a new query, do not choose any tables, go to the SQL view and do the following:

(a) paste in the SQL for the 'totals by month in a year' query - deleting the semi-colon (;) at the end

(b) add the word          UNION

(c) paste in the SQL for the 'months with no bookings' query (do not delete the semi-colon at the end).

 

You now have a UNION query, with SQL like:

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

FROM Membership

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

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

UNION

SELECT DISTINCT Month.Month, 0 AS Total

FROM Month, Membership

WHERE (((Month.Month) Not In (SELECT DISTINCT Month([Date of Joining]) AS Month

FROM Membership

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

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

Note that for UNION queries, the results of each query must be of the same format (i.e. same number of columns with the same data types in the same order).

 

Run this and see what you get! You can then use this new query result as the basis for a graph.

 

See also What is an Outer Join?

 

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

SELECT DISTINCT Month, 0 AS Total

FROM [Month]

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

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

 

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

SELECT * FROM [Totals by months in a year]

UNION

SELECT * FROM  [months with no bookings]

ORDER BY Month;

 

 

Back to Top


 

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

 

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

 

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

 

Back to Top


 

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

 

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

 

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

 

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

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

 

 

 

Page breaks in reports

 

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

 

 

Add a page break to a report

 

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

 

1          Open the report in Design view.

2          Click the Page Break tool    in the toolbox.

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

 

Microsoft Access marks the page break with a short dotted line on the left edge of the report.

 

If you want each group or record in a report to start on a new page, set the ForceNewPage property of the group header, group footer, or detail section.

 

 

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

 

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

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

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

 

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

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

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

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

 

Notes

 

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

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

 

 

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

 

1          Open the report in Design view.

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

3          Open the report's PageHeader_Format event procedure.

 

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

 

Me![CondPgBreak].Visible = False

 

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

 

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

 

If Me![Counter] = 10 Then

            Me![CondPgBreak].Visible = True

End If

 

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

 

 

Back to Top

 


16. How can I combine column values to form just one column in a query? For example, join forename and surname, or show first initial and surname?

 

In order to join fields you use the concatenation character

&             (ampersand).

Remember to allow for space characters between fields where necessary.

 

Query column showing the full name.

Enter the following for the Field row in the Query:

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

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

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

 

Query column showing the first initial.

Enter the following for the Field row in the Query:

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

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

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

 

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

 

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

 

Back to Top


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

 

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

 

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

 

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

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

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

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

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

(d) Choose the Count Function.

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

Date

Total Of Booking No

Court 1

Court 2

Court 3

Fitness Suite

Sports Hall 1

Sports Hall 2

13/05/1996

5

1

 

 

2

1

1

14/05/1996

4

 

 

1

3

 

 

15/05/1996

5

1

 

 

1

 

3

16/05/1996

5

 

1

 

1

 

3

17/05/1996

3

 

 

 

1

 

2

 

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

 

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

 

Example using SQL (example with more than one table)

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

Create a query with the following SQL:

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

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

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

   GROUP BY Year([Date of Birth])

   PIVOT [Membership Category].[Category Type];

 

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

 

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

 

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

 

See also VBA FAQ 14 How can I add a criterion to a Crosstab query?

 

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

 

Back to Top


 

18. What is an Outer Join?

 

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

 

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

 

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

 

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

 

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

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

   INTO [Totals by Month]

   FROM Membership

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

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

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

 

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

 

 

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

 

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

Month

Total

1

 

2

1

3

 

4

2

5

 

6

3

7

1

8

1

9

 

10

 

11

 

12

 

 

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

 

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

 

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

 

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

 

Back to Top


 

19. Can I compact my database automatically?

 

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

 

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

 

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

 

Back to Top


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

 

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

 

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

 

Back to Top


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

 

See later on this section for logic for a possible own VBA function to do this.

 

The example here demonstrates several useful features:

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.

Query to create Initial and Fullname:

 

Result of query:

Title

Initial

Lastname

FullName

Mr

A

Walker                  

Mr A. Walker

Mrs

D

Cartwright              

Mrs D. Cartwright

Mr

J

Perry                   

Mr J. Perry

Miss

A

Forsythe                

Miss A. Forsythe

Miss

D

Jameson                 

Miss D. Jameson

Miss

P

Robinson                 

Miss P. Robinson

Mr

D

Harris                  

Mr D. Harris

Mr

I

Shangali                

Mr I. Shangali

Mrs

M

Barrett                 

Mrs M. Barrett

Mr

G

Weiner                  

Mr G. Weiner

Mr

D

Ali                     

Mr D. Ali

Ms

A

Young                   

Ms A. Young

Mr

I

Gray                    

Mr I. Gray

Miss

F

Swift                   

Miss F. Swift

Mrs

S

Davies                  

Mrs S. Davies

Mrs

R

Robinson                

Mrs R. Robinson

Mr

A

Everett                  

Mr A. Everett

Mr

L

Locker                  

Mr L. Locker

Miss

A

Locker                  

Miss A. Locker

Mr

E

Jones                   

Mr E. Jones

 

 

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

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

A suitable function header could be:

Public Function myInitials(prmString As String) As String

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

 

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

 

Suggested logic 1:

get first initial (hint – use Left)

get length of string (hint – use Len)

For each char in the given string

  If the char = space then    (hint – use Mid)

       position to next char  (hint – add 1 to loop

                                                         counter)

       if position is outside end of string then

            exit for

       else

           add char after the space to the initials

                     so far   (hint – use &)

        end If

     end If

  Next    'go round again

  return upper case initials

 

 

Suggested logic 2:

get first initial (hint – use Left)

get length of string (hint – use Len)

set a counter to 1 for start of string

Do

    find position of space in string   (hint – use InStr)

    If position = 0 Then       ‘char not found

       exit do                     'no (more) occurrences of char

     else

       position to next character  (hint – add 1 to counter)

       If position > length Then

            Exit Do     

        Else

            add to list of initials    (hint – use &)

        End If

    End If

Loop

return upper case initials   

 

 

Back to Top


22. How do you use the Calendar Control?

 

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

 

The calendar control is an Active-X data object that shows a calendar on a form and allows a user to choose a specified date.

 

 

 

It can be used as an alternative to requiring the user to type a date directly into a text box. You need to think carefully which control (textbox or calendar) is appropriate for the given context.

 

 

Putting the control on a form.

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

 

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

 

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

 

 

Showing today’s date

 

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

            ocxCalendar.Value = Date

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

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

 

 

Using the Calendar

 

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

 

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

 

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

 

Back to Top

 


23. What is a UNION Query?

 

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

 

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

 

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

 

An example from Help is:

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

 

Back to Top

 


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

 

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

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

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

 

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

 

 

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

 

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

 

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

 

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

FROM Membership

ORDER BY Membership.[Date of Birth];

 

new 3 April 2010

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

 

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

 

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

 

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

  1. Use a combo box on a form, and allow the user to select a value for the 'top n'.

  2. Create the report as usual using your query.
    Group the report on the field being used for the top value.
    Set the required sort order (even though this has been specified on the query it may need to be done again here).
    Note that Access Top will take account automatically of equal value rows (joint positions).

  3. Delete the RecordSource property from the report property box.

  4. In the Report_Open event set up the query SQL in a String variable.
    Use the value from the form combo box for the 'Top' value in the SQL.
    Then assign the value in this String variable to the report RecordSource property.
    The report will now open using the data retrieved by the SQL.

  5. In the Report_Open event set an integer variable to the value 1 (one).
    The first record listed will be number 1 in the 'Top n' list.

  6. In the Detail_Print event, add 1 to the integer variable for each line printed.

  7. In the GroupHeader_Print event show the integer variable value in the header.

An alternative (possibly more challenging) method is:

  1. Read the aggregate query (without the Top clause) into a DAO Recordset.

  2. Read the Recordset row by row from the first record (this means coding a loop), taking account of duplicate values, writing the records to a temporary table (perhaps adding the ‘position’ in the list as a new field, or you can work this out using report event code as for points 6 and 7 above).

  3. Use a combo box on a form for the user to specify the 'top n' value, and stop the loop when the appropriate number of rows have been read and written to the temporary table.

  4. Work out your logic for this before you start to code it!

  5. Then use this temporary table as the basis of the report.

And don't forget to add suitable improvements to your report. Some of these may require VBA; see section 5 of the Getting Started VBA Trainer. See also advice for report design. Improvements to your report should include:

  1. Showing the 'top n' value, and any other query parameters used, in the report or page header.

  2. Catering for an empty report.

  3. Group and report totals.

 

Back to Top


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

 

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

 

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

 

Back to Top


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

 

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

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:

 

Later -  the link at http://support.microsoft.com/kb/818099 gives further information, including how to delete the table.

 

Back to Top


28. Why can’t I enter data into my form?

 

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

 

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

I would guess that the reason is that Access cannot easily identify the table row(s) that would need to be edited, so no editing or additions are allowed.

 

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

 

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

 

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

 

Back to Top


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

 

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

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

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

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

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

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

o         No VBA code is generated.

2        I will type in the values that I want.

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

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

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

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

o         No VBA code is generated.

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

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

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

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

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

 

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

 

Solution:

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 don’t 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 “M”0000 in order to generate key values of “M0001”, “M0002” etc, requiring the user only to enter 0001 and the mask will add the “M”.

 

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

 

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

 

See also the Custom Keys example database.

 

Back to Top

 


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

 

Check the property box for the control.

 

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

 

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

If you now look at the property box, the event link should be present and the control should work when activated.

 

Back to Top


32. How can I lock part of a form?

 

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

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

   or

(b) via VBA code in an appropriate event (for example, the Form_Load event if wanting to set these properties for the form when it first opens).


Some useful properties for non-data-entry fields are:
   set Locked property (Data tab on field property box) to Yes
   set SpecialEffect (Format tab on etc) to Flat
   set BackStyle (Format tab on etc) to Transparent

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

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

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

Back to Top


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

 

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

 

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

 

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

 

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

 

Back to Top

 


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

 

There is a lot of useful information this in Access 2003 at http://office.microsoft.com/en-us/access/HA011472041033.aspx in an article called “Use images in your Access forms, reports, and controls”.

 

The article also has two videos showing:

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

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

 

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

Linked images require the use of a little VBA, though it's not difficult; look at Access Help with “Add a picture or object“. They also mean that you need to refresh the image path if the image folder is moved. But these seem to be the only disadvantages of linking.

 

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

This method is also very useful when testing the application on several different machines; simply change the path to match the location of the files. February 2008 - example database available.

 

Another advantage of linked images is that, if you have a logo that appears on all forms, reports, letters etc produced by the application, then you simply replace the old logo file with a  new one (but with the same name) and the application itself needs no changes.

 

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

 

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

 

Back to Top

 


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

 

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

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

 

The causes for this include:

  1. A compilation error. You should always clear all compilation errors before attempting to run any code. Even better, clear all errors as they arise (code a bit, compile it, test it, repeat...).

  2. Your database is corrupted. This can happen if there is insufficient room on the disk for your database. So Compact your database (save a copy somewhere else first) to remove deleted items and keep the size to a minimum (see also the notice at the top of this page). I have managed to clear the error from a student database by creating a new database and copying each object across from the error database to the new one. I compacted the error database first.

  3. Incompatibility between Access and Office. This error has also occurred with me when running Access 2002 on a machine that had Office 2007 (but not Access 2007) installed. So - ensure that your version of Access and your version of Office are the same.

 

Back to Top

 


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

 

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

    Private Sub cmdClose_Form_Click()

    On Error GoTo Err_cmdClose_Form_Click

 

        If Me.Dirty Then Me.Dirty = False

        DoCmd.Close

 

    Exit_cmdClose_Form_Click:

        Exit Sub

 

    Err_cmdClose_Form_Click:

        MsgBox Err.Description

        Resume Exit_cmdClose_Form_Click

   

    End Sub

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

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

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

 

Back to Top

 


37. Why doesn’t 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 don’t like using VBA. The code is in the RowSource property for the text box txtCategoryNo. Look up the IIF function in VBA Help – it’s a very useful function.

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

Back to Top

 


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

 

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

 

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

 

Back to Top

 


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

 

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

 

Back to Top

 


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

 

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

 

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

 

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

 

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

 

Back to Top

 


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

 

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

 

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

 

Back to Top

 


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

 

See information on the Access 2010 page of this site.

 

Back to Top


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

 

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

It has been removed from Access 2010.

See information on my Access 2010 page.

 

Back to Top

 


***********************End of Access Q&A**********************************


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

 

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

 

You may have a statement such as:

    If member-ID = user-request-ID THEN...

where you are trying to compare two data items. 

 

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

 

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

 

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

 

Back to Top

 


 

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

 

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

 

         Dim BookingTableRecords as Recordset.

 

 

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

 

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

The code shown in the "Further VBA" Trainer should now work in Access 2000.

 

See also:

 

Back to Top

 


 

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

 

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

 

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

 
Back to Top

 


4. How can I create a multi-purpose query/report which allows the user to enter a variable number of values each time? 

Note - the suggestions below mainly use Query Design and the Forms Collection - VBA only really comes into play for checking date ranges or for setting the sort order at run-time for the report.

 

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

 

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

 

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

 

 

The Query

 

When a system is up and running, the user may want to do various one-off queries. The information from these queries may be wanted quickly, and the user will not want to go through negotiations with the system developer to produce the report and arrange a price. It is useful to provide a general-purpose query if possible. For example, the Chelmer Leisure Management (see scenario in Access Further Skills textbook) may want queries such as:

Details of all members with a particular category, with certain dates of birth, with certain sporting interests, by surname, by gender, etc.

Rather than having lots of separate queries, it is possible to create a query that picks up the required values from a form via parameter values in text and combo boxes, etc.

 

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

 

 

Try the following:

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'.
 

All the above has been based on just one table, but it is also applicable to a form based on a query joining two or more tables.

 

 

 

The Report

As a report can be based on a query, then, instead of having the form command button run a variable parameter query, as done above, choose to run a report instead. 

 

The report header should list the parameter values that the user entered in the form fields. This is very straightforward. Create unbound text box field controls in the report header and enter Forms![form name]![field name] in the control to pick up the value from the form (with the appropriate form and field names, of course!). If there is no value in the form, then this will show as blank.

 

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

 

Back to Top

 


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

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

 

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

 

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

 

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

 

The VBA code is as follows:

So, when the form is opened the sale button is disabled. When a sale is recorded, the button is enabled so that the user can click on it to confirm the sale. This activates code that updates the quantity in stock; as the form field is bound to the table row, this will automatically update the table. The button is then disabled to stop the user from clicking on it again; alternatively, the form could be closed.

 

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

 

In a properly designed system, the stock code number would be typed in (simulating a scanner) and the form opened showing just that record. There would also be checks (in the ConfirmSale click event) such as:

The 'Getting Started' VBA Trainer covers validation of data entered into fields on a form.

 

Back to Top


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

 

See the creating custom primary keys example database.

 

Back to Top


 

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

 

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

Look up Maximise and Restore in Help.

Also look up Minimise and SelectObject.

 

Look also at section 4.3.8 in the Getting Started VBA Trainer; this uses the InsideWidth property to set the width of a form at run-time.  This bit added 15/1/2007.

 

Back to Top

 


 

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

 

 

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

 

 

The Mailing Letter example database demonstrates how to:

All except the simple query Mail Merge use VBA.

 

Back to Top

 


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

 

This has happened when one decides to stop the debugger, after replying 'Yes' to 'This command will stop the debugger'.

If you then run the code without the debugger everything is OK.

So it would appear to be caused by the stopping of the debugger, not an error in your code (I think...).

 

Back to Top

 


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

 

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

 

 

Method 1:

 

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

  

Method 2:

 

Public Sub myProc(prmArray as Variant)

  

Both Methods:

 

The array definition in the procedure header does not specify the bounds of the array, but Access provides two useful functions LBound and UBound which determine these at run-time:

       For IntCount = LBound(prmArray) to UBound(prmArray) ...

 

Back to Top

 


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

 

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

 

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

 

Back to Top

 


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

 

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

 

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

 

Example:

Look at the Staff Holiday Booking example database. The Holiday form uses a DSum statement to add up the total holiday days booked:

     Forms![Staff]!txtSumOfDays = DSum("days", "qryHolDates", "[staffId] = " & Me!staffId)

If you change the "days" to "day" for the first parameter to the DSum statement then you will duly get the error message, as there is no field called "day" on qryHolDates.

 

The solution is to look carefully at each element of the SQL or Function, and check that they are entirely correct. Put all SQL in string variables, then you can check the contents at run (i.e. failure) time in the Debugger. It could also be useful to put the 3rd parameter (the SQL criterion) for a Domain Aggregate Function in a variable for checking at run/failure time.

Tip. it can be useful to try the function without the optional 3rd parameter (the SQL criterion). If it does not fail, then the fault is in the criterion, so check that carefully. If it still fails, then the fault lies with one (or both!) of the first two parameters.

See the end of section 6.6 of the 'Getting Started' VBA Trainer for a list of things that cause errors in embedded SQL - many of these also apply to Domain Aggregate Function code.

 

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

 

Back to Top

 


 

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

 

Examples:     Round(4.5,0) returns 4

                       Round(3.5,0) returns 4

 

The answer can be found at http://www.tek-tips.com/faqs.cfm?fid=3734 . The text at this site as at 11:13 6/12/2004 is copied below (as links can sometimes be removed).

(My thanks to Matthew Dean for pointing this site out to me, when I asked him why Round was apparently inconsistent/wrong).

 

 

 

http://www.techonthenet.com/access/functions/numeric/round.htm has a really neat solution! 8/3/2005.

"If you wanted to round 12.65 to 1 decimal place in the traditional sense (where 12.65 rounded to 1 decimal place is 12.7, instead of 12.6), try adding 0.000001 to your number before applying the Round function:

Round(12.45+0.000001,1)

By adding the 0.000001, the expression that you are rounding will end in 1, instead of 5...causing the Round function to round in the traditional way.

And the 0.000001 does not significantly affect the value of your expression so you shouldn't introduce any calculation errors."

 

 

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

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


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

Syntax: Round(expression[, numdecimalplaces])

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

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

Round(2.385,2)

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

2.38 (not 2.39)

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


If this is not the behaviour you expected, then here’s the explanation:

The Round() function does a round-to-even, not the more well-known round-to-larger. If the argument ends in 5, the number may be rounded up or down to achieve an even rightmost figure.

So in our example above:

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

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


A RoundToLarger() function:

Public Function RoundToLarger(dblInput As Double, intDecimals As Integer) As Double
    
    'Implements a variant of the Round() function, that rounds-to-larger
    'rather than rounds-to-even, like in Excel:

    Dim strFormatString As String 'Format string
    Dim strResult As String

    'If input is zero, just return zero. Else format as appropriate:
    If dblInput <> 0 Then
        strFormatString = "#." & String(intDecimals, "#")
        If Right(strFormatString, 1) = "." Then
            strResult = Format(dblInput, "#")
        Else
            strResult = Format(dblInput, strFormatString)
        End If

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


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


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

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

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

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

 

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

 

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

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

    'move the decimal point by the required number of digits
    'example, 4.45 required to 1 decimal place gives 45.5
    dblTemp = prmNumber * (10 ^ prmPlaces)       'note: 10^0 = 1

    'truncate the value to get rid of the unwanted decimal places
    dblIntegerPart = Fix(dblTemp)
    'subtract truncated value from temporary number to find out what the unwanted digits are
    dblDecimalPart = dblTemp - dblIntegerPart

    'are the unwanted digits +0.5 to +0.99999etc or -0.5 to -0.99999?
    If Abs(dblDecimalPart) >= 0.5 Then
        If prmNumber < 0 Then
             dblIntegerPart = dblIntegerPart - 1 'subtract 1 for -ve number
        Else
             dblIntegerPart = dblIntegerPart + 1 'add 1 for +ve number
        End If
    End If

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

End Function

 

 

Back to Top

 


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

 

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

 

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

 

Simple literal criterion.

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

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

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

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

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

    GROUP BY Year([Date of Birth])

    PIVOT [Membership Category].[Category Type];

 

Parameter criterion.

However, if you used a criterion that used a parameter such as [Please enter Category No] or a Forms Collection reference such as forms!frmcategory![Category No], your query would fail with a message similar to:

The Microsoft Jet database engine does not recognise “[Please enter Category No]” as a valid field name or expression.

or

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

 

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

 

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

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

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

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

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

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

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

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

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

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

PIVOT [Membership Category].[Category Type];

The query will now pick up the required parameter value, which can be varied by changing the value in the textbox.

 

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

 

    Dim dtDate As Date

    Dim strDate As String

 

        'delete previous rows from table

        DoCmd.RunSQL "DELETE * FROM TempDate"

 

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

        

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

            'dates in SQL statements must be in USA format

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

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

            'write date to temp table

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

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

       Loop

 

Access Help.

Look up “Create a parameter query” in Access Help.

 

Additional note - 1st March 2005

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

 

    Public Function myUSADate(prmUKDate As Date) As Date

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

     Dim strDate As String

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

        myUSADate = CDate(strDate)  

    End Function

 

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

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

 

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

?myUSADate(#1 mar 2005#)

 

Further note - 6th April 2006

 

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

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

(where cboFindDate is the name of the combo box)

 

Back to Top

 


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

 

Access 2002 Help says:

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

(Search with ‘dates in SQL’)

 

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

    dtDate = txtStartDate

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

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

    DoCmd.RunSQL "INSERT INTO TempDate VALUES (#" & Date & "#)"              ‘today’s date

 

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

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

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

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

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

 

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

 

Back to Top

 


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

 

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

 

The problem seems to occur in a form or report module where there is a table, report or form field called Date or Time. If you code something like:

    Dim dtDate as Date

        dtDate = Date()      'get system date

then Access appears to refer to the field called Date, not to its own function. (It would be handy if this situation gave rise to a compilation error or a specific run-time error, then at least you know what was going on).

 

Solution 1.

Don't use the names Date and Time for table, form or report fields.

(The Chelmer Leisure database from McBride does use these names, unfortunately).

 

Solution 2.

Create your own functions in a separate Access module. As the module is not bound to a table or query, there is no conflict between names, and Access will use its own functions correctly. Code the following two procedures:

    Public Function myDate() As Date
        myDate = Date
    End Function
    '-----------------------------------------------------------
    Public Function myTime() As Date
        myTime = Time()
    End Function

Then code as follows to get the system date and time:

    Dim dtDate as Date

    Dim dtTime as Date

        dtDate = myDate()      'get system date

        dtTime = myTime()     'get system time

 

Back to Top


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

 

Check that you are using the same version of MS Access as MS Office.

 

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

 

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

 

Back to Top


18. How can I get totals on a form?

 

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

 

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

 

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

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

 

Back to Top


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

 

This is very easily done using the Forms Collection.

 

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

 

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

 

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

 

Back to Top

 


20. What does “Run-time error ‘3061’: Too few parameters. Expected 1” mean?

 

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

 

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

 

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

Back to Top

 


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

 

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

 

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

 

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

 

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

 

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

 

Public Sub myFindImages()

'must install Microsoft Office 10.0 Object Library to use this

'install via Tools-References from a code window

'code adapted from VBA Help for SearchSubFolders Property

 

Dim i As Integer                              'loop counter for the files found

Dim fs As FileSearch                       'FileSearch Object

Dim strLookIn As String                   'path to search in

Dim intLen As Integer                      'length of folder path

Dim intLen2 As Integer                    'length of path + filename

Dim strSQL As String                      'SQL to add filename to table

Dim strFilename As String               'filename (no path)

   

    'get path of folder from path table

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

    intLen = Len(strLookIn)

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

   

    'delete previous entries from image list table

    strSQL = "DELETE * FROM ImageName"

    DoCmd.SetWarnings False

    DoCmd.RunSQL strSQL

    DoCmd.SetWarnings True

   

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

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

    With fs

        .LookIn = strLookIn                  'specify the folder to be searched

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

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

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

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

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

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

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

                DoCmd.SetWarnings False

                DoCmd.RunSQL strSQL       'put filename into table

                DoCmd.SetWarnings True

            Next i

        Else

            MsgBox "There were no files found."

        End If

    End With

   

End Sub

 

Back to Top

 


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

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

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

in the After_Update event for the field Name.

 

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

          Town = StrConv(Town,vbProperCase)

But this doesn’t appear to take account of names with apostrophes or hyphens.

  

Public Function myWordCase(prmString As String) As String

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

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

 

Dim intLen As Integer         'stores num of chars in prmString

Dim intCounter As Integer   'counter for position within the string

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

 

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

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

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

   

    intLen = Len(prmString)

 

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

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

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

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

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

                Exit For              'yes - exit loop

            Else

                 'convert char after found char to upper case

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

            End If

        End If

    Next    'go round again

   

    myWordCase = strString        'return the converted string

 

End Function

 

Back to Top

 


 

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

 

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

(It really would help if the message identified the field and the table...)

 

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

 

Background

The project had an order form based on a query joining the orders and customer tables:

    tblCustomer (CustID, Forename, Surname, CustomerType,...)

    tblOrder (OrderID, CustID, OrderDate, ...)

    qryOrder (SELECT tblOrder.OrderID, tblOrder.CustID, tblCustomer.Forename, ...)

The idea was that the CustID field on the order form be a combo box based on customer details, the user would select the customer who is placing the order, and the customer detail fields would then be populated on the form.

The error message above occurred when attempting to place a new order and selecting a customer from the combo box.

The student database was a .mdb database, and the error occurred when running under Access 2002, 2003 and 2007.

 

Cause of the error

The form used an option group for the CustomerType, bound to the field on the Customer table, but the Orders table was (correctly) the table with the primary key in the query qryOrder. It appears that this binding causes the error - I'm guessing this is because of the way Access handles option groups and tries to match values in the field with values specified in the option group.

When the binding was removed, the error no longer occurred.

If a combo box, or a simple text box, was used for the field, even if bound, the error did not occur.

 

Solution

The option group should be unbound.

In the Form_Current event write code to move the CompanyType value (perhaps from a hidden field on the form, or use something like DLookup) to the frame for the option group:

    IF Not IsNull(OrderID) Then    'existing record

        Frame99 = CompanyType

    End If

Write the same line in the CustID_AfterUpdate event:

    Frame99 = CompanyType

This worked in the project mentioned above.

 

Back to Top


 

24. How can I send emails from my database?

 

Three possible methods of doing this are listed below:

 

(a) Hyperlink datatype

It is possible to use a hyperlink datatype for an email address in a table (and thus for the associated field on a bound form). Clicking on the address in the form field will open your default email client with the email address inserted in the To row ready for you to complete the email.

If the user wishes to edit the field then he/she must click and hold in order to be able to do this.

 

(b) Hyperlink button

Create your email address field as a standard text field.

Create a non-wizard command button on the form. Set this to be a hyperlink by typing anything (doesn't have to be a valid email or anything sensible) in the hyperlink property.

Then, in the button click event type something like:

    cmdSendEmail.HyperlinkAddress = "mailto:" & txtMemberEmail

When the user clicks on the button, the button hyperlink address will be set to the appropriate value for the value in the email field text box, and the default email client will open as before.

 

(c) DoCmd.SendObject method

This needs a bit more VBA code but can be more flexible as you can set up various parts of the email (address[es], subject, message, etc) and can choose to have the email open in the default email client or be sent automatically. The example database Sending Emails uses this method.

Feb 2009. The example database attached here shows how to send an attachment with an email. This document shows Access 2002 Help for DoCmd.Send Object (this gives a bit more information than the Help in Access 2007).

 

You might also like to look at http://www.utteraccess.com/forums/showflat.php?Board=84&Number=1597715

 

Back to Top

 


 

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

 

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

 

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

 

So code the open command as:
    Set rstName = dbName.OpenRecordset("tblName", dbOpenDynaset)

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

 

Back to Top

 


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

 

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

 

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

 

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

 

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

 

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

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

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

Syntax

DoEvents( )

Remarks

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

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

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

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

 

 

Back to Top

 


 

27. What does "Runtime error 3027 - cannot update. Database or object is read-only" mean?

 

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

 

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

 

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

  1. Create a query to select the records for the recordset.

  2. If necessary use the Forms Collection for criteria to pick up the required records (the criteria values can be put in hidden fields on a form if they are not on a form already).

  3. Make sure the table join is an Access join (remove your WHERE criterion and draw the usual line to join the tables in the query design window).

  4. The SQL for the recordset will now be of the form: "SELECT * FROM Query1".

This method also has the advantage that you can test out your query before using the recordset.

 

Back to Top

 


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

 

I don't know why this occurs but I found a fix that worked in my database.

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

 

I found some items on the web from people who also had this problem but none of the first few I checked seemed to suggest why this was happening or how to fix it.

http://www.utteraccess.com/forum/DoCmdSendObject-t682420.html looks a useful alternative method. I paste the code below in case the link changes or is removed:

Function MailParameters()

   'this code was posted by Ricky Hicks April 16th 2005
  
   Dim outApp As Outlook.Application, outMsg As MailItem
   Set outApp = CreateObject("Outlook.Application")
   Set outMsg = outApp.CreateItem(olMailItem)
   With outMsg
      '.Importance = olImportanceHigh
      .To = Me.eMailAddress
      '.CC = "CC EMAIL ADDRESS GOES HERE"
      '.BCC = "BCC EMAIL ADDRESS GOES HERE"
'      .Subject = "YOUR SUBJECT GOES HERE"
'      .Body = "YOUR_E-MAIL_MESSAGE_GOES_HERE"
      '.Attachments.Add "YOUR FILE PATH AND NAME", , , "YOUR FILES NAME"
      ' If you want the screen to be seen then add the following line
      .Display
      '.Send
   End With
  
   Set outApp = Nothing
   Set outMsg = Nothing

End Function

 

Back to Top


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

 

 

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

 

    Me.RecordSource = strSQL  

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

 

 

However, setting the SQL in the RowSource property for a chart isn't as simple. I tried using various events to set this property, but without any luck. then I came across the following page which provides a simple solution that does the trick: http://www.pcreview.co.uk/forums/error-setting-rowsource-using-vba-chart-t3417699.html

  1. Create a query for the chart - it doesn't really matter what it does as it will be changed later (see point 3 in this list).

  2. Go to the property box for the chart and change the RowSource to use the new query.

  3. In the Report_Open event code the following:
        CurrentDb.QueryDefs("qryForChart").SQL = strSQL

If the chart is based on the data for the report then you can use the same strSQL variable

 

Back to Top

 


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