Microsoft Access 2000: Building Applications with Forms and Reports |
CHAPTER 8
If you plan to distribute your application to other users, you may want to use the tools that Microsoft® Access provides to make your application easy to install and maintain. This chapter discusses techniques you can use to prepare your application for delivery.
Chapter Contents
Putting the Final Touches on an Application
Setting Startup Options
Separating Your Application’s Tables from Its Other Objects
Documenting Your Database
Database Maintenance
When you have finished developing and testing the database and objects that make up your application, it’s time to put the final touches on your application before you deliver it to users. Think about where your users are located, as well as their levels of database expertise. Also, think about the environment in which your application will run, and the potential for future updates to the database and objects you have developed. Considering such issues will help you create a polished final product that meets the specific needs of your users.
You may want to do any of the following before you distribute your application:
See Also For more information about securing your application, see Chapter 18, “Securing Access Databases,” in the Microsoft Office 2000/Visual Basic Programmer's Guide (Microsoft Press, 1999). You can also find this guide in the Office Developer Documentation section of the Microsoft Developer Network (MSDN) Online Library.
See Also For more information about how to create and use replicas of your application, see Chapter 16, “Multiuser Database Solutions,” in the Microsoft Office 2000/Visual Basic Programmer's Guide (Microsoft Press, 1999). You can also find this guide in the Office Developer Documentation section of the Microsoft Developer Network (MSDN) Online Library.
In addition to the tools and information provided by Microsoft Access to assist you with application development, Microsoft Office 2000 Developer provides tools to help you develop Microsoft® Windows®- and Office-compatible applications. Additionally, Office 2000 Developer includes:
You can set options in the Startup dialog box that determine how your application looks and behaves when it starts. For example, you can:
To display the Startup dialog box, click Startup on the Tools menu.
See Also For more information about using the Startup dialog box, see “Setting Startup Options” in Chapter 1, “Creating an Application.”
If you’re distributing your application to a number of users, or if your data is located on a server, consider using a back-end database to hold the tables that contain your data and a front-end database to hold the application’s other objects (queries, forms, reports, macros, and modules). You can then base all objects in your application on linked tables from the back-end database.
When you separate the application’s data from its objects, you can easily distribute new versions of your front-end database that include upgraded queries, forms, reports, macros, and modules without disturbing the application’s data. Similarly, if you need to exchange one set of data for another or back up your data, you can perform these operations on your back-end database without affecting the objects in your front-end database. And if your data is located on a server, you can reduce the network load and improve performance by having users run the front-end database on their workstations rather than from the server.
Users open and use the front-end database. Because the objects in the front-end database are based on linked tables, changes that users make to the data using these objects change the data in the back-end database. The following illustration demonstrates this configuration.
If you know from the beginning that you intend to split your application into two database files, you can develop the application with this in mind. Or you can keep tables and objects together in the same file and split them only when you’re finished with development and are ready to distribute the application.
The easiest way to split an application after creating its objects is to use the Database Splitter Wizard.
To split an application after creating its objects
The Database Splitter Wizard creates a new, empty back-end database. It moves all tables in the current database to the new back-end database, preserving table relationships and properties. The current database is now the front-end database. The wizard then links each table in the back-end database to the front-end database.
See Also For more information about using linked tables, type linked tables in the Office Assistant or on the Answer Wizard tab in the Help window, and then click Search.
The links used by linked tables in the front-end database are based on the location of the back-end database. If users move the back-end database to a different location, the links will fail. If the current links are broken, you can automate the process of linking tables for your users by prompting them for the path to the back-end database when they start your application. Then you can use the RefreshLink method to refresh your application’s links. To see an example of how this works, open the Developer Solutions sample application in the Samples subfolder of your Office folder. In the upper part of the Developer Solutions form, double-click Use Multiple Databases. In the lower part, double-click Link Tables At Startup. You can download the Developer Solutions sample application and associated Help files from the Microsoft Developer Network (MSDN) Online Web site.
Before you distribute your database to users, you may want to document the objects in your database; the underlying structure, or schema, of your application; and any Data Access Objects (DAO) objects, methods, and properties. This is sometimes called mapping the database. When you have a complete map of your database, it’s easier to modify the database and to write applications that manipulate the data.
If you just need information about application objects that appear in the user interface, you can use the Documenter (Tools menu, Analyze submenu) to produce a report on those objects. However, to obtain information about the DAO objects, properties, and methods that can’t be manipulated by way of the user interface, you must use VBA.
See Also For more information about the Documenter, type Documenter in the Office Assistant or on the Answer Wizard tab in the Help window, and then click Search.
Because DAO objects are organized in a hierarchy of nested containers, you can map the database by walking through the hierarchy with a series of nested For...Each loops. Each element in the collection can be accessed with a statement block with the following syntax:
For Each object In collection
statements' Map the properties of the object.
Next object
See Also For information about individual properties that are exposed when you map a database, type the name of the property in the Office Assistant or on the Answer Wizard tab in the Help window, and then click Search.
The following code maps the current database. For brevity, the Attributes property is fully mapped only for each TableDef object. If you want to map attributes of the other objects, simply use the code for the TableDef object attributes as a model and insert the appropriate statements. This example assumes that the user running this code has at least Read Design permission on all tables in the database.
Sub MapDatabase()
Dim dbs As DAO.Database, tdf As DAO.TableDef, fld As DAO.Field
Dim idx As DAO.Index, rel As DAO.Relation
Dim intX As Integer
OnError GoTo ErrorHandler
Set dbs = CurrentDb
' Map the Database properties.
Debug.Print "DATABASE"
Debug.Print "Name: ", dbs.Name
Debug.Print "Connect string: ", dbs.Connect
Debug.Print "Transactions supported?: ", dbs.Transactions
Debug.Print "Updatable?: ", dbs.Updatable
Debug.Print "Sort order: ", dbs.CollatingOrder
Debug.Print "Query time-out: ", dbs.QueryTimeout
' Map the TableDef objects.
Debug.Print "TABLEDEFS"
For Each tdf in dbs.TableDefs
Debug.Print "Name: ", tdf.Name
Debug.Print "Name: ", tdf.DateCreated,
Debug.Print "Name: ", tdf.LastUpdated,
If tdf.Updatable = True Then
Debug.Print "Updatable",
Else
Debug.Print "Not Updatable",
End If
' Show the TableDef Attributes.
Debug.Print Hex$(tdf.Attributes)
If (tdf.Attributes And dbSystemObject) <> 0 Then
Debug.Print "System object"
End If
If (tdf.Attributes And dbAttachedTable) <> 0 Then
Debug.Print "Linked table"
End If
If (tdf.Attributes And dbAttachedODBC) <> 0 Then
Debug.Print "Linked ODBC table"
End If
If (tdf.Attributes And dbAttachExclusive)<> 0 Then
Debug.Print "Linked table opened in exclusive mode"
End If
' Map Fields for each TableDef object.
Debug.Print "FIELDS"
For Each fld in tdf.Fields
Debug.Print "Name: ", fld.Name
Debug.Print "Type: ", fld.Type
Debug.Print "Size: ", fld.Size
Debug.Print "Attribute Bits: ", Hex$(fld.Attributes)
Debug.Print "Collating Order: ", fld.CollatingOrder
Debug.Print "Ordinal Position: ", fld.OrdinalPosition
Debug.Print "Source Field: ", fld.SourceField
Debug.Print "Source Table: ", fld.SourceTable
' Show the Field Attributes here.
Debug.Print Hex$(fld.Attributes)
If (fld.Attributes And dbSystemObject) <> 0 Then
Debug.Print "System Object"
End If
Next fld ' Get the next Field in the TableDef object.
' Map Indexes for each TableDef object.
Debug.Print "INDEXES"
For Each idx in tdf.Indexes
' Set the Index variable.
Set idx = tdf.Indexes(intX)
Debug.Print "Name: ", idx.Name
Debug.Print "Clustered: ", idx.Clustered
Debug.Print "Foreign: ", idx.Foreign
Debug.Print "IgnoreNulls: ", idx.IgnoreNulls
Debug.Print "Primary: ", idx.Primary
Debug.Print "Unique: ", idx.Unique
Debug.Print "Required: ", idx.Required
' Map the Fields of the Index.
For Each fld in idx.Fields
Debug.Print "Name: ", fld.Name
Next fld ' Get the next Field in the Index.
Next idx ' Get the next Index in the TableDef object.
Next tdf ' Get next TableDef in the Database.
' Map the Relation objects.
Debug.Print "RELATIONS"
For Each rel in dbs.Relations
Debug.Print "Name: ", rel.Name
Debug.Print "Attributes: ", rel.Attributes
Debug.Print "Table: ", rel.Table
Debug.Print "ForeignTable: ", rel.ForeignTable
' Map the Fields of the Relation objects.
For Each fld in rel.Fields
Debug.Print "Name: ", fld.Name
Debug.Print "ForeignName: ", fld.ForeignName
Next fld ' Get the next Field in the Relation object.
Next rel ' Get next Relation object in the Database.
dbs.Close
Set rel = Nothing
Set idx = Nothing
Set fld = Nothing
Set tdf = Nothing
Set dbs = Nothing
Exit Sub
ErrorHandler:
MsgBox "Error #: " & Err.Number & vbCrLf & Err. Description
End Sub
As your application is used, the database file can grow in size. If you are responsible for the maintenance of your database, you’ll need to perform a number of system-oriented tasks from time to time, such as compacting the database and repairing it if it becomes corrupted. This section discusses these maintenance tasks.
If you are performing compact and repair operations, you will often use the menu commands provided in the user interface. The Compact and Repair Database command is available on the Database Utilities submenu (Tools menu) in the Access startup window.
However, if you want to provide a way for your users to compact and repair their copies of your application, you can provide them with either an icon that performs the compact and repair operations or code that compacts and repairs the database automatically.
You can create a shortcut that uses the /compact command-line option. This command-line option compacts and repairs your application without opening it. When you create the shortcut, type a command line that consists of:
Note To compact and repair a database, the database and any connections to it must be closed. Also, if you have established user-level security for your application, the user running the compact and repair operation must have Open Exclusive permission for the database, and have Modify Design or Administer permission for all tables in the database. For more information about permissions, type setting permissions in the Office Assistant or on the Answer Wizard tab in the Help window, and then click Search. Additionally, when compacting, there must be sufficient disk space for both the original and compacted versions of the database, even if the database is being compacted to the same file name. This is because the compacted database is renamed as the original database only after compacting to a temporary file is successful.
To maintain a high state of performance, Access defers the removal of discarded pages until you shut down the database and compact the discarded pages. This design keeps the interactive performance of your database high at the expense of recoverable disk space.
Compacting a database:
To compact your database, point to Database Utilities on the Tools menu and click Compact and Repair Database. If the database you want to compact is currently open, it will be closed, compacted into a temporary file, and then reopened. If no database is open, you must specify the database to compact and the database to compact into. If you specify the same file name to compact into, Access compacts into a temporary file. When Access compacts to a temporary file, it renames the temporary file back to the original file name once the compacting process is completed.
You can also use the CompactDatabase method of the DBEngine object to compact a database. When you use the CompactDatabase method, you must compact to a file with a different name. The following code example uses the CompactDatabase method to compact the Orders sample database to a temporary file and then renames that temporary file to the original name if the compacting process is successful. You can download the Orders sample application and associated Help files from the Microsoft Developer Network (MSDN) Online Web site.
Sub CompactDB()
Const FILE_PATH = "C:\Program Files\Microsoft Office\Office\Samples\"
On Error GoTo ErrorHandler
' Compact the database to a temp file.
DBEngine.CompactDatabase FILE_PATH & "Orders.mdb", _
FILE_PATH & "OrdersTemp.mdb"
' Delete the previous backup file if it exists.
If Dir (FILE_PATH & "Orders.bak") <> vbBullString Then
Kill FILE_PATH & "Orders.bak"
End If
' Rename the current database as backup and rename the temp file to
' the original file name.
Name FILE_PATH & "Orders.mdb" As FILE_PATH & "Orders.bak"
Name FILE_PATH & "OrdersTemp.mdb" As FILE_PATH & "Orders.mdb"
MsgBox "Compacting is complete"
Exit Sub
ErrorHandler:
Msgbox "Error #: " & Err.Number & vbCrLf & vbCrLf & Err.Description
End Sub
The CompactDatabase method also gives you the option of changing the encryption state, the version, and the disk or folder of a database while it’s being compacted. In other words, you can choose to convert an encrypted database to a non-encrypted database, or vice versa.
For example, the following code compacts a database named Old and creates a new, encrypted database named New.
DBEngine.CompactDatabase "C:\Old.mdb", "C:\New.mdb", _
dbLangGeneral, dbEncrypt
See Also For more information about database encryption, see Chapter 18, “Securing Access Databases” in the Microsoft Office 2000/Visual Basic Programmer's Guide (Microsoft Press, 1999). You can also find this guide in the Office Developer Documentation section of the Microsoft Developer Network (MSDN) Online Library.
Note Compacting cannot be done inside a transaction, or on a database that is currently open by another user.
You can also compact your database automatically when you close it.
To automatically compact your database when you close it
Replicated databases make extensive use of temporary space, especially when many design changes are made to an application. Just as with non-replicated databases, compacting regularly reduces file size and improves performance.
For optimal results, compact a replicated database twice. Compacting a replica the first time reclaims some space and flags other space as available for reclaiming later. Compacting a second time reclaims all available space. Compacting more than twice doesn’t provide additional benefits.
Improperly compacting the Design Master of a replica set causes the replica set to lose its Design Master. When Access opens a replica, it stores the name and location of the file in the database. The next time Access opens the replica, it checks to see if the file has the same name and location. If so, then the file opens normally. If not, Access gives the replica a new ReplicaID property value and, if the file was the Design Master, removes the Design Master flag. This prevents two replicas from having the same ReplicaID property value or a replica set from having two Design Masters.
To prevent a Design Master from losing its Design Master flag when you compact a replicated database, do one of the following:
If your database is damaged, close the database, then point to Database Utilities on the Tools menu and click Compact and Repair Database. The Compact and Repair Database command checks all pages in the database for correct linkage, validates all system tables, and validates all indexes. Because the Compact and Repair Database command can’t fix all possible forms of database corruption, you should back up your database files regularly to avoid unrecoverable data loss. This kind of corruption can occur when the system isn’t shut down normally (such as during a power failure).