You are on page 1of 132

Data Access Xtra for Macromedia Director and Authorware

User Manual
Version 2.0
August 21, 1998

© Used under license by Integration New Media, Inc.


www.INM.com
Datagrip Table of Contents

CHAPTER 1 GETTING STARTED WITH DATAGRIP™..................................................................................... 4


INTRODUCTION ........................................................................................................................................... 4
WHAT’S NEW IN VERSION 2.0 .................................................................................................................... 4
SYSTEM REQUIREMENTS ............................................................................................................................. 5
TYPOGRAPHICAL CONVENTIONS ................................................................................................................. 5
PRODUCT RETURN POLICY.......................................................................................................................... 6
COPYRIGHTS AND TRADEMARKS ................................................................................................................ 6
INSTALLING DATAGRIP™ ........................................................................................................................... 6
CHAPTER 2: DATAGRIP TUTORIAL OVERVIEW ............................................................................................ 8
OVERVIEW OF THE APPLICATION ................................................................................................................ 8
THE CONTACT DATABASE .......................................................................................................................... 9
CHAPTER 3: DIRECTOR TUTORIAL ............................................................................................................. 12
OPENING THE DATABASE .......................................................................................................................... 12
CREATING A RECORDSET .......................................................................................................................... 13
WORKING WITH QUERYDEF OBJECTS ....................................................................................................... 16
PARAMETERIZED QUERIES ........................................................................................................................ 17
DISPLAYING THE CONTACT INFORMATION ............................................................................................... 18
FILLING THE LIST BOX WITH PHONE NUMBER INFORMATION ................................................................... 20
ADDING NEW RECORDS ............................................................................................................................ 23
NAVIGATING THROUGH THE CONTACTS .................................................................................................... 25
ADDING PHONE NUMBERS ........................................................................................................................ 26
SUMMARY................................................................................................................................................. 28
CHAPTER 4: AUTHORWARE TUTORIAL ...................................................................................................... 29
OPENING THE DATABASE .......................................................................................................................... 29
CREATING A RECORDSET .......................................................................................................................... 30
WORKING WITH QUERYDEFS .................................................................................................................... 32
PARAMETERIZED QUERIES ........................................................................................................................ 33
DISPLAYING THE CONTACT INFORMATION ............................................................................................... 34
ADDING NEW RECORDS ............................................................................................................................ 37
NAVIGATING THROUGH THE CONTACTS .................................................................................................... 38
ADDING PHONE NUMBERS ........................................................................................................................ 38
SUMMARY................................................................................................................................................. 39
CHAPTER 5 LANGUAGE REFERENCE .......................................................................................................... 40
CLEARDGERROR ...................................................................................................................................... 40
DGCLOSE ................................................................................................................................................. 41
DGCREATEGRID....................................................................................................................................... 42
DGCREATERECORDSET ............................................................................................................................ 43
DGEXECUTE ............................................................................................................................................. 44
DGGETVERSION....................................................................................................................................... 45
DGGRIDADDFIELD .................................................................................................................................. 46
DGGRIDDELETEFIELD ............................................................................................................................. 47
DGGRIDUPDATE ...................................................................................................................................... 48
DGISDAOREGISTERED ............................................................................................................................ 49
DGOPENDATABASE ................................................................................................................................. 50
DGQDCLOSE ........................................................................................................................................... 51
DGQDCREATE ......................................................................................................................................... 52
DGQDCREATERS .................................................................................................................................... 53
DGQDGETNAME ..................................................................................................................................... 54
DGQDGETPARAMETERCOUNT ................................................................................................................ 55
DGQDGETPARAMETERVALUE ................................................................................................................ 56

Datagrip User Manual, Version 2.0 i August 21, 1998


DGQDGETSQL........................................................................................................................................ 57
DGQDISOPEN .......................................................................................................................................... 58
DGQDOPEN ............................................................................................................................................. 59
DGQDSETPARAMETERVALUE ................................................................................................................. 60
DGQDSETSQL ........................................................................................................................................ 61
DGRSADDNEW........................................................................................................................................ 62
DGRSBINDFIELD ..................................................................................................................................... 63
DGRSBINDVAR ....................................................................................................................................... 64
DGRSCANAPPEND ................................................................................................................................... 65
DGRSCANCELUPDATE............................................................................................................................. 66
DGRSCANSCROLL ................................................................................................................................... 67
DGRSCANTRANSACT .............................................................................................................................. 68
DGRSCANUPDATE................................................................................................................................... 69
DGRSCLOSE ............................................................................................................................................ 70
DGRSDELETE .......................................................................................................................................... 71
DGRSEDIT ............................................................................................................................................... 72
DGRSFILLLIST......................................................................................................................................... 73
DGRSFILLSTRING .................................................................................................................................... 74
DGRSFINDFIRST ...................................................................................................................................... 75
DGRSFINDLAST....................................................................................................................................... 76
DGRSFINDNEXT ...................................................................................................................................... 77
DGRSFINDPREV ...................................................................................................................................... 78
DGRSGETABSOLUTEPOSITION ................................................................................................................ 79
DGRSGETEDITMODE .............................................................................................................................. 80
DGRSGETFIELDCOUNT ........................................................................................................................... 81
DGRSGETFIELDVALUE ........................................................................................................................... 82
DGRSGETLOCKINGMODE ....................................................................................................................... 83
DGRSGETNAME ...................................................................................................................................... 84
DGRSGETPERCENTPOSITION ................................................................................................................... 85
DGRSGETRECORDCOUNT ....................................................................................................................... 86
DGRSGETSQL......................................................................................................................................... 87
DGRSIMPORTRESOURCE.......................................................................................................................... 88
DGRSISBOF ............................................................................................................................................ 90
DGRSISEOF ............................................................................................................................................ 91
DGRSISOPEN ........................................................................................................................................... 92
DGRSMOVEFIRST .................................................................................................................................... 93
DGRSMOVE ............................................................................................................................................. 94
DGRSMOVELAST .................................................................................................................................... 95
DGRSMOVENEXT .................................................................................................................................... 96
DGRSMOVEPREV .................................................................................................................................... 97
DGRSREQUERY ....................................................................................................................................... 98
DGRSSETABSOLUTEPOSITION ................................................................................................................. 99
DGRSSETFIELDVALUE .......................................................................................................................... 100
DGRSSETLOCKINGMODE ...................................................................................................................... 101
DGRSUNBINDFIELD............................................................................................................................... 103
DGRSUNBINDVAR ................................................................................................................................. 104
DGRSUPDATE ........................................................................................................................................ 105
DGGETREGVALUE ................................................................................................................................. 106
GETLASTDGERROR ............................................................................................................................... 107
DGSETAUDIOSAFEMODE....................................................................................................................... 108
DGSETREGVAL ...................................................................................................................................... 109
CHAPTER 6 DISTRIBUTING YOUR DATAGRIP APPLICATIONS .................................................................. 110
CREDITS REQUIREMENTS ........................................................................................................................ 110
DISTRIBUTING DATAGRIP ....................................................................................................................... 110

Datagrip User Manual, Version 2.0 ii August 21, 1998


DATAGRIP FILES ..................................................................................................................................... 111
APPENDIX A: GLOSSARY ........................................................................................................................... 114
APPENDIX B: MORE READING .................................................................................................................. 116
APPENDIX C: EXAMPLE DIRECTOR CODE ................................................................................................ 117
STARTUP SCRIPTS ................................................................................................................................... 117
BUTTON SCRIPTS .................................................................................................................................... 118
FRAME SCRIPTS ...................................................................................................................................... 119
INTERFACE SCRIPTS ................................................................................................................................ 119
DATABASE SCRIPTS ................................................................................................................................ 120
APPENDIX D: EXAMPLE AUTHORWARE CODE ......................................................................................... 125
STARTUP SCRIPTS ................................................................................................................................... 125
SUBROUTINES ......................................................................................................................................... 126
APPENDIX E: WHAT’S NEW IN DATAGRIP 2.0........................................................................................... 128
DATAGRIP SOFTWARE LICENSING AGREEMENT ..................................................................... 130

Datagrip User Manual, Version 2.0 iii August 21, 1998


Chapter 1
Getting Started with Datagrip™

Introduction
Thank you for purchasing Datagrip™ from Integration New Media, Incorporated.

Datagrip is an extension Xtra for Macromedia Director and Authorware that provides a
powerful and simple interface to Microsoft Access-format databases1 . You can use Datagrip
to quickly store, retrieve, and sort all kinds of information for electronic catalogs, computer-
based training, and template-based presentations.

You can read and write data to Access databases, return sets of records based on an SQL
query, search for records, use stored queries, and perform most of the common database
operations that you can do through Microsoft Access. In addition, since Datagrip is fully
compatible with Microsoft Access version 1.0 through Access ‘97, you can use Access to
create, edit, and browse the databases you use with Datagrip. You can even share a single
database between multiple Director and Authorware programs.

Here is a summary of Datagrip’s key features:


• Full access to Microsoft Access databases from the scripting language
• Compatible with Microsoft Access databases from version 1.0 through Access 97
• Support for stored queries allows you to store SQL queries in the database
• Support for parameterized stored queries
• Unlimited number of records and record sets (limited only by memory)
• Read and write functions for the Windows™ registry.
• Simple to use
• Royalty-free distribution
What’s New in Version 2.0
Version 2.0 includes a number of powerful new features that will not only improve
productivity, but will allow you to structure your multimedia application in new ways
improving the maintainability of the product and allowing content updates to be as simple as
shipping a new database file.

Datagrip’s new features include:


• Support for BMP bitmaps and Wave audio files
• Bound fields that automatically update when a user changes the current record

1 Microsoft Access databases are usually stored in files with a .MDB extension. For example, the Datagrip tutorial
database is stored in the file named TUTOR.MDB in the Datagrip installation directory.

Datagrip User Manual, Version 2.0 4 August 21, 1998


• Automatic support for multi-column list boxes (grids)
• The ability to run Datagrip without installing any software on a client’s hard drive
• Auto-fill of lists and list boxes
A more detailed list of the new features in version 2.0 can be found in Appendix E.

System Requirements
To use Datagrip you’ll need the following:
• Windows ’95, Windows ‘98 or NT 4.0 or later
• Macromedia Director version 5.0 (or later) or Macromedia Authorware 4.0 (or later)
• Internet connection for downloading
• At least 5 MB of free disk space
• Microsoft Access
Typographical Conventions
This manual uses several conventions designed to help clarify the text:
• Structured Query Language (SQL) statements are printed on a separate line or lines in a
bold font like this unless they are part of Macromedia Scripting Language code. For
example, the following is a simple SQL statement:
“SELECT * FROM CONTACTS WHERE COMPANY = ‘Integration New Media’”

• Datagrip function names used in the text are printed in bold type. For example,
DGRSFindNext is a Datagrip function.
• Macromedia Scripting Language code is printed a typewriter font like this:
set dbHandle = DGOpenDatabase(the moviePath & "Tutor.mdb")
if dbHandle = "#ERROR#" then
alert "Error: " & GetLastDGError()
alert "Now exiting the program."
ClearDGError()
quit
end if

• Macromedia Scripting Language handlers referred to in text blocks will use a typewriter
font. As an example, note the font difference when referencing a handler named
FillPhoneNumFields().

Note
The text in code blocks use the Macromedia Scripting Language syntax, so you
can copy them directly with one exception. On occasion, lines of code are split
when they are too long to fit on a single line in this manual. In those cases, the
last two characters of the line are “>>” These characters indicate that the next
line should be appended to the end of the current line. Do not include the “>>”
characters in the code.

Datagrip User Manual, Version 2.0 5 August 21, 1998


Product Return Policy
A fully functional evaluation version of Datagrip is available for download from the Datagrip
web site (www.INM.com). The evaluation version gives you a convenient way to try all the
Datagrip functions and test it in your application. The only limitation of the evaluation version
is that it cannot be redistributed and it displays a dialog box at startup. The dialog box does
not appear in the product version.

If you have any questions about Datagrip's suitability for your application, we suggest you
download and try the evaluation version.

Copyrights and Trademarks


Microsoft Access is a registered trademark of Microsoft Corporation. Macromedia Director
Macromedia Authorware and Macromedia Xtra are registered trademarks of Macromedia,
Inc. All other trademarks are the property of their respective owners.

Installing Datagrip™
Datagrip™ is available for download from the Integration New Media web site:
http://www.INM.com/products/

Note
If you re-install Director in the future, you’ll need to re-install Datagrip as well
because parts of Datagrip are installed in an Xtras folder under the main
Director program folder.

Installing the Demo (Evaluation) Version:

Download the installer for the evaluation version and unzip it. Then double-click the installer,
named datagrip-demo-installer.exe and follow the instructions on screen. When installation
is complete, a new folder named DataGrip Xtra is created within Program Files > Integration
New Media. This DataGrip Xtra folder contains documentation and the following file:

- DGDemo.X32: Place this file in the Xtras folder within the Director/Authorware
application folder, for use during authoring time. (Note that in Director MX 2004,
the Xtras folder is in Program Files\Director MX 2004\Configuration\Xtras).
The evaluation version cannot be used in the "runime" environment, for playback of
projectors/packaged pieces.

Datagrip User Manual, Version 2.0 6 August 21, 1998


Installing the Release Version:

After evaluating the demo version of DataGrip, you can purchase a license from INM's secure
online store: https://Store.INM.com

Once you have purchased your license you will be sent a Release version of the Xtra, which
you can test and distribute with your projects. Download the installer for the Release version
and unzip it. Then double-click the installer, named datagrip-release-installer.exe and
follow the instructions on screen. When installation is complete, the following Xtras will be
placed in the folder named Program Files > Integration New Media > DataGrip Xtra:

- DGDes.X32: Place this file in the Xtras folder within Director/Authorware, for use
during authoring time.

- DGRel.X32: Place this file beside your executable Director projector or Authorware
packaged piece, for playback and distribution.

Datagrip User Manual, Version 2.0 7 August 21, 1998


Chapter 2:
Datagrip Tutorial Overview

This chapter will help get you started with using Datagrip™ by showing you step-by-step
how to build a simple Contact Manager application using Macromedia Director/Authorware
and Datagrip. This particular contact manager is used to organize a list of photographers or
artists and contains a bitmap field for showing a portfolio sample. Along the way, you’ll see
most of the key features of Datagrip in action, including segments of the code from the sample
application that illustrate the concepts. Following this overview chapter, there are detailed
chapters covering the use of Datagrip with Director and Authorware.

The complete application is included with Datagrip as a Director 6.0 file and as an
Authorware 4.0 file, so you can open it, run the application, and see how it all works together.
You can even copy code directly from the tutorial application as a starting point for your own
projects. You’ll find the Director file, called TUTOR.DIR and the Authorware file, called
TUTOR.A4P, in the Datagrip directory.

Overview of the Application


Our contact manager application is a lot like many other simple contact managers with two
important differences. To better illustrate Datagrip’s capabilities we have included a bitmap
field that is used to show a bitmap showing a sample of the person’s portfolio. We have also
included the capability to store an unlimited number of phone numbers (because we have
been frustrated in the past by contact managers that have a fixed number of phone number
fields). This allows you to store the contacts two home numbers, a FAX number at home and
at work, cellular number, pager number, and office number. You’ll see as we go through the
tutorial how multiple tables in the database are used to implement this feature. Figure 1 shows
the main contact manager screen when the application is complete.

Datagrip User Manual, Version 2.0 8 August 21, 1998


Figure 1. The tutorial program main screen.

The Contact Database


We could implement the contact manager program using a single table in the database. Each
contact would have one record (row) in the database. However, if we use a single table, we
will have to choose some maximum number of telephone numbers for each contact. We will
have to define one field (column) in the table for each phone number we want to store. If we
want to allow up to five phone numbers per contact, the table must have five phone number
fields. More phone numbers requires more fields in the table. Worse yet, every record must
have all of the phone number fields, whether they are used or not. Figure 2 shows a single
database table with a fixed number of phone number fields in both the traditional row and
column layout and as a Microsoft Access structure diagram.

FirstName LastName Address Company Phone 1 Phone 2 Phone 3 Phone 4 Phone 5

Figure 2a. A single database table with five phone number fields laid out in a row and column format.

Datagrip User Manual, Version 2.0 9 August 21, 1998


Figure 2b. Microsoft Access structure view of the single table database.

A more efficient way to store the phone numbers and eliminate the restriction on the
maximum number of telephone fields is to use two related tables. Figure 3 shows a design
using related tables. In this design, the Contacts table stores information about the contact, but
it doesn’t store any phone numbers. A separate table called the Phone Number table, stores
only phone numbers and a description of each phone number. However, notice that each
record in the Phone Number table also has a “ContactID” field that identifies which contact in
the Contacts table this phone number belongs to. A single record in the Contacts table might
have dozens—even hundreds—of corresponding phone number entries in the Phone Number
Table. The entries in the two tables are linked together by ContactID field.

Contacts Table
ContactID FirstName LastName Address Company Title

Phone Number Table


ContactID NumberID PhoneNumber Description

Figure 3a. Row/column diagram of two tables related by the ContactID field make unlimited phone
number storage easy.

Datagrip User Manual, Version 2.0 10 August 21, 1998


Figure 3b. Microsoft Access structure diagram of two tables related by the ContactID.

In this design, each contact can have as many phone numbers as needed, and the phone
number table doesn’t need any empty records if a contact only has one phone number.

The related tables might sound very complex to deal with. How would you go through the
two tables and find all the telephone numbers that belong to an individual contact? The
records for an individual contact might not even be all together in the Phone Number table!

Fortunately, you don’t have to do any sorting or any special work to find related records in the
two tables. Datagrip, working in concert with the Microsoft Access database system, does the
hard work for you. You simply write structured query language (SQL) queries to retrieve the
data you want. Datagrip does the rest.

Note
These tutorials assume some basic knowledge of database concepts, and of
Macromedia’s scripting language. While you should be able to follow the
tutorials with minimal database or scripting experience, if you need more help
we suggest looking through a couple of the books listed in Appendix B, More
Reading.

The tables in Figure 3 exist in the tutorial database file called TUTOR.MDB. You’ll find this
database in the Datagrip directory. If you have Microsoft Access, you can open the database
and examine the tables. You don’t need Microsoft Access to use Datagrip, but you’ll probably
find Access useful for designing and examining databases. In addition, Microsoft Access
makes it easy to import data into a database from a variety of other file formats.

With that background, let’s get started on developing the contact manager application.

Note
The TUTOR.MDB file is written in Access version 7.0 format (Microsoft Office
95) so that it will be compatible with all later versions of Access. If you are
using a later version of Access, you will probably see a message asking if you
want to convert the database to the newer format. Datagrip is compatible with
all database formats up to, and including Access ‘97, so it won't cause problems
to convert the database to the format for your version of Access.

Datagrip User Manual, Version 2.0 11 August 21, 1998


Chapter 3:
Director Tutorial

This chapter will help get you started using Datagrip™ by showing you step-by-step how to build
a simple Contact Manager application using Macromedia Director. If you are using Authorware,
skip this chapter and refer to Chapter 4.
The tutorial has been re-written to take advantage of some of the new features of version 2.0. So
even if you are familiar with Datagrip, you may want to review this chapter.

Opening the database


The first step in just about any database application is to open the database file. You’ll use the
DGOpenDatabase function. DGOpenDatabase takes one parameter2 , the name of the
database you want to open. If the database file exists in the same directory as your projector,
you can simply use the name of the file like this:
set dbHandle = DGOpenDatabase("Tutor.mdb")

Note
In the design environment the local directory is actually the directory that
Director is installed in. In the run-time environment, the local directory is the
directory where the projector is stored.

Otherwise, you may want to construct the full name of the path by combining the location of
the currently running movie with the name of the database. If, for example, the database is
located in the same directory as the currently playing movie, you can open the database like
this:
set dbHandle = DGOpenDatabase(the moviePath & "Tutor.mdb")

In this case Tutor.mdb was a local file, but Datagrip can also open databases on a networked
disk. This can be very useful when you need to share a database between multiple projectors.

Opening a database on a network drive is essentially the same as opening a local database,
except that you include the name of the computer that the database is stored on using the
Universal Naming Convention (UNC) format. For example, to open a database on the
computer named “FileServer” you would make the following call.
set dbHandle = DGOpenDatabase("\\FileServer\Tutor.mdb")

If the DGOpenDatabase function succeeds, it returns a number called a handle. You’ll want
to store this handle in a variable because you’ll use it in other Datagrip functions to refer to
the open database. In the example above, the handle is stored in the variable dbHandle.

2
An alternate form of the DGOpenDatabase command takes four parameters and allows for opening the database
exclusively, read-only, or with a specific connection string. Refer to the Language Reference section for details.

Datagrip User Manual, Version 2.0 12 August 21, 1998


Every database you open will have a unique handle, so you can simultaneously open as many
databases as you need. Remember to store the handle for each open database in a separate
variable so you’ll have a way to refer to the databases in other parts of your code.

In the event that the DGOpenDatabase function fails, it will not return a number. Instead it
returns the special error string #ERROR#. The error might be caused by any number of
problems, such as a database file that is missing, or opened exclusively by another application
(such as Microsoft Access).

You should test the return value from DGOpenDatabase. If it is #ERROR#, you can use the
GetLastDGError function to get information on the cause of the problem.

Now let’s put what we’ve learned so far to practice. Following is the first part of the code
we’ll use to initialize the application in the InitDB function. This script is called from
startMovie.

set dbHandle = DGOpenDatabase(the moviePath & "Tutor.mdb")


if dbHandle = "#ERROR#" then
alert "Error: " & GetLastDGError()
alert "Now exiting the program."
ClearDGError()
Quit
end if

In the first line, we open the database, which is located in the same directory as the movie file.
We store the handle that is returned in the global variable called dbHandle. Then we check to
see if an error occurred while opening by comparing dbHandle to #ERROR#. If
DGOpenDatabase returned #ERROR#, we call to GetLastDGError to find out what went
wrong and print out the error string that is returned.

After we’ve retrieved the error information, we call ClearDGError to reset the error
information. Since failing to open the database makes the program pretty useless, we exit at
this point.

Creating a Recordset
At this point, we have an open database, but we still haven’t retrieved any data. To read data
from the database, we need to create a recordset. A recordset, as the name implies, is a set of
records (rows) from one or more database tables. The recordset might contain all the records
in the table, or it might contain only a few records, based on some criteria we specify in an
SQL query.

To create a recordset, call the DGCreateRecordset function, which takes two parameters.
The first parameter is an SQL query string that defines which fields and records in the
database should be included in the recordset. The second parameter is the handle to the open
database, which was returned from DGOpenDatabase. Here’s what a typical call to
DGCreateRecordset looks like:
set rsHandle = DGCreateRecordset("SELECT * FROM Contacts", dbHandle)

Datagrip User Manual, Version 2.0 13 August 21, 1998


The first parameter is the SQL string, which says, “create a recordset that contains all fields
and all records from the Contacts table”. The query string could also specify that only records
that meet a certain criteria be returned. For example, the SQL string:
“SELECT * FROM CONTACTS WHERE COMPANY = ‘INM”

returns only contacts where the company field contains the string “INM”.

Note
If you’re not familiar with SQL, we recommend you refer to one of the books on
Microsoft Access or SQL in the More Reading section.

The DGCreateRecordset function also returns a handle, much like the DGOpenDatabase
function. You’ll want to store this handle as well because you’ll use it to read and write data
from the recordset and perform other functions on the recordset. If DGCreateRecordset
encounters an error, it returns the standard error string, #ERROR#.

Now let’s put together the open database code from the previous example with the code
required to open the recordset.
-- Global data handles that will be used
–- for the database and recordset.
global dbHandle
global rsHandle
global qdHandle

--
-- Open the contacts database assuming
-- that it exists in the local directory.
-- If it doesn't we will get an error back
-- that we can use to communicate with the user.
--
set dbHandle = DGOpenDatabase(the moviePath & "Tutor.mdb")
if dbHandle = "#ERROR#" then
alert "Error: " & GetLastDGError()
alert "Now exiting the program."
ClearDGError()
quit
end if

--
--This SQL string will define our
--recordset. It essentially means
--Select everything that exists
--inside the Contacts table.
--
set sqlString = "SELECT * FROM Contacts"

--
--Open a recordset using our above created
--SQL string and our database handle
--
set rsHandle = DGCreateRecordset(sqlString, dbHandle)
if rsHandle = "#ERROR#" then
alert "Error: " & GetLastDGError()
alert "Now exiting the program."
Quit
end if

Datagrip User Manual, Version 2.0 14 August 21, 1998


You’ve already seen the first block of code the opens the database, so let’s start with opening
the recordset. We call the DGCreateRecordset with an SQL string that returns all the records
and fields from the Contacts table. We store the return value in rsHandle and check it for the
standard #ERROR# string. If an error occurs, we get the error information, print the error
string, and exit.

Typically, a recordset contains one or more records based on the criteria used to create the
recordset. In the above example, the recordset contains all of the records in the “Contacts”
table. Although the recordset can contain more than one record, there is a single record that is
considered the current record – the record that is “pointed to”. It is this current record that
many functions will operate on. For instance, deleting, editing, updating, etc all operate on the
current record. If a record is added to the recordset, the current record position will point to
the newly added record. This is an extremely important concept in understanding how
databases work.

At this point, the recordset contains all the information from our Contacts table. But what
about the PhoneNumber table? There are several ways we can gain access to the
PhoneNumber data. One simple method is to use a join in SQL. You simply replace the SQL
string with this:
SELECT Contacts.*, PhoneNumbers.*
FROM Contacts INNER JOIN PhoneNumbers ON Contacts.ContactID = PhoneNumbers.ContactID;

Now the recordset contains all the fields from the Contacts table and the PhoneNumbers table
(refer to Figure 4). Better still, the database has automatically matched up all the contacts with
their corresponding Phone Numbers. The only disadvantage to using this technique is that the
recordset actually contains one record for every contact and every phone number. This means
that if a contact has three phone numbers, the contact will exist three times in the recordset—
once with each of his or her phone numbers. For more information on SQL joins, refer to the
one of the books in Appendix B, More Reading.

Figure 4. The recordset returned from the SQL join of the Contacts table and the PhoneNumber table.

For our purposes, the SQL join probably isn’t the best way to retrieve the phone numbers.
Instead, for each contact, we’ll create a second recordset that contains all the phone numbers
for the current contact.

Datagrip User Manual, Version 2.0 15 August 21, 1998


We could create the second record using another DGCreateRecordset call, much like the
first one. Assuming that we have the ContactID value for the contact whose phone numbers
we want to find, here’s what the code would look like:
set queryStr = "SELECT * From PhoneNumbers Where ContactID=" & CurContact
set rsHandle = DGCreateRecordset(queryStr, dbHandle)

The query string (queryStr) says “get all the records in the PhoneNumbers table whose
ContactID is equal to CurContact. CurContact is the variable that contains the Contact ID for
the current contact. For example, if the current contact contained “2” in the ContactID field,
then the query above would return the recordset shown in Figure 5.

Figure 5. The set of records in the PhoneNumber table corresponding to a ContactID of 2.

Working with QueryDef Objects


In all the previous examples, we’ve entered a query string in the DGCreateRecordset call.
There, is however, another, more efficient way to handle queries. You can store queries in the
database file itself, in a QueryDef (Query Definition). A QueryDef is simply a query, just like
the ones we’ve seen up to this point, stored in the database file and given a name.

The advantage of stored queries is that they are faster than query strings in your code and they
improve the maintainability of your program. If you use a particular query several places in
your code, it’s also easier to maintain a single query in the database than defining it all the
places you need it in your code.

We open a QueryDef using the DGQDOpen function. Here’s an example:


set qdHandle = DGQDOpen("PhoneQuery", dbHandle)
if qdHandle = "#ERROR#" then
alert "Error: " & GetLastDGError()
alert "Now exiting the program."
Quit
end if

The first parameter to DGQDOpen is the name of the stored QueryDef. The second
parameter is the database handle returned from DGOpenDatabase.

By now, you recognize the error checking code. The DGQDOpen function returns a handle
just like the open database and create recordset functions we’ve used so far. You’ll use the

Datagrip User Manual, Version 2.0 16 August 21, 1998


handle returned from DGQDOpen to create a recordset based on the stored query. To create a
recordset based on a stored query, use the DGQDCreateRS function:
set rsHandle = DGQDCreateRS(qdHandle)

Notice that the DGQDCreateRS function takes only one parameter—a QueryDef handle.
That’s because the QueryDef handle refers to a stored query in the database, so you don’t
need an SQL string or database handle.

Parameterized Queries
You’ll often want to use a stored query, but change one of its parameters. In the case of our
contact manager, we’ll use the following query to find the phone numbers for the current
contact:
PARAMETERS pContactID Long;
SELECT *FROM PhoneNumbers WHERE (PhoneNumbers.ContactID=[pContactID]);

This query was created by using the Microsoft Access query designer. If you are comfortable
with SQL, you can simply type the SQL directly to create the query. In any event, this SQL is
saved as a query in Access.

Notice the use of the parameter “pContactID”. This is called a “parameterized query” and is
very useful in many applications where you want to create a recordset based on some set of
criteria, typically a field equal to some value. You can specify more than one parameter but
each parameter will have to be set before using the query.

Here’s a segment of code that illustrates the process:


-- Set the variable “val” equal to the value of the ContactID
–- field of the current record. This field value will be used to
–- set the value of a parameter in a saved query
set val = DGRSGetFieldValue("ContactID", rsHandle)
if val <> "#ERROR#" then
DGQDSetParameterValue("pContactID", val, qdHandle)
set tmpRS = DGQDCreateRS(qdHandle)
end if

Note
There are numerous advantages to using stored queries in Microsoft Access and
working with QueryDef objects to access them in Datagrip. In addition to better
performance, stored queries can improve the reliability and maintenance of
your program by eliminating the use of hard-coded SQL in your code. Once a
QueryDef has been defined, it can be modified to sort the records or join with
another table without having to make changes in Lingo.

In the first line we use a new Datagrip function to read the value of the ContactID field from
the Contacts table using a recordset we’ve previously created. As long as no error occurred in
reading the value, we use that value in a DGQDSetParameterValue function. This function
takes three parameters:

Datagrip User Manual, Version 2.0 17 August 21, 1998


pContactID is the name of the parameter in the query that we want to set.
val is the value that we’re setting for the parameter
qdHandle is a handle to a previously opened QueryDef.

We won’t discuss the details of setting up a parameterized query in this tutorial. For more
information, refer to the reference section for the Datagrip QueryDef functions, which all
begin with DGQD. An example of using a parameterized query is included in the tutorial
example. Refer to the handler named FillPhoneNumFields in the tutorial to see an
example of using a parameterized QueryDef.

Once the parameter values are set with DGQDSetParameterValue, we call


DGQDCreateRS to create a recordset based on the QueryDef with the parameter values we
set. When this code segment finishes executing, the tmpRS recordset should contain all the
phone numbers for the particular ContactID we read from the Contacts table. If you need to
change the value of the parameter and update the query you can call DGRSRequery. This is
much faster than destroying the old recordset and opening a new one.

Displaying the Contact Information


Now we have the information we need from the database. It’s time to display the information
on the stage. The main screen of our contact manager has eight fields that will hold the data
from the database (see Figure 1). The names of the fields on the stage correspond with the
fields in the database. There are fields for the first name, last name, address, company, title
and portfolio sample (a bitmap image). A list box displays the phone numbers and
descriptions for the current contact. There is also one hidden piece of data associated with
contact records – that of a wave file used to auto dial the telephone. When the user clicks on
the “Dial Phone” button, you will hear the tones associated with a telephone number. For this
example, the wave file is associated with the contact record. In a real application, it would
make more sense to give each phone record its own wave file.

There are several different approaches to displaying the field information on the stage. Two
methods will be described – field binding and manually updating field values. The tutorial
actually uses both approaches in order to show exactly how each method is implemented.
Binding Fields
One very powerful feature of Datagrip is the ability to directly bind Director cast members to
database fields. Binding will result in the automatic update of the cast member whenever the
current record changes. Field binding is accomplished by using the function DGRSBindField
as shown in the following code:
--
-- Link each field to it's appropriate Database field
--
DGRSBindField("FirstName_Field", "FirstName", rsHandle)
DGRSBindField("LastName_Field", "LastName", rsHandle)
DGRSBindField("Company_Field", "Company", rsHandle)
DGRSBindField("Title_Field", "Title", rsHandle)

Datagrip User Manual, Version 2.0 18 August 21, 1998


The DGRSBindField function takes three parameters. The first parameter specifies the name
of the cast member that will be bound. The second parameter is the name of the field in the
recordset, and the third parameter is a recordset handle.

All of the code to this point in the tutorial can be found in the handler initDB, which is
included in the script cast member, “StartupScripts”.
Using DGRSGetFieldValue()
There are some situations where automatic field binding may not be the best choice. For
example, if the database stored codes in a particular field and you wanted to display the text
associated with the code, you may have to get the field value and convert the code to a string
using a property list or some other approach. In this case, you may want to use the function
DGRSGetFieldValue.

In the current tutorial, one field, the address field, is not bound and must be manually updated
whenever the position of the current record changes. You will see code similar to the
following code segment in a number of different functions (GoToNextRecord,
GoToPrevRecord, etc.)

set txt = DGRSGetFieldValue("Address", rsHandle)


if txt <> "#ERROR#" then
set the text of member "Address_Field" = txt
end if

Prior to the field binding feature being added to Datagrip, the tutorial included a handler
called FillFields that was called each time the record position was changed. The code
below shows how FillFields managed the display of the contact information.
on FillFields
global qdHandle
global rsHandle
--
-- Check to see if we have any records
--
if DGRSGetRecordCount(rsHandle) <= 0 then return
--
-- If so, fill the fields on the stage with the data
-- from the database.
--
SetFieldVal("FirstName_Field", "FirstName")
SetFieldVal("LastName_Field", "LastName")
SetFieldVal("Address_Field","Address")
SetFieldVal("Title_Field", "Title")
SetFieldVal("Company_Field", "Company")
. . .

Note
The current tutorial uses field binding for all but the Address field. This section
shows how field values where updated on stage in the Tutorial that
accompanied version 1.0 of Datagrip.

Datagrip User Manual, Version 2.0 19 August 21, 1998


The FillFields function first declares the global variables for the recordset (rsHandle) and
querydef (qdHandle) so we can use these values in the function. Next, we call
DGRSGetRecordCount to find out if the recordset contains any records. If it doesn’t, there’s
not much point in trying to display the data—there’s nothing to display.

If there is at least one record in the recordset, we call another function called SetFieldVal
to transfer the data between the recordset and the corresponding field on the screen.
SetFieldVal takes two parameters. The first one is the name of the cast member where we
will put the text we get from the database. The second is the name of the field in the database
that contains the text. Here’s the SetFieldVal function:
on SetFieldVal fieldName, dbField
global rsHandle
set val = DGRSGetFieldValue(dbField, rsHandle)
if val = "#ERROR#" then
alert "Error while retrieving from " & fieldName & RETURN & GetLastDGError()
ClearDGError()
set the text of member fieldName = ""
else
set the text of member fieldName = val
end if
end

Notice that we declare the rsHandle variable as global again, since we use it throughout the
code. Next, we call a new Datagrip function called DGRSGetFieldValue that retrieves the
data from a specified field. The first parameter to DGRSGetFieldValue is the name of the
field we want to read data from. The second parameter is the recordset handle.

If you look back up at the FillFields functions above, you’ll see that the first call to
SetFieldVal passes a database field name of “FirstName” (the second parameter to
SetFieldVal). That name is stored in the dbField variable inside SetFieldVal, which is,
in turn, passed on to the DGRSGetFieldValue function. The other parameter to
SetFieldVal is the name of the cast member on the stage that will receive the data from the
database.

DGRSGetFieldValue checks for an error using the standard method. If an error occurs, it
clears the field on screen by setting it to the empty string. Otherwise, the field on the stage is
set to the text read from the database.

Once the FillFields function has called SetFieldVal for each of the fields in the contact
table, all the contact information is filled out. The next step is to get the phone numbers for the
current contact and display them.

Filling the List Box with Phone Number Information


Macromedia’s Director program supports only very simple list boxes that have but one
column. Many times the developer would like to display more that one column in a list box.
This can be done by using a constant character width font (like Courier) and “padding” or
truncating spaces to line up the columns. This can be done directly in Macromedia’s scripting
language if you want to take the time to write and test the functions yourself. Or, you can use
the direct support for grids (multi-column list boxes) provided by Datagrip.

Datagrip User Manual, Version 2.0 20 August 21, 1998


Using the Grid Functions
This section will show you how to use the grid functions in Datagrip to automatically control
the columns in a multi-column list box. Below is the FillPhoneNumFields handler
implemented using the grid functions taken directly from the tutorial.
on FillPhoneNumFields

global rsHandle
global qdHandle

--
-- First, get the value of the contact ID from the current
-- record of the contact recordset
--
set val = DGRSGetFieldValue("ContactID", rsHandle)

if val <> "#ERROR#" then


--
-- Set the parameter "pID" in the phone queryDef to
-- the contact ID and open the recordset.
--
DGQDSetParameterValue("pID", val, qdHandle)
set tmpRS = DGQDCreateRS(qdHandle)

if tmpRS <> "#ERROR#" then

--
--Create a grid and add the needed fields
--
set gridHandle = DGCreateGrid("PhoneNum_Field", tmpRS)
DGGridAddField("Description", 13, gridHandle)
DGGridAddField("PhoneNumber", 14, gridHandle)

--
--Tell the grid to fill in all of the data
--
DGGridUpdate(gridHandle)
end if
end if
end

Here is how the handler works.

First, the global variables rsHandle and qdHandle are declared as usual. Remember, rsHandle
is the recordset handle for the Contacts table that was opened in the function InitDB.
Likewise, the QueryDef handle qdHandle is the parameterized query that was created in the
same function at startup time. It will be used to create a recordset of phone records that
corresponds to the current contact.

Next, the variable val is set to the value of the ContactID field of the current record of
Contacts recordset. Once again, you will want to check to make sure the function did not
return an error.

Setting the parameter value and opening the recordset using the QueryDef object is done
exactly as described earlier by calling DGQDSetParameterValue and DGQDCreateRS.

Datagrip User Manual, Version 2.0 21 August 21, 1998


The next step is to make a call to DGCreateGrid to create a grid object and call
DGGridAddField for each of the columns that we want to display. Then, we call
DGGridUpdate to automatically fill the grid with the field values specified for all of the
records in the recordset. No looping required and much faster!

The first argument of DGCreateGrid is the name of the Director field cast member while the
second argument is the handle to a recordset. Following the creation of the grid, calling
DGGridAddField will add new fields to the grid object in a left to right fashion. The first
argument to DGGridAddField is the name of the field in the recordset. The second argument
is the character width of the grid column and the third argument is a handle to a Datagrip grid
object.

Note
If the contents of the field has more characters than the column width specified
in the DGGridAddField function, the contents will be truncated.

Manually Filling a List Box


Sometimes manually filling the grid may be advantageous compared to the automatic method.
This might occur when the database contains codes instead of the actual text you want to
display. In any case, you can manually fill the grid by looping through each of the records in
the phone recordset and manually setting the list box data. This section will describe how to
do just that.

The recordset we created with the QueryDef in the previous section contains all the phone
numbers associated with the current contact. The following repeat loop reads the phone
number and description fields from each phone number record and fills a single large string
that has carriage returns between each phone number and description. Here’s the code:
repeat while not DGRSIsEOF(tmpRS)
set desc = DGRSGetFieldValue("Description", tmpRS)
if desc = "#ERROR#" then set desc = ""
set num = DGRSGetFieldValue("PhoneNumber", tmpRS)
if num = "#ERROR#" then set num = ""
set tmpStr1 = tmpStr1 & padText(desc) & num & RETURN
DGRSMoveNext(tmpRS)
end repeat
DGRSClose(tmpRS)

The loop begins with a call to DGRSIsEOF. This function returns a non-zero value if we’ve
gone past the end of the phone number recordset. Remember that tmpRS is the recordset
handle we created in the previous code segment. When we increment past the last record, the
loop stops.

For each pass through the loop (each phone number), we’ll read the value of the Description
and Phone Number fields by calling DGRSGetFieldValue for each field. We do the standard
error checking, and set the appropriate strings to empty if an error occurs. Once we’ve read
both the description and phone numbers from the database, we append them together with

Datagrip User Manual, Version 2.0 22 August 21, 1998


some white space between them and a carriage return on the end. The results are appended to
tmpStr1.

The padText function is a little function that is used only to add enough white space to get
the phone number and description fields to line up on screen. We won’t take the time to go
through that function here. If you want to see how it works, it is included at the end of this
section.

At the bottom of the loop, we call DGRSMoveNext to move to the next record in the phone
numbers recordset. This process continues until we reach the last record in the recordset. The
DGRSClose function at the end of the loop closes the recordset we created to read the phone
numbers.

When the loop finishes, tmpStr1 will contain all the phone numbers and descriptions for the
selected contact, separated by carriage returns as shown in Figure 1.

Then it’s a simple matter to assign this string to the cast member that contains the list on
screen:
set the text of member "PhoneNum_Field" = tmpStr1

The PadText function is used to line up the two columns of the list box by adding white
space or truncating characters thus forcing it to appear as a multi-column grid. Here is the
code.
on PadText str
--
--Set the num of chars before the next column
--
set padLength = 20

set count = length(str)

if count <= (padLength - 1) then


repeat with ii = 1 to (padLength - count)
set str = str & " "
end repeat
else
set str = chars(str, 1, padLength - 1) & " "
end if

return str
end

Adding New Records


At this point, our contact manager application can display the first contact and all the phone
numbers assigned to that contact. We’ve actually done most of the work, but the application
isn’t too useful unless we can move through the contacts and add new ones.

There are three major steps to follow whenever you want to add a new record to a database or
change an existing record in the database. Here are the steps:
1. Call DGRSAddNew to add a new empty record or call DGRSEdit to edit an existing record.

Datagrip User Manual, Version 2.0 23 August 21, 1998


2. Add data to the new record or change data in the existing record. If you’re modifying an
existing record, you can call DGRSGetFieldValue to read the current value of a field. Call
DGRSSetFieldValue function to put data into a field.
3. Call DGRSUpdate to save the new record or changes to the database.
You must repeat this process for every record you want to add or change.

Now that you know the process, let’s look at how we would implement code to add a new
record to our contact database. The following script, which is placed under the “New” button
does just that:
on CreateNewRecord
global rsHandle
if DGRSGetEditMode(rsHandle)=2 then
SaveCurrentData()
end if
DGRSAddNew(rsHandle)
end

The CreateNewRecord function once again declares rsHandle as a global variable, so we


can use the recordset we opened in the InitDB function at startup. Then we begin by calling
the DGRSGetEditMode function, which will return an integer indicating the state of the
database.

If this function returns a 2, it means that a new record has been added to the database but not
yet saved or that the recordset was opened for editing (DGRSEdit) but has not been updated
(DGRSUpdate). If that is the case, we’ll call the SaveCurrentData function to transfer
data on the screen to the database. Then we’ll call the DGRSUpdate function to save the data
in the database.

Now that the previous data, if any, has been saved, we call the DGRSAddNew function to
add a new empty record.

Let’s back up for a moment and look at what’s inside the SaveCurrentData function that
we called to save the data. Here’s the code:
on SaveCurrentData
global rsHandle

SaveDBField("FirstName")
SaveDBField("LastName")
SaveDBField("Address")
SaveDBField("Title")
SaveDBField("Company")

DGRSUpdate(rsHandle)
end

First you see the standard global declaration for the recordset handle. The main part of the
function makes five calls to SaveDBField and passes the name of the database field we want
to save. After we’ve saved all the fields, we call DGRSUpdate to store the results in the
database.

Datagrip User Manual, Version 2.0 24 August 21, 1998


The SaveDBField function is a tiny function that relies on the fact that we named our
database fields and the cast members on screen using the same names, but with “_field”
appended to the end of the cast member names. Here’s the SaveDBField function:
on SaveDBField fieldName
global rsHandle
DGRSSetFieldValue(FieldName, the text of member(fieldName & "_Field"),rsHandle)
end

The DGRSSetFieldValue function takes three arguments. The first function is the name of
the field we want to store data in. That name is passed in to the function. The second
argument is the data we want to store. In this case, the data comes from the text of the cast
member whose name is the same as the field name with a “_Field” appended to the end. The
last parameter is the global recordset handle.

Navigating through the contacts


Our contact manager program is getting pretty functional. We can display a contact, including
all their phone numbers and we can add new contacts. However, you may have noticed that at
this point, we have no way of moving through the contacts in the database. You can only see
the first contact or the most recently added contact. We need to add some way to move
through the contact database.

Moving through the database one record at a time is pretty easy. We’ll add two functions
called GoToNextRecord and GoToPrevRecord and we’ll tie these to the Next and
Previous buttons on screen. The two functions are so close to identical, that we’ll just show
you the GoToPrevRecord function and point out the differences between the two. You can
see the GoToNextRecord function in TUTOR.DIR.
on GoToPrevRecord
global rsHandle

if DGRSGetEditMode(rsHandle) = 2 then
SaveCurrentData()
end if
DGRSMovePrev(rsHandle)
if DGRSIsBOF(rsHandle) then
DGRSMoveNext(rsHandle)
end if
end

The first block of code should look familiar. It’s the same code we used in the
CreateNewRecord function. It calls DGRSGetEditMode function to find out if there’s
some unsaved data. We want to save the data before we move to a new record.

Once we’ve taken care of saving any unsaved data, we’re ready to move to the previous
record. We call the DGRSMovePrev function to make the move. The only problem with this
is that we might already be at the first record. To take care of that situation, we call
DGRSisBOF. This function returns a non-zero value (true) if we are past the beginning of the
recordset. It’s important to remember that it only returns true if we are past the beginning of
the data. It won’t do any good to call DGRSisBOF before you move, because it doesn’t
return true until you’ve moved past the beginning.

Datagrip User Manual, Version 2.0 25 August 21, 1998


The result of this behavior is that you must move to the previous (or next) record, then test
whether you’re past the end of the records. If so, you move back to where you were. In our
case, we call DGRSMoveNext to move back to the first record if we move past the
beginning.

Remember that we said the GoToPrevRecord and GoToNextRecord functions were


essentially identical. The only difference is that in GoToNextRecord, the DGRSMovePrev
and DGRSMovePrev calls are swapped and we call DGRSisEOF instead of DGRSisBOF,
since we’re testing to see if we moved past the end of the recordset, instead of testing for
moving past the beginning. Apart from that, the two functions are identical.

Each time the user clicks on the Next or Previous buttons, we call the corresponding function,
which moves to the next record in the contact recordset, until we reach the beginning or end
of the records. Each time we move to a new record, we’ll also need to call the code to get the
corresponding phone numbers from the phone number table. We saw this code when we
looked at QueryDefs. If field binding is used, the fields will automatically display the data
corresponding to the new record. Otherwise, call the FillFields handler to update the
screen.

Adding Phone Numbers


One of the key features of our contact program is the ability to store as many phone numbers
as we want for a particular contact. However, we still need a way to add phone numbers to the
phone number table.

Following is the code for a function that will be called when the user clicks the “Add Phone
Number” button.

Datagrip User Manual, Version 2.0 26 August 21, 1998


global rsHandle
global dbHandle
--
-- Save any un-saved data
--
if DGRSGetEditMode(rsHandle) = 2 then
SaveCurrentData()
DGRSUpdate(rsHandle)
DGRSMoveLast(rsHandle)
end if
--
-- Get the phone numbers and descriptions from the screen
--
set descStr = the text of member "tmpDesc_Field"
set NumStr = the text of member "tmpNum_Field"
--
-- If there are no phone numbers or descriptions, stop here.
--
if the number of words in descStr=0 and the number of words in numStr=0 then
return
end if
--
-- Get the ContactID value for the current Contact and
–- build a recordset of phone numbers for that ContactID
--
set id = DGRSGetFieldValue("ContactID", rsHandle)
if id <> "#ERROR#" then
set tmpRS = DGCreateRecordset("SELECT * FROM PhoneNumbers Where ContactID =" >>
&& id, dbHandle)
DGRSAddNew(tmpRS)
DGRSSetFieldValue("ContactID", id, tmpRS)
DGRSSetFieldValue("Description", descStr, tmpRS)
DGRSSetFieldValue("PhoneNumber", numStr, tmpRS)
DGRSUpdate(tmpRS)
DGRSClose(tmpRS)
end if

The code begins in the usual way by declaring our global handles. The next block should also
be familiar. It checks for unsaved data and saves the data if necessary.

Now the real work begins. The next two lines copy the text from the cast members that store
the phone numbers and descriptions (tmpNum_Field and tmpDesc_Field) to temporary
variables. We need to check whether there are, in fact, any phone numbers or descriptions
entered, so the next line checks the number of words in the temporary variables. If they’re
both zero, we just quit. There’s no point in creating a new record to store empty strings.

If there is something to store, we read the ContactID field from the current contact record. As
long as there was no error in reading the ContactID value, we create a recordset from the
PhoneNumber table based on that contact ID. The query in the DGCreateRecordset function
says “get all the records in the PhoneNumbers table that have a ContactID of id. Id is the
variable that stores the ContactID we read from the Contacts table. The result is that the
tmpRS recordset contains all the phone numbers associated with the current contact.

Next, we add a new record to the recordset we just created. Then we call
DGRSSetFieldValue to store the ContactID, Description, and Phone Number fields for the
new record. Finally, we call DGRSUpdate to store the new record in the database and
DGRSClose to close the phone number recordset. Notice that we’re closing the phone
number recordset (tmpRS), not the contacts recordset (rsHandle).

Datagrip User Manual, Version 2.0 27 August 21, 1998


Summary
We’ve created all the core functionality of a useful little contact management program. We
haven’t covered every detail of the code, and there are certainly a number of areas for
improvement in our program. Now would be a good time to look through the tutorial file or
refer to Appendix C to see how the scripts have been organized.

When you open TUTOR.DIR, you’ll find that any functions that work directly with the
database are in the script titled “DB Scripts”. Any functions that deal with the stage or user
interface are in “Interface Scripts”. Functions that initialize the entire application are located
in “Startup Scripts”.

This tutorial is designed to provide a high-level overview of Datagrip and show some
examples of using it in code. The tutorial only covers a small part of Datagrip’s functionality.
You’ll want to look through the Language Reference chapter to see all the other things
Datagrip can do.

As a final exercise, you might consider adding search capability to the contact manager.
You’ll need to add a new button to invoke a search, and perhaps a dialog box to enter the
search text. You can use the DGFindFirst function to search the database for a match.

We expect to be adding new functionality to Datagrip as well as releasing complimentary


products. We would like to know what you want in future releases of Datagrip as well as other
products. If you find a unique application for Datagrip or would like to see the product
improved in some way, tell us about it at our web site (www.INM.com).

Thank you for choosing Datagrip from Integration New Media, Inc.

Datagrip User Manual, Version 2.0 28 August 21, 1998


Chapter 4:
Authorware Tutorial

This chapter will help get you started using Datagrip™ by showing you step-by-step how to build
a simple Contact Manager application using Macromedia Authorware. If you are using Director,
refer to the previous chapter.

Opening the database


The first step in just about any database application is to open the database file. You’ll use the
DGOpenDatabase function. DGOpenDatabase takes one parameter, the name of the
database you want to open. If the database file exists in the same directory as packaged file,
you can simply use the name of the file like this:
dbHandle := DGOpenDatabase(“Tutor.mdb”)

In this case Tutor.mdb was a local file, but Datagrip can also open databases on a networked
disk. This can be very useful when you need to share a database between multiple projectors.

Opening a database on a network drive is essentially the same as opening a local database,
except that you include the name of the computer that the database is stored on using the
Universal Naming Convention (UNC) format. For example, to open a database on the
computer named FileServer you would make the following call.
dbHandle := DGOpenDatabase(“\\\\FileServer\\Tutor.mdb”)

If the DGOpenDatabase function succeeds, it returns a number called a handle. You’ll want
to store this handle in a variable because you’ll use it in other Datagrip functions to refer to
the open database. In the example above, the handle is stored in the variable dbHandle.

Every database you open will have a unique handle, so you can simultaneously open as many
databases as you need. Remember to store the handle for each open database in a separate
variable so you’ll have a way to refer to the databases in other parts of your code.

In the event that the DGOpenDatabase function fails, it will not return a number. Instead it
returns the special error string #ERROR#. The error might be caused by any number of
problems, such as a database file that is missing, or opened exclusively by another application
(such as Microsoft Access).

You should test the return value from DGOpenDatabase. If it is #ERROR#, you can use the
GetLastDGError function to get information on the cause of the problem.

Now let’s put what we’ve learned so far to practice. Following is the first part of the code
we’ll use to initialize the application. This code is located in the OpenDatabase icon.

Datagrip User Manual, Version 2.0 29 August 21, 1998


dbHandle := DGOpenDatabase("Tutor.mdb")
if dbHandle = "#ERROR#" then
LastErrorTxt := "Error in icon: Open Database: "^GetLastDGError()
ClearDGError()
quit
end if

In the first line, we open the database, which is located in the same directory as the movie file.
We store the handle that is returned in the global variable called dbHandle. Then we check to
see if an error occurred while opening by comparing dbHandle to #ERROR#. If
DGOpenDatabase returned #ERROR#, we call to GetLastDGError to find out what went
wrong and print out the error string that is returned.

After we’ve retrieved the error information, we call ClearDGError to reset the error
information. Since failing to open the database makes the program pretty useless, we exit at
this point.

Creating a Recordset
At this point, we have an open database, but we still haven’t retrieved any data. To read data
from the database, we need to create a recordset. A recordset, as the name implies, is a set of
records (rows) from one or more database tables. The recordset might contain all the records
in the table, or it might contain only a few records, based on some criteria we specify in an
SQL query.

To create a recordset, call the DGCreateRecordset function, which takes two parameters.
The first parameter is an SQL query string that defines which fields and records in the
database should be included in the recordset. The second parameter is the handle to the open
database, which was returned from DGOpenDatabase. Here’s what a typical call to
DGCreateRecordset looks like:
rsHandle := DGCreateRecordset("SELECT * FROM Contacts", dbHandle)

The first parameter is the SQL string, which says, “create a recordset that contains all fields
and all records from the Contacts table”. The query string could also specify that only records
that meet a certain criteria be returned. For example, the SQL string:
“SELECT * FROM CONTACTS WHERE COMPANY = ‘Integration New Media’”

returns only contacts where the company field contains the string “Integration New Media”.

Note
If you’re not familiar with SQL, we recommend you refer to one of the books on
Microsoft Access or SQL in the More Reading section.

The DGCreateRecordset function also returns a handle, much like the DGOpenDatabase
function. You’ll want to store this handle as well because you’ll use it to read and write data
from the recordset and perform other functions on the recordset.

If DGCreateRecordset encounters an error, it returns the standard error string, #ERROR#.

Datagrip User Manual, Version 2.0 30 August 21, 1998


Now let’s put together the open database code from the previous example with the code
required to open the recordset.
--
-- Open the Database
--
-- LastErrorTxt is shown across the bottom of the screen when it has a message in it.
dbHandle := DGOpenDatabase("Tutor.mdb")
if dbHandle = "#ERROR#" then
LastErrorTxt := "Error in icon: Open Database: "^GetLastDGError()
ClearDGError()
quit
end if

--
-- Create the recordset
--
QueryStr := "Select * from Contacts ORDER BY Contacts.LastName"
rsHandle := DGCreateRecordset(QueryStr, dbHandle)
if rsHandle = "#ERROR#" then
LastErrorTxt := LastErrorTxt^"\rError in icon Get Record Set ...: "^GetLastDGError()
ClearDGError()
quit
end if

You’ve already seen the first block of code that opens the database, so let’s start with opening
the recordset. We call the DGCreateRecordset with an SQL string that returns all the records
and fields from the Contacts table. We store the return value in rsHandle and check it for the
standard #ERROR# string. If an error occurs, we get the error information, print the error
string, and exit.

At this point, the recordset contains all the information from our Contacts table. But what
about the PhoneNumber table? There are several ways we can gain access to the
PhoneNumber data. One simple method is to use a join in SQL. You simply replace the SQL
string with this:
SELECT * From Contacts,PhoneNumbers Where Contacts.ContactID=PhoneNumber.ContactID

Or, alternatively:
SELECT Contacts.*, PhoneNumbers.* FROM Contacts INNER JOIN PhoneNumbers >>
ON Contacts.ContactID = PhoneNumbers.ContactID;

Now the recordset contains all the fields from the Contacts table and the PhoneNumbers table
(refer to Figure 5). Better still, the database has automatically matched up all the contacts with
their corresponding Phone Numbers. The only disadvantage to using this technique is that the
recordset actually contains one record for every contact and every phone number. This means
that if a contact has three phone numbers, the contact will exist three times in the recordset—
once with each of his or her phone numbers. For more information on SQL joins, refer to the
one of the books in Appendix B, More Reading.

Datagrip User Manual, Version 2.0 31 August 21, 1998


Figure 5. The recordset returned from the SQL join of the Contacts table and the PhoneNumber table.

For our purposes, the SQL join probably isn’t the best way to retrieve the phone numbers.
Instead, for each contact, we’ll create second recordset that contains all the phone numbers for
the current contact.

We could create the second record using another DGCreateRecordset call, much like the
first one. Assuming that we have the ContactID value for the contact whose phone numbers
we want to find, here’s what the code would look like:
queryStr := "SELECT * From PhoneNumbers Where ContactID=" ^CurContact
rsHandle := DGCreateRecordset(queryStr, dbHandle)

The query string (queryStr) says “get all the records in the PhoneNumbers table whose
ContactID is equal to CurContact. CurContact is the variable that contains the Contact ID for
the current contact.

Working with QueryDefs


In all the previous examples, we’ve entered a query string in the DGCreateRecordset call.
There, is however, another, more efficient way to handle queries. You can store queries in the
database file itself, in a QueryDef (Query Definition). A QueryDef is simply a query, just like
the ones we’ve seen up to this point, stored in the database file and given a name.

The advantage of stored queries is that they are faster than query strings in your code- up to
25% faster than opening a recordset with an SQL string. If you use a particular query several
places in your code, it’s also easier to maintain a single query in the database than defining it
all the places you need it in your code.

We open a QueryDef using the DGQDOpen function. Here’s an example:


qdHandle := DGQDOpen("PhoneQuery", dbHandle)
if qdHandle = "#ERROR#" then
LastErrorTxt := LastErrorTxt^"\rError in icon Get Record Set ...: "^GetLastDGError()
ClearDGError()
quit
end if

The first parameter to DGQDOpen is the name of the stored QueryDef. The second
parameter is the database handle returned from DGOpenDatabase.

By now, you recognize the error checking code. The DGQDOpen function returns a handle
just like the open database and creates recordset functions we’ve used so far. You’ll use the

Datagrip User Manual, Version 2.0 32 August 21, 1998


handle returned from DGQDOpen() to create a recordset based on the stored query. To create
a recordset based on a stored query, use the DGQDCreateRS function:
rsHandle := DGQDCreateRS(qdHandle)

Notice that the DGQDCreateRS function takes only one parameter—a QueryDef handle.
That’s because the QueryDef handle refers to a stored query in the database, so you don’t
need an SQL string or database handle.

Parameterized Queries
You’ll often want to use a stored query, but change one of its parameters. In the case of our
contact manager, we’ll use the following query to find the phone numbers for the current
contact:
"SELECT * From PhoneNumbers Where ContactID = " ^CurContact

We’ll store this query in the database as a QueryDef. However, we need to supply a value for
the CurContact variable each time we use the query. This is called a “parameterized query”
because we store the query, but we can modify one or more of the query’s parameters in our
code.

Here’s a segment of code that illustrates the process:


val := DGRSGetFieldValue("ContactID", rsHandle)
if val <> "#ERROR#" then
DGQDSetParameterValue("pContactID", val, qdHandle)
tmpRS := DGQDCreateRS(qdHandle)
end if

In the first line we use a new Datagrip function to read the value of the ContactID field from
the Contacts table using a recordset we’ve previously created. As long as no error occurred in
reading the value, we use that value in a DGQDSetParameterValue function. This function
takes three parameters:

pContactID is the name of the parameter in the query that we want to set.
Val is the value that we’re setting for the parameter
qdHandle is a handle to a previously opened QueryDef.

We won’t discuss the details of setting up a parameterized query in this tutorial. For more
information, refer to the reference section for the Datagrip QueryDef functions, which all
begin with DGQD or refer to the Microsoft Access help.

Once the parameter values are set with DGSetParameterValue, we call DGCreateRS to
create a recordset based on the QueryDef with the parameter values we set. When this code
segment finishes executing, the tmpRS recordset should contain all the phone numbers for the
particular ContactID we read from the Contacts table.

Datagrip User Manual, Version 2.0 33 August 21, 1998


Displaying the Contact Information
Now we have the information we need from the database. It’s time to display the information
on the screen. The main screen of our contact manager has seven fields that will hold the data
from the database (see Figure 1). The names of the fields on the screen correspond with the
fields in the database. There are fields for the first name, last name, address, company and
title. A list box displays the phone numbers and descriptions for the current contact.

There are several different approaches to displaying the field information on the screen. Two
methods will be described – field binding and manually updating field values. The tutorial
actually uses both approaches in order to show exactly how each method is implemented.
Binding Fields
One very powerful feature of Datagrip is the ability to directly bind Authorware variables to
database fields. Binding will result in the automatic update of the variable whenever the
current record changes. Field binding is accomplished by using the function DGRSBindField
as shown in the following code:
--
-- Link each variable to it's appropriate Database field
--
DGRSBindVar("FirstNameStr", "FirstName", rsHandle)
DGRSBindVar("LastNameStr", "LastName", rsHandle)
DGRSBindVar("TitleStr", "Title", rsHandle)
DGRSBindVar("CompanyStr", "Company", rsHandle)

The DGRSBindField function takes three parameters. The first parameter specifies the name
of the variable that will be bound. The second parameter is the name of the field in the
recordset, and the third parameter is a recordset handle.

All of the code to this point in the tutorial can be found in the “Setup Handlers & Fields” icon
in the source file.
Using DGRSGetFieldValue()
There are some situations where automatic field binding may not be the best choice. For
example, if the database stored codes in a particular field and you wanted to display the text
associated with the code, you may have to get the field value and convert the code to a string
using a property list or some other approach. In this case, you may want to use the function
DGRSGetFieldValue.

In the current tutorial, one field, the address field, is not bound and must be manually updated
whenever the position of the current record changes. You will see code similar to the
following code segment in a number of different icons (Next >, Prev <, etc.)
AddressStr := DGRSGetFieldValue("Address", rsHandle)

Prior to the field binding feature being added to Datagrip, the tutorial was designed so that any
time the recordset changed a series of calls would be made to DGRSGetFieldValue. This

Datagrip User Manual, Version 2.0 34 August 21, 1998


function takes two parameters. The first is the name of the fields in the recordset and the
second is a handle to out previously opened recordset.

DGRSGetFieldValue checks for an error using the standard method. If an error occurs, it
clears the field on screen by setting it to the empty string.

Using the Grid Functions


This section will show you how to use the grid functions in Datagrip to automatically control
the columns in a multi-column list box. Below is the “Phone Fields” and “Get Contact ID”
icons implemented using the grid functions taken directly from the tutorial.
--
--Get the ID of the current contact
--
CurContact := DGRSGetFieldValue("ContactID",rsHandle)
DGQDSetParameterValue("pContactID", CurContact, dbHandle)
phHandle := DGQDCreateRS(qdHandle)

if phHandle = "#ERROR#" then


LastErrorTxt := LastErrorTxt^"\rError in icon: Get Contact ID -
"^GetLastDGError()
ClearDGError()
end if

--
--Create a grid object and tie the phone number fields to it
--
gridHandle := DGCreateGrid("PhoneGrid", phHandle)
DGGridAddField("Description", 7, gridHandle)
DGGridAddField("PhoneNumber" ,15, gridHandle)
DGGridUpdate(gridHandle)

--
--Close the recordset since it will change
--every time we change records.
--
DGRSClose(phHandle)

Here is how the handler works. First, the variable CurContact is set to the value of the
ContactID field of the current record of Contacts recordset. Once again, you will want to
check to make sure the function did not return an error.

Setting the parameter value and opening the recordset using the QueryDef object is done
exactly as described earlier by calling DGQDSetParameterValue and DGQDCreateRS.

The next step is to make a call to DGCreateGrid to create a grid object and call
DGGridAddField for each of the columns that we want to display. Then, we call
DGGridUpdate to automatically fill the grid with the field values specified for all of the
records in the recordset. No looping required and much faster!

The first argument of DGCreateGrid is the name of the Authorware variable while the
second argument is the handle to a recordset. Following the creation of the grid, calling

Datagrip User Manual, Version 2.0 35 August 21, 1998


DGGridAddField will add new fields to the grid object in a left to right fashion. The first
argument to DGGridAddField is the name of the field in the recordset. The second argument
is the character width of the grid column and the third argument is a handle to a Datagrip grid
object.

Note
If the contents of the field has more characters than the column width specified
in the DGGridAddField function, the contents will be truncated.

Manually Filling a List Box


Sometimes manually filling the grid may be advantageous compared to the automatic method.
This might occur when the database contains codes instead of the actual text you want to
display. In any case, you can manually fill the grid by looping through each of the records in
the phone recordset and manually setting the list box data. This section will describe how to
do just that.

The recordset we created with the QueryDef in the previous section contains all the phone
numbers associated with the current contact. The following repeat loop reads the phone
number and description fields from each phone number record and fills a single large string
that has carriage returns between each phone number and description. Here’s the code:
repeat while not DGRSIsEOF(tmpRS)
desc := DGRSGetFieldValue("Description", tmpRS)
if desc = "#ERROR#" then desc := ""
num := DGRSGetFieldValue("PhoneNumber", tmpRS)
if num = "#ERROR#" then num := ""
tmpStr1 := tmpStr1^” “^num^”\r”
DGRSMoveNext(tmpRS)
end repeat
DGRSClose(tmpRS)

The loop begins with a call to DGRSIsEOF. This function returns a non-zero value if we’ve
gone past the end of the phone number recordset. Remember that tmpRS is the recordset
handle we created in the previous code segment. When we increment past the last record, the
loop stops.

For each pass through the loop (each phone number), we’ll read the value of the Description
and Phone Number fields by calling DGRSGetFieldValue for each field. We do the standard
error checking, and set the appropriate strings to empty if an error occurs. Once we’ve read
both the description and phone numbers from the database, we append them together with
some white space between them and a carriage return on the end. The results are appended to
tmpStr1.

At the bottom of the loop, we call DGRSMoveNext to move to the next record in the phone
numbers recordset. This process continues until we reach the last record in the recordset. The
DGRSClose function at the end of the loop closes the recordset we created to read the phone
numbers.

Datagrip User Manual, Version 2.0 36 August 21, 1998


When the loop finishes, tmpStr1 will contain all the phone numbers and descriptions for the
selected contact, separated by carriage returns as shown in Figure 1.

Then it’s a simple matter to assign this string to the variable that will display the text on
screen.
OnScreenVar := tmpStr1

Adding New Records


At this point, our contact manager application can display the first contact and all the phone
numbers assigned to that contact. We’ve actually done most of the work, but the application
isn’t too useful unless we can move through the contacts and add new ones.

There are three major steps to follow whenever you want to add a new record to a database or
change an existing record in the database. Here are the steps:
1. Call DGRSAddNew to add a new empty record or call DGRSEdit to edit an existing record.
2. Add data to the new record or change data in the existing record. If you’re modifying an
existing record, you can call DGRSGetFieldValue to read the current value of a field. Call
DGRSSetFieldValue function to put data into a field.
3. Call DGRSUpdate to save the new record or changes to the database.
You must repeat this process for every record you want to add or change.

Now that you know the process, let’s look at how we would implement code to add a new
record to our contact database. The following script, which is in the “NewRecord” subroutine,
does just that:
DGRSAddNew(rsHandle) -- Add a new record
CanWeEdit := DGRSGetEditMode(rsHandle)

if CanWeEdit = 2 then
DGRSSetFieldValue("FirstName", FirstNameStr, rsHandle)
DGRSSetFieldValue("LastName", LastNameStr, rsHandle)
DGRSSetFieldValue("Address", AddressStr, rsHandle)
DGRSSetFieldValue("Title", TitleStr, rsHandle)
DGRSSetFieldValue("Company", CompanyStr, rsHandle)
DGRSUpDate(rsHandle)
end if

In the “NewRecord” subroutine, we begin by calling the DGRSGetEditMode function,


which will return an integer indicating the state of the database.

If this function returns a 2, it means that a new record has been added to the database but not
yet saved. Each of the field values is saved by calling the DGRSSetFieldValue function. This
function takes three arguments. The first argument is the name of the field we want to store
data in. The second argument is the data we want to store. The last parameter is the global
recordset handle.

Once the field values have been saved, we’ll call the DGRSUpdate function to save the data
in the database.

Datagrip User Manual, Version 2.0 37 August 21, 1998


Now that the previous data, if any, has been saved, we call the DGRSAddNew function to
add a new empty record.

Navigating through the contacts


Our contact manager program is getting pretty functional. We can display a contact, including
all their phone numbers and we can add new contacts. However, you may have noticed that at
this point, we have no way of moving through the contacts in the database. You can only see
the first contact or the most recently added contact. We need to add some way to move
through the contact database.

Moving through the database one record at a time is pretty easy. We’ll add two subroutines
called Next and Prev and we’ll tie these to the Next and Previous buttons on screen.

If the current button is the last record in the recordset, the “Next” button is disabled. Likewise,
if we are positioned on the first record, the “Prevous” button is disabled. This behavior is
accomplished in the “Active If” property of the button.
--
-- Next Record Icon
--
DGRSMoveNext(rsHandle)
NoCurrentEntry := NoCurrentEntry + 1

--
--Previous Record Icon
--
DGRSMovePrev(rsHandle)
NoCurrentEntry := NoCurrentEntry –1

Each time the user clicks on the Next or Previous buttons, we call the corresponding
subroutines, which moves to the next record in the contact recordset, until we reach the
beginning or end of the records. Each time we move to a new record, we’ll also need to call
the code to get the corresponding phone numbers from the phone number table. We saw this
code when we looked at QueryDefs.

Adding Phone Numbers


One of the key features of our contact program is the ability to store as many phone numbers
as we want for a particular contact. However, we still need a way to add phone numbers to the
phone number table.

Following is the code for a function that will be called when the user clicks the
AddPhoneNumber button.

Datagrip User Manual, Version 2.0 38 August 21, 1998


--
--Store new phone #
--
DGRSClose(phHandle)
CurContact := DGRSGetFieldValue("ContactId",rsHandle)
QueryStr := "Select * From PhoneNumbers Where ContactID=" ^CurContact
phHandle := DGCreateRecordset(QueryStr, dbHandle)
DGRSAddNew(phHandle)
DGRSSetFieldValue("ContactID", CurContact, phHandle)
DGRSSetFieldValue("Description", PhoneNum[NextPhone,1], phHandle)
DGRSSetFieldValue("PhoneNumber",PhoneNum[NextPhone,2], phHandle)
DGRSUpDate(phHandle)

Now the real work begins. The next two lines copy the text from the cast members that store
the phone numbers and descriptions (tmpNum_Field and tmpDesc_Field) to temporary
variables. We need to check whether there are, in fact, any phone numbers or descriptions
entered, so the next line checks the number of words in the temporary variables. If they’re
both zero, we just quit. There’s no point in creating a new record to store empty strings.

If there is something to store, we read the ContactID field from the current contact record. As
long as there was no error in reading the ContactID value, we create a recordset from the
PhoneNumber table based on that contact ID. The query in the DGCreateRS function says
“get all the records in the PhoneNumbers table that have a ContactID of id. Id is the variable
that stores the ContactID we read from the Contacts table. The result is that the tmpRS
recordset contains all the phone numbers associated with the current contact.

Next, we add a new record to the recordset we just created. Then we call
DGRSSetFieldValue to store the ContactID, Description, and Phone Number fields for the
new record. Finally, we call DGRSUpdate to store the new record in the database and
DGRSClose to close the phone number recordset. Notice that we’re closing the phone
number recordset (tmpRS), not the contacts recordset (rsHandle).

Summary
We’ve created all the core functionality of a useful little contact management program. We
haven’t covered every detail of the code, and there are certainly a number of areas for
improvement in our program. Now would be a good time to look through the tutorial file or
refer to Appendix D to see how the scripts have been organized.

As a final exercise, you might consider adding search capability to the contact manager.
You’ll need to add a new button to invoke a search, and perhaps a dialog box to enter the
search text. You can use the DGRSFindFirst function to search the database for a match.

We expect to be adding new functionality to Datagrip as well as releasing complimentary


products. We would like to know what you want in future releases of Datagrip as well as other
products. If you find a unique application for Datagrip or would like to see the product
improved in some way, tell us about it at our web site (www.INM.com).

Thank you for choosing Datagrip from Integration New Media, Inc.

Datagrip User Manual, Version 2.0 39 August 21, 1998


Chapter 5
Language Reference

ClearDGError
Description: Clears the error buffer. When an error occurs a string buffer is filled with
a detailed message explaining the error. If you want to test and see if an
error occurred you could call GetLastDGError(), and then clear it with
this function.

Syntax: ClearDGError()

Returns: Nothing is returned from this function.

See Also: GetLastDGError.

Example: The example below checks to see if an error occurred and then clears the
error buffer. It’s a good idea to clear the error buffer after handling an
error so that it will always represent the most recent error, if any.

on exitFrame
if not voidP(GetLastDGError())
put GetLastDGError()
ClearDGError()
end if
end

Datagrip User Manual, Version 2.0 40 August 21, 1998


DGClose
Description: Closes an open database.

Syntax: DGClose(dbHandle)
dbHandle: A handle to a valid open database object.

Returns: Nothing is returned unless an error occurs, in which case the standard
error string is returned.

See Also: DGOpenDatabase

Example:

if DGClose(dbHandle) = "#ERROR#" then


alert "Error closing the database."
end if

Datagrip User Manual, Version 2.0 41 August 21, 1998


DGCreateGrid
Description: This function will create a multi-column version of the data in the
database. For instance if you wanted to display the first name, last name,
and age of each record in the database all in a nicely formatted way you
would use this function. The spacing is automatically handled for the
developer so the output looks very nice. For everything to line up
correctly you should use a fixed width font, such as Courier.

Syntax: DGCreateGrid(outName, rsHandle)

outName: If your using Authorware this should be the name of the


variable that will hold the grid once it is created. In Director this is the
name of the field that will hold grid.

rsHandle: A handle to a valid and open recordset.

Returns: Upon success this function returns a handle to a newly created grid
object. This handle will be used in later functions to format the grid. If
the function fails the standard error string will be returned.

See Also: DGGridAddField, DGGridDeleteField, DGGridUpdate

Example: The following example will create a new grid in the My_Field cast
member .

set gridHandle = DGCreateGrid(“My_Field”, rs)

The following example will create a new grid in the My_Var variable.

gridHandle := DGCreateGrid(“My_Var”, rs)

Datagrip User Manual, Version 2.0 42 August 21, 1998


DGCreateRecordset
Description: This function creates a recordset from an open database and a query
string. The recordset contains a set of records that meet the criteria
specified in the query string.

Syntax: DGCreateRecordset(sqlString, dbHandle)


sqlString: The SQL string that defines the recordset that you are opening.
dbHandle: A handle to an open database object. You can get this handle
by calling DGOpenDatabase.
Returns: If the function is successful it returns a handle to the recordset object. If
the call was not successful it returns the standard error string, #ERROR#.
Call GetLastDGError() for a more detailed description of the error.

See Also: DGOpenDatabase, GetLastDGError

Example: The example below opens a database and creates a recordset object that
will hold all of the fields in the 'Family' table. Finally it prints the handle
of the recordset object to the message window.

on exitFrame
set db = DGOpenDatabase("C:\MyDb.mdb")
set rs = DGCreateRecordset("SELECT * FROM Family", db)
put rs
end

Datagrip User Manual, Version 2.0 43 August 21, 1998


DGExecute
Description: Executes SQL commands on the database.

Syntax: DGExecute(sqlString, dbHandle)


sqlString: A string that contains the SQL commands to be executed.
dbHandle: A handle to an open database object.

Returns: Nothing if the function is successful. If an error occurs the standard error
string, #ERROR#, will be returned.

Example: The following example deletes all the records in the Family table.

on exitFrame
set db = DGOpenDatabase("C:\MyDb.mdb")
DGExecute("Delete * from Family",db)
end

Datagrip User Manual, Version 2.0 44 August 21, 1998


DGGetVersion
Description: This function will return the current version of Datagrip. It is important
to remember that this function is only available in version 2.0 and above.

Syntax: DGGetVersion()

Returns: A string will be returned specifying the version of the currently installed
Datagrip Xtra.

See Also: None.

Example: The following example ensures that Datagrip 2.0 is running.

if DGGetVersion() is not “2.0” then return

Datagrip User Manual, Version 2.0 45 August 21, 1998


DGGridAddField
Description: Adds a field to the grid list. This list holds every database field that will
be displayed in the grid.

Syntax: DGGridAddField(fieldName, size, gridHandle)

fieldName: The name of the field in the database to add to the grid list.

size: The number of characters to be displayed in the column inside the


grid.

gridHandle: A handle to a grid which has been created by


DGCreateGrid().

Returns: If this function is successful nothing is returned. In the case that


something went wrong the standard error string will be returned.

See Also: DGCreateGrid, DGGridDeleteField, DGGridUpdate.

Example: The following example will add the ID, Name, and PhoneNum fields
which exist in the open recordset. The results will be stored in the
My_Field cast member.

set gridHandle = DGCreateGrid(“My_Field”, rsHandle)


DGGridAddField(“ID”, 3, gridHandle)
DGGridAddField(“Name”, 8, gridHandle)
DGGridAddField(“PhoneNum”, 8, gridHandle)

Datagrip User Manual, Version 2.0 46 August 21, 1998


DGGridDeleteField
Description: This function deletes a field from the field list that the grid holds. When
you call this function the grid will no longer pull data from the specified
database field.

Syntax: DGGridDeleteField(fieldName, gridHandle)

fieldName: The name of the database field that you want to terminate a
connection with.

gridHandle: A valid grid handle created by DGCreateGrid().

Returns: If this function is successful then nothing is returned. On the other hand
if an error occurs then the standard error string is returned.

See Also: DGCreateGrid, DGGridAddField, DGGridUpdate.

Example: The following example will add two database fields to the grid and then
delete the initial one.

set gridHandle = DGCreateGrid(“My_Field”, rsHandle)


DGGridAddField(“ID”, 2, gridHandle)
DGGridAddField9(“Name”, 9, gridHandle)
DGGridDeleteField(“ID”, gridHandle)

Datagrip User Manual, Version 2.0 47 August 21, 1998


DGGridUpdate
Description: This function will update the cast member or the variable with the new
data from the grid object.

Syntax: DGGridUpdate(gridHandle)

gridHandlei: A handle to a valid grid object created by DGCreateGrid().

Returns: Nothing is returned unless an error occurs. In this case the standard error
string is returned.

See Also: DGCreateGrid, DGGridAddField, DGGridDeleteField.

Example: The following example will fill out the My_Field cast member with all of
the contents of two fields in the recordset. When the data transfer is done
all of the columns should line up.

set grid = DGCreateGrid(“My_Field”, rsHandle)


DGGridAddField(“Name”, grid)
DGGridAdDField(“PhoneNum”, grid)
DGGridUpdate(grid)

Datagrip User Manual, Version 2.0 48 August 21, 1998


DGIsDAORegistered
Description: This function will check to see if the DAO engine is installed. If by using
this function you discover that DAO is not installed then you will need to
register the DAO engine before Datagrip will run.

Syntax: DGIsDAORegistered()

Returns: A 1 meaning that the engine is installed, a 0 otherwise.

See Also: None.

Example: The following example checks to see if the engine is registered. If not
then a call to regsvr32 is made.

if not DGIsDAORegistered()
open “DAO350.DLL” with “C:\windows\system\regsvr32.exe”
end if

Datagrip User Manual, Version 2.0 49 August 21, 1998


DGOpenDatabase
Description: Use this function to open a database. When you open a database a
database handle is returned which you will use to reference this database
in other Datagrip functions. You can open as many databases
simultaneously as you need. Each open database has a unique handle.

Syntax: DGOpenDatabase(dbName)
DGOpendatabase(dbName, bExclusive, bReadOnly, connectionString)

dbName: The name of the database to be opened.


bExclusive: A boolean value specifying exclusive rights to the database.
bReadOnly: A boolean that allows you to open the database in a read
only mode. This is useful when reading the data off of a CDROM.
connectionString: A string that allows you to pass additional parameters
to the database. For instance a string that looks like
“;PWD=mypassword” will allow you to open a password protected
database. Simply substitute mypassword for the real password.
Returns: If the function is successful, it returns a handle. If the request was not
successful then the standard error string, #ERROR#, is returned.

See Also: GetLastDGError

Example: This example opens the first database using the simple form and then
opens another database using the extended form. The extended form
example will open the database in a read only mode.

on StartMovie
set dbHandle1 = DGOpenDatabase("C:\MyDB.mdb")
set dbHandle2 = DGOpendatabase(“DB1.mdb”, 0, 1, “”)
end

Datagrip User Manual, Version 2.0 50 August 21, 1998


DGQDClose
Description: Closes an open QueryDef object.

Syntax: DGQDClose(qdHandle)
qdHandle: A handle to an open QueryDef object that was created using
DGCreateQueryDef.
Returns: If the function was successful, it returns 1. If the function was not
successful, the standard error string is returned.

See Also: DGQDCreate, DGQDOpen

Example: The example closes the QueryDef only if it is open.

if DGQDIsOpen(qd) then
DGQDClose(qd)
end if

Datagrip User Manual, Version 2.0 51 August 21, 1998


DGQDCreate
Description: This function will create a new stored query in the database and return
the handle if the function was successful.

Syntax: DGQDCreate(queryName, sqlString, dbHandle)


queryName: The name that will be given to the query when it is stored in
the database.
sqlString: The SQL string that you want associated with the new query.
dbHandle: A handle to a Database object created.
Returns: If the function is successful a handle to the QueryDef is returned. If the
function fails, it returns the standard error string. You should call
GetLastDGError() for a more detailed description of the error.

See Also: None.

Example: The example will create a QueryDef and store it in the database.

set db = DGOpenDatabase("C:\MyDB.mdb")
set qd = DGQDCreate("MSQuery", "SELECT * FROM Family", db)
DGQDSetSQL("SELECT * FROM Family", qd)

Datagrip User Manual, Version 2.0 52 August 21, 1998


DGQDCreateRS
Description: Creates a Recordet object from a QueryDef object.

Syntax: DGQDCreateRS(qdHandle)
qdHandle: A handle to an open QueryDef object

Returns: If the function was successful it will return a handle to a Recordset that
can be used in all of the other recordset functions. If the functions fails
the standard error string, #ERROR#, is returned.

See Also: DGQDCreate, DGRS

Example: The following example will take a QueryDef, which was stored in the
database, create a recordset from it, and then check to see how many
fields are in the recordset.

DGQDOpen("MSQuery", qd)
rs = DGQDCreateRS(qd)
if rs <> "#ERROR#" then
put DGRSGetFieldCount(rs)
else
put GetLastDGError()
end if

Datagrip User Manual, Version 2.0 53 August 21, 1998


DGQDGetName
Description: Returns the name of a QueryDef, given the QueryDef handle.

Syntax: DGQDGetName(qdHandle)
qdHandle: A handle to an open QueryDef.

Returns: If the function is successful the name of the QueryDef will be returned as
a string. If the QueryDef has not been named, it is a new QueryDef and
is called a temporary query. If this is the case you will get a #Temporary
QueryDef# back. If the function fails it will return the standard error
string, #ERROR#.

See Also: DGQDCreate

Example: The example will print the name of the opened QueryDef to the message
window.

put DGQDGetName(qd)

Datagrip User Manual, Version 2.0 54 August 21, 1998


DGQDGetParameterCount
Description: Gets the number of parameters that are defined in a query.

Syntax: DGQDGetParameterCount(qdHandle)
qdHandle: A handle to an open QueryDef object.

Returns: If the function is successful it returns an integer which is the number of


parameters defined in the QueryDef. If the function fails the standard
error string is returned.

See Also: DGQDGetParameterValue, DGQDSetParameterValue

Example: The example prints out the number of parameters to the message
window.

on exitFrame
global qd

ret = DGQDGetParameterCount(qd)
if ret <> "#ERROR#" then
put ret
else
put GetLastDGError()
end if
end

Datagrip User Manual, Version 2.0 55 August 21, 1998


DGQDGetParameterValue
Description: Returns the value of a specific parameter that has been defined in a
QueryDef.

Syntax: DGQDGetParameterValue(paramName, qdHandle)


paramName: The name of the parameter whose value is being retrieved.
qdHandle: A handle to an open QueryDef object.

Returns: If the function was successful it returns the value of the parameter, which
could be a number or a string. If the function fails, the standard error
string is returned.

See Also: DGQDSetParameterValue, DGQDGetParameterCount, DGQDCreateRS,


DGRSRequery.

Example: The example below reads the value of a parameter called "ID"

global qd
pValue = DGQDGetParameterValue("ID", qd)
put "Parameter value = " & pValue

Datagrip User Manual, Version 2.0 56 August 21, 1998


DGQDGetSQL
Description: Returns the SQL string that defines a QueryDef.

Syntax: DGQDGetSQL(qdHandle)
qdHandle: A handle to an open QueryDef.

Returns: If the function is successful is returns an SQL string. If the function fails,
it returns the standard error string.

See Also: DGQDSetSQL, DGQDGetParameterValue, DGQDSetParameterValue

Example: The example gets the SQL string that defines the QueryDef and prints it
in the message window.

global qd
put DGQDGetSQL(qd)

Datagrip User Manual, Version 2.0 57 August 21, 1998


DGQDIsOpen
Description: Tests to see if the QueryDef is open or not.

Syntax: DGQDIsOpen(qd)
qdHandle: A handle to a QueryDef object.

Returns: If the function is successful it returns true (1) or false (0). If the function
fails, the standard error string is returned.

See Also: DGQDCreate, DGQDClose

Example: The following example checks to see if the query is open. If the query is
open the query is closed.

if DGQDIsOpen(qd) then
DGQDClose(qd)
end if

Datagrip User Manual, Version 2.0 58 August 21, 1998


DGQDOpen

Description; Opens a QueryDef object that has been defined previously in the
database.

Syntax; DGQDOpen(Queryname,qdHandle)
Queryname: The name of the predefined query to open.
qdHandle: A handle to a database object.
Returns: If the function is successful, it returns a handle. If the function fails, the
standard error string is returned.

See Also: DGQDClose, DGQDIsOpen.

Example: The example opens a predefined query.

global db
DGQDOpen("MSQuery", db)

Datagrip User Manual, Version 2.0 59 August 21, 1998


DGQDSetParameterValue
Description: Sets the value of a specific parameter in a QueryDef.

Syntax: DGQDSetParameterValue(paramName, value, qdHandle)


paramName: The name of the parameter to be set
value: The value of the parameter
qdHandle: A handle to a QueryDef object

Returns: If the function is successful nothing is returned. If the function fails, it


returns the standard error string, #ERROR#.

See Also: DGQDGetParameterValue, DGQDGetParameterCount

Example: The example changes the value of the ID parameter to 0.

if DGQDSetParameterValue("ID", 0, qd) = #ERROR# then


put GetLastDGError()
end if

Datagrip User Manual, Version 2.0 60 August 21, 1998


DGQDSetSQL
Description: Sets the SQL string that defines a QueryDef object.

Syntax: DGQDSetSQL(sqlString, qdHandle)


sqlString: The SQL string.
qdHandle: A handle to a QueryDef object

Returns: If the function fails, it returns #ERROR#. Otherwise, it returns nothing.

See Also: DGQDGetSQL.

Example: This example changes the SQL string so that it now references all of the
fields in the Person table.

if DGQDSetSQL("SELECT * FROM Person", qdHandle) = #ERROR# then


put GetLastDGError()
end if

Datagrip User Manual, Version 2.0 61 August 21, 1998


DGRSAddNew
Description: Adds a new record to the recordset.

Syntax: DGRSAddNew(rsHandle)
rsHandle: A handle to an open recordset.

Returns: If the function fails, it returns #ERROR#. Otherwise it returns nothing.

See Also: DGRSUpdate, DGRSEdit

Example: This example will add a new record to a recordset object whose handle is
defined globally.

global rsHandle
DGRSAddNew(rsHandle)

Datagrip User Manual, Version 2.0 62 August 21, 1998


DGRSBindField
Description: Binds a cast member field directly to a field in the database. This is
useful since anytime the recordset changes the field will automatically be
updated. The developer doesn’t have to call DGRSGetFieldValue() and
set the text, it is all done automatically. This function is only available in
Director.

Syntax: DGRSBindField(fieldName, dbField, rsHandle)

fieldName: The name of the field in Director to bind to.

dbField: The name of the field in the recordset to bind to.

rsHanddle: A handle to a valid and open recordset.

Returns: Upon success this function returns nothing. If the function fails then the
standard error string is returned.

See Also: DGRSBindVar.

Example: The following code will bind a field on the stage named My_Field to the
name field in the database. Once this is done anytime you call
DGRSMoveNext() the field will automatically contain the new data.

DGRSBindField(“My_Field”, “FirstName”, rsHandle)

Datagrip User Manual, Version 2.0 63 August 21, 1998


DGRSBindVar
Description: Use this function to tie a variable to a specific field in a recordset so that
when changes are made to the recordset the variable is automatically
updated. This is useful when stepping through records one at a time.

Syntax: DGRSBindVar(varName, dbField, rsHandle)

varName: The name of the variable that will be bound to the recordset.
This should be in the form of a string.

dbField: The name of the field in the recordset which will be bound.

rsHandle: A handle to valid and open recordset.

Returns: On success this function returns nothing except that the variable is now
tied to the recordset. If the function fails then the standard error string
will be returned.

See Also: DGRSBindField.

Example: The following example will tie a variable called MyVar to the ID field in
the recordset.

set MyVar = 0
DGRSBindVar(“MyVar”, “ID”, rs)

Datagrip User Manual, Version 2.0 64 August 21, 1998


DGRSCanAppend
Description: Determines if the recordset supports adding new records.

Syntax: DGRSCanAppend(rsHandle)
rsHande: A handle to a recordset object.

Returns: If the recordset supports adding new records the function returns 1. If the
recordset does not allow new records, the function returns 0. If the
function fails (which would happen if rsHandle is not a valid handle to
an open recordset), the function returns #ERROR#.

See Also: DGRSAddNew

Example: The example below checks to see if the database allows new records. If it
does it will add a new record.

if DGRSCanAppend(rs) = 1 then
DGRSAddNew(rs)
end if

Datagrip User Manual, Version 2.0 65 August 21, 1998


DGRSCancelUpdate
Description: Cancels any pending updates. When a call has been made to either
DGRSAddNew or DGRSEdit and the call to DGRSUpdate has not yet
been made, this function will cancel any changes made after the AddNew
or Edit operation.

Syntax: DGRSCancelUpdate(rsHandle)
rsHande: A handle to a recordset object.

Returns: This function returns the standard error string, #ERROR#, if an error
occurs. Otherwise, it returns nothing.

See Also: DGRSUpdate

Example: This example makes a change to a recordset, and then cancels it.

DGRSEdit(rs)
DGRSSetFieldValue("Phone", "633-3333", rs)
DGRSCancelUpdate(rs)

Datagrip User Manual, Version 2.0 66 August 21, 1998


DGRSCanScroll
Description: Checks to see if the current record can be moved (scrolled).

Syntax: DGRSCanScroll(rsHandle)
rsHande: A handle to a records object

Returns: The function returns 1 if scrolling is allowed or 0 if not. If an error


occurs the standard error string, #ERROR#, is returned.

See Also: DGRSCanTransact

Example: The following example determines if we can scroll through the


Recordset. If we can, move the recordset forward 2 records.

if DGRSCanScroll(rs) then
DGRSMoveNext(rs)
DGRSMoveNext(rs)
end if

Datagrip User Manual, Version 2.0 67 August 21, 1998


DGRSCanTransact
Description: Determines whether the database supports transactions.

Syntax: DGRSCanTransact(rsHandle)
rsHande: A handle to a recordset object.

Returns: The function returns one if the database supports transactions and zero if
it does not. If an error occurs, the standard error string, #ERROR# is
returned.

See Also: DGRSCanScroll

Example: This example checks to see if the database supports transactions.

if DGRSCanTransact(rs) then put "Transactions supported"

Datagrip User Manual, Version 2.0 68 August 21, 1998


DGRSCanUpdate
Description: Determines whether the database is ready for updating.

Syntax: DGRSCanUpdate(rsHandle)
rsHande: A handle to a recordset object.

Returns: This function returns one if the database is read for updating, and zero if
not. If an error occurs, the standard error string, #ERROR# is returned.

See Also: DGRSUpdate, DGRSEdit

Example: The following example checks to see if the database is currently able to
update. If it returns true, DGRSUpdate is called.

if DGRSCanUpdate(rs) = 1 then
DGRSUpdate(rs)
end if

Datagrip User Manual, Version 2.0 69 August 21, 1998


DGRSClose
Description: Closes an open recordset object.

Syntax: DGRSClose(rsHandle)
rsHande: A handle to a recordset object.

Returns: This function returns nothing unless an error occurs. If an error occurs,
the function returns the standard error string, #ERROR#.

See Also: DGCreateRecordset.

Example: The following example checks to see if the recordset is open and then
closes it.

if DGRSIsOpen(rs) then
DGRSClose(rs)
end if

Datagrip User Manual, Version 2.0 70 August 21, 1998


DGRSDelete
Description: Deletes the current record in the recordset.

Syntax: DGRSDelete(rsHandle)
rsHande: A handle to a recordset object.

Returns: This function returns nothing unless an error occurs. If an error occurs,
the function returns the standard error string, #ERROR#.

See Also: DGRSUpdate, DGRSEdit.

Example: The following example deletes the current record.

if DGRSDelete(rs) = "#ERROR#" then


put "Error"
end if

Datagrip User Manual, Version 2.0 71 August 21, 1998


DGRSEdit
Description: Prepares the current record for editing.

Syntax: DGRSEdit(rsHandlei)
rsHande: A handle to a recordset object.

Returns: This function returns nothing unless an error occurs. If an error occurs,
the function returns the standard error string, #ERROR#.

See Also: DGRSUpdate, DGRSAddNew.

Example: This example puts the string "Rob" in the "Name" field of the current
record.

DGRSEdit(rs)
DGRSSetFieldValue("Name", "Rob", rs)
DGRSUpdate(rs)

Datagrip User Manual, Version 2.0 72 August 21, 1998


DGRSFillList
Description: This function will build a list of all records of a specified field in the
passed recordset. For instance if you have a database full of names you
could call this function to fill a list variable with the entire database all in
one call.

Syntax: listVar = DGRSFillList(dbField, rsHandle)

listVar: A variable that will hold the list when the function is finished.

dbField: The name of the field in the recordset that contains the needed
data.

rsHandle: A handle to a valid and open recordset.

Returns: If this function fails it will return the standard error string. If this
function succeeds then a list containing the new data will be returned.

See Also: DGRSFillField, DGCreateGrid.

Example: The following example makes a list of each record from the first name
field in the recordset. Before you can use a list you must initialize the
variable.

set MyList = []
set MyList = DGRSFillList(“FirstName”, rsHandle)

Datagrip User Manual, Version 2.0 73 August 21, 1998


DGRSFillString
Description: This function will allow you to automatically fill a string with the data
from a specific field for an entire recordset. For instance if you wanted to
display all of the names in your database in a field you would use this
function. This function is not supported in Authorware.

Syntax: string = DGRSFillString(dbField, rsHandle)

string: The new string that is returned.

dbField: The name of the field in the recordset that contains the data.

rsHandle: A handle to a valid and open recordset.

Returns: When the function fails the standard error string is returned. If the
function is successful then a string is returned that contains all of the new
data.

See Also: DGRSBindField, DGRSCreateGrid.

Example: The following example will automatically fill the field with all of the
names in my recordset.

set str = DGRSFillField(“FirstName”, rs)


set the text of member “My_Field” = str

Datagrip User Manual, Version 2.0 74 August 21, 1998


DGRSFindFirst
Description: Finds the first instance of a record that matches a specified criteria. The
criteria is specified by a string that is the WHERE clause of an SQL
statement without the WHERE keyword.

Syntax: DGRSFindFirst(string, rsHandle)


string: The criteria string. This is the WHERE clause of an SQL
statement without the keyword WHERE.
rsHande: A handle to a recordset object.
Returns: If a record is found that matches the criteria, a non-zero number is
returned. If no instances were found, the function returns zero. If an error
occurs, the function returns the standard error string, #ERROR#.

See Also: DGRSFindLast, DGRSFindNext, DGRSFindPrev

Example: This example finds the first record whose "ID" field is equal to 5.

if DGRSFindFirst("ID = 5", rs) <> 0 then


put "Found record ID = 5"
end if

Datagrip User Manual, Version 2.0 75 August 21, 1998


DGRSFindLast
Description: Finds the last instance of a record that matches the specified criteria. The
criteria is specified by a string that is the WHERE clause of an SQL
statement without the WHERE keyword.

Syntax: DGRSFindLast(string, rsHandle)


string: The criteria string. This is the WHERE clause of an SQL
statement without the keyword WHERE.
rsHande: A handle to a recordset object.
Returns: If a record is found that matches the criteria, a non-zero number is
returned. If no instances were found, the function returns zero. If an error
occurs, the function returns the standard error string, #ERROR#.

See Also: DGRSFindFirst, DGRSFindNext, DGRSFindPrev

Example: This example finds the last record whose "ID" field is equal to 5.

if DGRSFindLast("ID = 5", rs) <> 0 then


put "Found record ID = 5"
end if

Datagrip User Manual, Version 2.0 76 August 21, 1998


DGRSFindNext
Description: Finds the next instance of a record that matches a specified criteria. The
criteria is specified by a string that is the WHERE clause of an SQL
statement without the WHERE keyword.

Syntax: DGRSFindNext(string, rsHandle)


string: The criteria string. This is the WHERE clause of an SQL
statement without the keyword WHERE.
rsHande: A handle to a recordset object.

Returns: If a record is found that matches the criteria, a non-zero number is


returned. If no instances were found, the function returns zero. If an error
occurs, the function returns the standard error string, #ERROR#.

See Also: DGRSFindLast, DGRSFindFirst, DGRSFindPrev

Example: This example finds the first record whose age is equal to 5.

if DGRSFindNext("ID = 5", rs) <> 0 then


put "Found record ID = 5"
end if

Datagrip User Manual, Version 2.0 77 August 21, 1998


DGRSFindPrev
Description: Finds the previous instance of a record that matches a specified criteria.
The criteria is specified by a string that is the WHERE clause of an SQL
statement without the WHERE keyword.

Syntax: DGRSFindPrev(string, rsHandle)


string: The criteria string. This is the WHERE clause of an SQL
statement without the keyword WHERE.
rsHande: A handle to a recordset object.

Returns: If a record is found that matches the criteria, a non-zero number is


returned. If no instances were found, the function returns zero. If an error
occurs, the function returns the standard error string, #ERROR#.

See Also: DGRSFindLast, DGRSFindNext, DGRSFindFirst.

Example: This example finds the first record whose age is equal to 5.

if DGRSFindNext("ID = 5", rs) <> 0 then


put "Found record ID = 5"
end if

Datagrip User Manual, Version 2.0 78 August 21, 1998


DGRSGetAbsolutePosition
Description: Determines the absolute position of the current record within the
recordset.

Syntax: DGRSGetAbsolutePosition(rsHandle)
rsHande: A handle to a recordset object

Returns: If the function is successful it returns an integer between 0 and the


number of records in the recordset. This value is the absolute position of
the current record in the recordset. If the function fails, the standard error
string, #ERROR# is returned.

See Also: DGRSSetAbsolutePosition

Example: The following example gets the current absolute position and prints the
number to the message window.

put DGRSGetAbsolutePosition(rs)

Datagrip User Manual, Version 2.0 79 August 21, 1998


DGRSGetEditMode
Description: Gets the current edit state of the recordset.

Syntax: DGRSGetEditMode(rsHandle)

rsHande: A handle to a recordset object.

Returns: This function returns an integer that indicates the current edit mode of
the recordset. The return value will be one of the following:

0 No editing operation in progress


1 DGRSEdit has been called.
2 DGRSAddNew has been called.
If an error occurs, such as rsHandle is not a valid recordset handle, the
function returns the standard error string, #ERROR#.

See Also: DGRSEdit, DGRSAddNew, DGRSUpdate

Example: This example checks the edit mode. If DGRSAddNew or DGRSEdit


have been called, it will call DGRSUpdate to save the new data.

if DGRSGetEditMode(rs) > 0 then


DGRSUpdate(rs)
end if

Datagrip User Manual, Version 2.0 80 August 21, 1998


DGRSGetFieldCount
Description: Determines the number of fields in the current recordset.

Note
This function may take a significant amount of time to execute when
using large databases. In order to return a value, the records in the
database must be counted, which can be a time-consuming operation.

Syntax: DGRSGetFieldCount(rsHandle)
rsHande: A handle to a recordset object.

Returns: If the function is successful then it returns an integer that specifies the
number of fields in the current recordset. If the function fails, it returns
the standard error string, #ERROR#.

See Also: None.

Example: This example determines the number of fields in the recordset and prints
it out to the message window.

put DGRSGetFieldCount(rs)

Datagrip User Manual, Version 2.0 81 August 21, 1998


DGRSGetFieldValue
Description: Returns the value of a specified field in a recordset.

Syntax: DGRSGetFieldValue(fieldName, rsHandle)


fieldName: The name of the field to be read.
rsHandle: A handle to an open recordset object.

Returns: If the function is successful it returns the data from the field named in
fieldname. in the current recordset. The value that is returned can be an
integer, a float, or string.

When currency values are returned they do not include the dollar sign
and the values are returned as floats.

If an error occurs (other than overflow described above) in retrieving the


data from the database, this function returns the standard error string,
#ERROR#.

Access also support hyperlinks. When a hyperlink is returned you get a


string in this format

"address#protocol://address#"

This is an example of what the database would return:

"www.inm.com#http://www.inm.com#"

Note
Hyperlinks are only supported in Access version 8.0 or later databases.

See Also: DGRSSetFieldValue, GetLastDGError

Example: The example below prints the value of the field named "Address" in the
current record to the message window.

put DGRSGetFieldValue("Address", rsHandle)

Datagrip User Manual, Version 2.0 82 August 21, 1998


DGRSGetLockingMode
Description: Determines the current locking mode for a given recordset.

Syntax: DGRSGetLockingMode(handle)

handle: A handle to a valid and open recordset.

Returns: Upon success, the mode is returned which will be a 1 or a 0. If an error


occurs the standard error string will be returned.

See Also: DGRSSetLockingMode, DGRSGetEditMode.

Example: The following example checks to see if the recordset is using optimistic
locking. If it is, set it to pessimistic which is safer.

if DGRSGetLockingMode(rsHandle) = 0 then
DGRSSetLockingMode(1, rsHandle)
end if

Datagrip User Manual, Version 2.0 83 August 21, 1998


DGRSGetName
Description: Gets the name of the recordset.

Syntax: DGRSGetName(rsHandle)
rsHande: A handle to a recordset object.

Returns: If successful it returns a string which is the name of the recordset. In


some cases the Recordset may not have a name. In these cases the string
#Temporary QueryDef# is returned. If the function fails, it returns the
standard error string, #ERROR#.

See Also: None.

Example: Prints the name of the recordset to the message window.

put DGRSGetName(rs)

Datagrip User Manual, Version 2.0 84 August 21, 1998


DGRSGetPercentPosition
Description: Gets the position of the current record and returns it as a percentage.

Note
This function may not return an accurate indication of the record
position under some circumstances, because the number of records in
a recordset is not known until all the records have been accessed.

This function may take a significant amount of time to execute when


using large databases. In order to return a value, the records in the
database must be counted, which can be a time-consuming operation.

Syntax: DGRSGetPercentPosition(rsHandlei)
rsHande: A handle to a recordset object.
Returns: This function returns a two-digit float value which represent the position
of the current record in the recordset expressed as a percentage. If the
function fails, it returns the standard error string, #ERROR#.

See Also: DGRSGetAbsolutePosition

Example: This example will determine if the current record is more than half way
through the entire Recordset and will print a message to the message
window.

if DGRSGetPercentPosition(rs) > .50 then


put "We are at least 50% the way through the records."
end if

Datagrip User Manual, Version 2.0 85 August 21, 1998


DGRSGetRecordCount
Description: Gets the number of records in the current recordset.

Note
This function may not return an accurate count of records in many
cases. The record count that is returned is the number of the last
record that has been accessed. Unless the current record has been
moved to the last record prior to calling this function, the record
count may not be accurate. Call DGRSMoveLast before calling
DGRSGetRecordCount to insure that the record count is accurate.

Syntax: DGRSGetRecordCount(rsHandle)
rsHande: A handle to a recordset object.
Returns: This function returns the number of records in the recordset. If the
function fails, it returns the standard error string, #ERROR#.

See Also: None.

Example: This code segment will determine if we have more than 10 people in our
address book database.

if DGRSGetRecordCount(rs) > 10 then


put "We have more than 10 people."
end if

Datagrip User Manual, Version 2.0 86 August 21, 1998


DGRSGetSQL
Description: Returns the SQL string that defines the recordset.

Syntax: DGRSGetSQL(rsHandle)
rsHandle: A handle to an open Recordset.

Returns: This function returns a string that contains the SQL query that defines
the recordset. If the function fails, it returns #ERROR#.

See Also: DGQDGetParameterValue, DGQDSetParameterValue

Example: The example gets the SQL string that defines the recordset and prints it
to the message window.

global qd
put DGQDGetSQL(qd)

Datagrip User Manual, Version 2.0 87 August 21, 1998


DGRSImportResource
Description: Use this function to import bitmaps and wave files that are stored in the
database.

Syntax: DGRSImportResource(memberRef, dbField, rsHandle)

memberRef: A member reference that will hold the new resource.

dbField: The name of the field in the recordset that contains the resource
you are importing.

rsHandle: A handle to a valid and open recordset.

Returns: If successful nothing is returned from this function but the specified cast
member should now contain the imported data. When the function fails it
will return the standard error string.

See Also: None.

Example: This example will import a wave file that has been stored in the wave
field of a previously opened recordset. When the function is done the 10th
cast member of the third cast will contain the new wave.

DGRSImportResource(member 10 of castLib 3, “Wave”, rs)


Notes: For this function to work you must have a valid OLE server program
registered to open bitmaps and waves. Windows comes configured with
Paintbrush and Sound Recorder registered which will work just fine.
When you are inserting data in to the database ensure that the data is
being inserted as a Wave or a Bitmap. If Package ever appears in the
database field inside Access then you don’t have a valid OLE server
registered. The easiest way to solve this problem is to reinstall Paintbrush
and Sound Recorder. This is only required on the system that is inserting
the resources. The end users machine and other development machines
will be able to read the resources without a problem. To re-install
Paintbrush follow these steps:

1. Open the control panel

2. Double click on ‘Add/Remove Program’

3. Select Windows Setup

4. Scroll down and select Multimedia

Datagrip User Manual, Version 2.0 88 August 21, 1998


5. Click on details

6. Scroll down and un-check Paintbrush

7. Continue clicking ‘OK’ until you at the control panel.

8. Go back in to ‘Add/Remove Programs’

9. Select Windows Setup

10. Scroll down to Multimedia

11. Click on details

12. Scroll down and check Paintbrush.

13. Click ‘OK’ until you are back to the control panel.

At this point you should be able to successfully insert bitmaps in to the


database. To do the same thing for wave files follow the same procedure
except select Sound Recorder instead of Paintbrush in steps 6 and 12.

When importing resources it is possible that Director is currently reading


that data. This will be a problem if you are playing a sound and then try
and replace the cast member with this function. To prevent this Datagrip
will run in two modes. The first mode is the Safe Mode. This means that
you cannot import a wave file while any of the sound channels are busy.
The function will simply return an error. You can turn off Safe Mode
with a call to DGSetAudioSafeMode(). When you override this function
Datagrip no longer performs the check to see if a sound is currently
being played. In this case you need to make sure that you don’t try and
replace data that Director is using.

Datagrip User Manual, Version 2.0 89 August 21, 1998


DGRSIsBOF
Description: Determines if the current record is past the beginning of the recordset.

Syntax: DGRSIsBOF(rsHandle)
rsHandle: A handle to a recordset object.

Returns: This function returns one (true) if the current record is before the
beginning of the recordset, or zero (false) if the current record is in the
recordset. If the function fails (e.g. rsHandle is not a valid recordset
handle), it returns the standard error string, #ERROR#.

See Also: DGRSIsEOF

Example: The following example moves to the previous record if we are not past
the beginning of the recordset. Because DGRSisBOF only returns true
after the current record moves past the beginning of the recordset, you
must move, test, and move back if DGRSIsBOF returns true.

DGRSMovePrev(rsHandle)
if not DGRSIsBOF(rsHandle) then
DGRSMoveNext(rsHandle)
end if

Datagrip User Manual, Version 2.0 90 August 21, 1998


DGRSIsEOF
Description: Determines if the current record is past the end of the recordset.

Syntax: DGRSIsEOF(rsHandle)
rsHandle: A handle to a recordset object.

Returns: This function returns one (true) if the current record is after the end of
the recordset, or zero (false) if the current record is in the recordset. If the
function fails (e.g. rsHandle is not a valid recordset handle), it returns the
standard error string, #ERROR#.

See Also: DGRSIsBOF

Example: The following example moves to the next record if we are not past the
end of the recordset. Because DGRSisEOF only returns true after the
current record moves past the end of the recordset, you must move, test,
and move back if DGRSIsEOF returns true.

DGRSMoveNext(rsHandle)
if not DGRSIsEOF(rsHandle) then
DGRSMovePrev(rsHandle)
end if

Datagrip User Manual, Version 2.0 91 August 21, 1998


DGRSIsOpen
Description: Determines if the current recordset is open.

Syntax: DGRSIsOpen(rsHandle)
rsHandle: A handle to a recordset object.

Returns: This function returns one if the recordset is open, or zero if it is not open.
If an error occurs (e.g. rsHandle isn't a valid recordset handle), the
function returns the standard error string, #ERROR#.

See Also: DGRSClose

Example: This example will check to see if the current recordset is open. If it is
open, the recordset is closed.

if DGRSIsOpen(rs) then DGRSClose(rs)

Datagrip User Manual, Version 2.0 92 August 21, 1998


DGRSMoveFirst
Description: Moves to the first record of a recordset.

Syntax: DGRSMoveFirst(rsHandle)
rsHandle: A handle to a recordset object.

Returns: If the function is successful it returns nothing. Otherwise, it returns the


standard error string, #ERROR#.

See Also: DGRSMoveLast, DGRSMoveNext, DGRSMovePrev

Example: This example will move to the first record if we are past the end of the
recordset. This would be convenient way to "wrap around" to the
beginning of the records when you've reached the end of the recordset.

if DGRSIsEOF(rs) then DGRSMoveFirst(rs)

Datagrip User Manual, Version 2.0 93 August 21, 1998


DGRSMove
Description: Moves forward or backwards a specified number of records.

Syntax: DGRSMove(index, rsHandle)


index: The number of records to move. A positive value will move
forward and a negative value will move backwards.
rsHandle: A handle to a recordset object.

Returns: If the function is successful, nothing is returned. Otherwise, the standard


string is returned, #ERROR#. Note that specifiying a number of records
to move the current record past the end or beginning of the recordset
does not generate an error. You can, however, test for this condition
using DGRSIsEOF and DGRSIsBOF.

See Also: DGRSMoveFirst, DGRSMoveLast, DGRSMoveNext, DGRSMovePrev,


DGRSIsEOF, DGRSIsBOF

Example: The example below will move forward by two records.

DGRSMove(2, rs)
if DGRSIsEOF then
DGRsMovePrev(rs)
end if

Datagrip User Manual, Version 2.0 94 August 21, 1998


DGRSMoveLast
Description: Moves to the last record of a recordset.

Syntax: DGRSMoveLast(rsHandle)
rsHandle: A handle to a recordset object.

Returns: If the function is successful it returns nothing. Otherwise, it returns the


standard error string, #ERROR#.

See Also: DGRSMoveFirst, DGRSMoveNext, DGRSMovePrev

Example: This example will move to the last record if we are past the beginning of
the recordset. This would be convenient way to "wrap around" to the end
of the records when you've reached the beginning of the recordset.

if DGRSIsBOF(rs) then DGRSMoveLast(rs)

Datagrip User Manual, Version 2.0 95 August 21, 1998


DGRSMoveNext
Description: Moves to the next record of a recordset.

Syntax: DGRSMoveNext(rsHandle)
rsHandle: A handle to a recordset object.

Returns: If the function is successful, nothing is returned. Otherwise, the standard


error string, #ERROR# is returned.

See Also: DGRSMoveFirst, DGRSMoveLast, DGRSMovePrev, DGRSIsEOF

Example: The following example moves to the next record if we are not past the
end of the recordset. Because DGRSIsEOF only returns true after the
current record moves past the end of the recordset, you must move, test,
and move back if DGRSIsEOF returns true.

DGRSMoveNext(rsHandle)
if not DGRSIsEOF(rsHandle) then
DGRSMovePrev(rsHandle)
end if

Datagrip User Manual, Version 2.0 96 August 21, 1998


DGRSMovePrev
Description: Moves to the previous record of a recordset.

Syntax: DGRSMovePrev(rsHandle)
rsHandle: A handle to a recordset object.

Returns: If the function is successful, nothing is returned. Otherwise, the standard


error string, #ERROR# is returned.

See Also: DGRSMoveFirst, DGRSMoveNext, DGRSMoveLast, DSRSIsBOF

Example: The following example moves to the previous record if we are not past
the beginning of the recordset. Because DGRSIsBOF only returns true
after the current record moves past the beginning of the recordset, you
must move, test, and move back if DGRSIsBOF returns true.

DGRSMovePrev(rsHandle)
if not DGRSIsBOF(rsHandle) then
DGRSMoveNext(rsHandle)
end if

Datagrip User Manual, Version 2.0 97 August 21, 1998


DGRSReQuery
Description: Refreshes a recordset by running the query again.

Syntax: DGRSReQuery(rsHandle)
rsHandle: This is a handle to a recordset.

Returns: If successful, the function will returns one, otherwise the standard error
string, #ERROR#, is returned.

See Also: DGQDCreateRS, DGQDSetParameterValue.

Example: This example will open a querydef, set a parameter and use the resulting
recordset to get a phone number from the database. Once we have the
first number the parameter in the querydef is changed and we requery our
original recordset to get the new data.

global rsHandle
set qdHandle = DGQDOpen(“PhoneQuery”, dbHandle)
DGQDSetParameterValue(“ContactID”, CurContact, >>
qdHandle)
set rsHandle = DGQDCreateRS(qdHandle)
set myNum = DGRSGetFieldValue(“PhoneNumber”, rsHandle)

DGQDSetParameterValue(“ContactID”, CurContact + 1, >>


qdHandle)
DGRSRequery(rsHandle)
Set myNum2 = DGRSGetFieldValue(“PhoneNumber”, rsHandle)

Datagrip User Manual, Version 2.0 98 August 21, 1998


DGRSSetAbsolutePosition
Description: Sets the current position of the recordset according to an absolute value.

Syntax: DGRSSetAbsolutePosition(value, rsHandle)


value: The record number to move to
rsHandle: This is a handle to a recordset.

Returns: If the function is successful, nothing is returned. Otherwise, the standard


error string, #ERROR# is returned. Note that moving to a record number
that is beyond the end of the recordset does not return an error. However,
you can test for this condition using DGRSIsEOF.

See Also: DGRSGetAbsolutePosition.

Example: This example gets a position, move the record and then returns to it.

val = DGRSGetAbsolutePosition(rs)
DGRSMoveFirst(rs)
DGRSSetAbsolutePosition(val, rs)

Datagrip User Manual, Version 2.0 99 August 21, 1998


DGRSSetFieldValue
Description: Use this function to set the value of a specified field in a recordset.

Syntax: DGRSSetFieldValue (fieldName, value, rsHandle)


fieldName: The name of the field to be set in the current record.
value: The new value to be stored in the field named fieldname.
rsHandle: The recordset handle

Returns: If the function is successful, nothing is returned. Otherwise, the standard


error string, #ERROR# is returned.

See Also: GetLastDGError, DGRSGetFieldValue

Example: The example below changes the value of the field named "Address" in
the database MyDb.mdb. First it opens the database then creates a
recordset and finally sets the value "123 Mystreet"

set db = DGOpenDatabase("C:\MyDB.mdb")
set rs = DGCreateRecordset("SELECT * FROM People", db)
return DGRSSetFieldValue("Address", "123 Mystreet", rs)

Datagrip User Manual, Version 2.0 100 August 21, 1998


DGRSSetLockingMode
Description: This function will allow you to switch back and forth between optimistic
and pessimistic recordset locking. Locking is a concern when you are
dealing in a multi-user environment since you want to prevent two users
from editing the same record at the same time. If you use pessimistic
locking then only one user will be able to edit a record at a time. In fact
what happens is the engine actually locks a 2K segment of data that no
one can edit until the first user is done. It is important to remember that a
record is usually less than 2K which means you could actually be locking
more than one record at a time. Your other option is optimistic locking
which allows multiple users to edit the same data at the same time but
when they try and save the data with the update command an error will
be returned. Remember that pessimistic locking is the default mode.

Benefits:

Pessimistic locking: Ensures that only one person will be editing the data
at any given time.

Optimistic locking: Only has the record locked for a very short period of
time when the user is saving the data.

Disadvantages:

Pessimistic locking: Locks the recordset for a long period of time. In fact
the user could initiate an edit command and then leave the keyboard
which would mean the recordset would be locked for a very long period
of time.

Optimistic locking: Possibility that multiple users will be able to edit the
same data at the same time. Which means when they save their data an
error will occur.

Syntax: DGRSSetLockingMode(mode, handle)

mode: 1 is pessimistic and a 0 is optimistic.

handle: A handle to a valid and open recordset object.

Returns: Upon success nothing is returned but when an error occurs the standard
Datagrip error string will be sent back.

See Also: DGRSGetEditMode, DGRSGetLockingMode.

Datagrip User Manual, Version 2.0 101 August 21, 1998


Example: The following example will turn pessimistic locking off so that we can
prevent users from locking a recordset for to long.

global rsHandle
DGRSSetLockingMode(0, rsHandle)

Datagrip User Manual, Version 2.0 102 August 21, 1998


DGRSUnbindField
Description: This function breaks the connection between a bound field and the
database. Once this function is called the field will no longer be
automatically updated.

Syntax: DGRSUnbindField(fieldName, rsHandle)

fieldName: The name of the cast member to break the connection with.

rsHandle: A handle to the recordset that the field was bound to.

Returns: If this function was unsuccessful then the standard error string will be
returned. Otherwise nothing will be returned.

See Also; DGRSBindField, DGRSBindVar, DGRSUnBindVar.

Example: The following example will break a previously made connection between
the cast member “My_Field” and the datbase.

global rsHandle
DGRSUnbindField(“My_Field”, rsHandle)

Datagrip User Manual, Version 2.0 103 August 21, 1998


DGRSUnbindVar
Description: This function will break the automatic data transfer connection between
the database and a variable.

Syntax: DGRSUnbindVar(varName, rsHandle)

varName: The name of the variable to break the connection with. This
should be in the form of a string.

rsHandle: The handle to the recordset to which the variable was bound.

Returns: If this function succeeds nothing is returned. If this function fails then the
standard error string is returned.

See Also: DGRSBindVar, DGRSUnBindField, DGRSBindField.

Example: The following example assumes that the recordset is already tied to my
ID variable. Here we are just breaking the connection.

global rsHandle
DGRSUnbindVar(“ID”, rsHandle)

Datagrip User Manual, Version 2.0 104 August 21, 1998


DGRSUpdate
Description: Saves changes made to a recordset to the database. This function should
only called after DGRSAddNew or DGRSEdit have been called.

Syntax: DGRSUpdate(rsHandle)
rsHandle: This is a handle to a recordset.

Returns: If the function is successful, nothing is returned. Otherwise, the standard


error string, #ERROR# is returned

See Also: DGRSEdit, DGRSAddNew

Example: The following example adds a new record to the recordset and then calls
update to save it in the database.

DGRSAddNew(rs)
DGRSSetFieldValue("Name", "Rob", rs)
DGRSUpdate(rs)

Datagrip User Manual, Version 2.0 105 August 21, 1998


DGGetRegValue
Description: Retrieves a value from the system registry.

Syntax: DGGetRegValue(HKEY, path, key)

HKEY: The HKEY to open. This can be one of the following:

HKEY_LOCAL_MACHINE
HKEY_CURRENT_USER
HKEY_CLASSES_ROOT
HKEY_USERS
HKEY_CURRENT_CONFIG.
path: The path to the key that you are retrieving.

key: A key name to lookup.

Returns: If an error occurred the standard error string, #ERROR#, will be


returned. If the function was successful nothing will be returned.

See Also: DGSetRegVal.

Example: This example will get the value of the key

HKEY_LOCAL_MACHINE\SOFTWARE\INM\Datagrip\Path

put DGGetRegVal("HKEY_LOCAL_MACHINE", "SOFTWARE\INM\Datagrip",


"Path")

Datagrip User Manual, Version 2.0 106 August 21, 1998


GetLastDGError
Description: Returns a descriptive string explaining the last error that occurred.

Syntax: GetLastDGError()

Returns: A string that gives more detail on the most recent error.

Datagrip User Manual, Version 2.0 107 August 21, 1998


DGSetAudioSafeMode
Description: This function sets the Safe Mode state of Datagrip. If Safe Mode is on
then you won’t be able to import waves while a sound channel is in use.
When Safe Mode is turned off you can import waves at any time but you
must be careful not to overwrite any data that Director is currently
reading.

Syntax: DGSetAudioSafeMode(state)

state: A 1 if you want Safe Mode on, a 0 otherwise.

Returns: Nothing is returned.

See Also: DGImportResource.

Example: The following example turns Safe Mode on.

DGSetAudioSafeMode(1)

Datagrip User Manual, Version 2.0 108 August 21, 1998


DGSetRegVal
Description: Sets the value of a key in the registry.

Syntax: DGSetRegVal(HKEY, path, key, value)

HKEY: The HKEY that you are opening. HKEY can be one of the
following:

HKEY_LOCAL_MACHINE
HKEY_CURRENT_USER
HKEY_CLASSES_ROOT
HKEY_USERS
HKEY_CURRENT_CONFIG.
path: The path to the key you are updating.

key: The specific key you are creating or updating. If this value is set to
an empty string ("") you will be setting the value of the default setting in
the folder specified in path.

value: This can be an integer or a text string. This is the value that the
key will be set to.

Returns: An integer or a string will be returned if the function was successful. If


an error occurred then the standard error string, #ERROR#, will be
returned.

See Also: DGGetRegVal.

Example: The following example will create a new folder and new key just as you
might do for your company when releasing a product.

DGSetRegVal("HKEY_LOCAL_MACHINE", "SOFTWARE\INM", "", "")


DGSetRegVal("HKEY_LOCAL_MACHINE", "SOFTWARE\INM", "Path",
"C:\SSS")

Datagrip User Manual, Version 2.0 109 August 21, 1998


Chapter 6
Distributing your Datagrip Applications

Credits Requirements
When you distribute an application that uses Datagrip your license agreement requires that
you display a credit line for Datagrip. The credit line should say “Database connectivity
provided by Datagrip”. It must be readable, in a font of at least 10 points, and must be visible
for at least four seconds. The ideal place to place this credit line is on the credits page required
by Macromedia with the Director/Authorware logo.

If your application will not be distributed, you are not required to include this credit line. An
example of a presentation that doesn't require a credit line is a business presentation that is
only used by a single presenter.

Distributing Datagrip
Parts of Datagrip are copyrighted by Microsoft. If you intend to distribute a Datagrip
application, you must own one of the following Microsoft products in order to have the right
to distribute the Microsoft DLL files that support Datagrip. Typically, you'll need Microsoft
Access to create and maintain databases anyway, so this requirement shouldn't be a problem.

You must own one of the following products in order to distribute Datagrip:
• Microsoft Access
• Microsoft Visual Basic
• Microsoft Visual C++
Datagrip can only be used in the Director/Authoware design environment on the licensed
user's computer. When you distribute Datagrip with an application you create, the users who
receive your application cannot use Datagrip in the Director/Authorware design environment.

Datagrip User Manual, Version 2.0 110 August 21, 1998


Datagrip Files
When you distribute Datagrip you will need to ship some of the run time files along with the
Xtra. You, the developer, have two options as to how you wish to handle this. The first option
which is what most people will do is to copy each of the listed files to their appropriate
locations on the user's hard drive. The second option is to place each of the files in the same
directory as the EXE that will run your application

If you choose the first option and decide to place the files on the users hard drive you will
want to remember that the names of these directories may change for international versions of
windows. There are instructions below to help you determine the correct folder placement.

If you choose the second option which is to leave the files on the CD you will want to be sure
and check to see if the files already exist on the users system. An easy way to determine this is
to make a call to DGIsDAORegistered which will check and see if the necessary components
are there. When the files don’t exist on the users system you will need to register them on the
CD. But if they do exist you will never want to register them on the CD since it will break
other applications. Also, remember to unregister the file once you are done if you registered it
in the beginning!
Location File Name
Folder named "Xtras" next to your Director DGREL.X32
projector or Authorware packaged piece
Windows System Folder MSVCRT20.DLL
VBAR332.DLL
MSJET35.DLL
MSVCRT40.DLL
MSVCRT.DLL
MSVCIRT.DLL
MSJINT35.DLL
MSJTER35.DLL
MSRD2X35.DLL (needs to be registered)
VBAJET32.DLL
Program Files\Common Files\Microsoft DAO350.DLL (needs to be registered)
Shared\DAO Folder
DAO2535.TLB

Note
For international installations the ‘Program Files\Common Files’ directory
may be named something different. To determine the location of this directory
you can look in the user’s registry. In the key:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\CommonFilesDir

Datagrip User Manual, Version 2.0 111 August 21, 1998


There are two DLL’s that are listed as needing to be registered. This means that windows will
need to know some additional information about the DLL before it can be used. Registering a
DLL is very easy to do. The first and by far the best choice is to use an installer package that
will automatically handle the registration for you. If you don’t know how to turn on
registration in your installer search the help system for “Self Registration”, “Active-X”, or
“OCX”.

Occasionally it is not feasible to put an installer on the front of your application. In this case
you can use a program called REGSVR32.EXE. This program is located in the Windows
system directory. To use it you execute it and on the command line pass the path to the file
you are trying to register. This program comes with a variety of calling options. To see these
options call REGSVR32.EXE without anything on the command line.

Datagrip User Manual, Version 2.0 112 August 21, 1998


Appendix A:
Glossary

Current record
The record within a recordset that will be read from, written to, or deleted. Many
Datagrip functions move the current record. For example, DGMoveNext moves the
current record to the next record in the recordset.

Field
Columns in a database table are called fields. Fields have a name that you use to refer to
them. For example, DGRSGetFieldValue gets the value of a field in the current record
whose name you supply. When you create a recordset, the field names in the recordset
are generally the same as the field names in the original database table.

Handle
A handle is a number that you use to refer to a Datagrip object, such as a database,
recordset, or querydef. The Datagrip Open or Create functions typically return a handle
that you’ll store in a variable and use until you close the object.

Lingo
Macromedia Director’s scripting language is called Lingo. More recently, both Director’s
and Authorware’s scripting languages are referred to as the “Macromeda Scripting
Language”. This manual assumes some familiarity with the scripting language. See the
More Reading section for information on learning and using the Macromedia Scripting
Language.

Path
A Path is the set of all the directories (sometimes called “folders”) that you need to open
to get to a particular file.

Query
A Query is a statement that defines which records (rows) you want to retrieve from a
database. Queries are written using the Structured Query Language (SQL).

Querydef
A Querydef is a query that is stored in a database file. Querydefs are more efficient than
queries you enter as strings in your code because the database can examine the query in
advance and prepare it for use. The Datagrip functions for using QueryDefs all start with
DGQD (Datagrip QueryDef).

Record
A record is one row in a database table or the recordset you create from the database table
using a query.

Datagrip User Manual, Version 2.0 114 August 21, 1998


Recordset
A recordset, as the term implies, is a set of records. The set of records is typically created
by executing a query, either using the Datagrip DGCreateRecordset function or the
DGQDCreateRS function.

Relational database
A relational database is a database that allows you to create multiple tables and make
relationships between the tables based on certain fields. Microsoft Access databases are
relational. We used this feature in the tutorial by creating two tables and relating them
using the ContactID field.

Stored query
See querydef

SQL
Structured Query Language. The SQL language defines a standard way to write queries
to retrieve data and perform other actions on a database. Datagrip uses a Microsoft
implementation of SQL, which is identical in most respects to the standard SQL. For
more information on the differences, refer to the Microsoft Access documentation.

Datagrip User Manual, Version 2.0 115 August 21, 1998


Appendix B:
More Reading

Here are some other books that may be useful for understanding database concepts, SQL, and
the Macromedia Scripting Language.
1. Understanding SQL, Martin Gruber , Sybex
2. Using Lingo Macromedia Director product documentation
3. Jet Database Engine Programmer's Guide, Dan Haught and Jim Ferguson, Microsoft Press,
1995
4. Microsoft Access Help File provided with the Access software

Datagrip User Manual, Version 2.0 116 August 21, 1998


Appendix C:
Example Director Code

Startup Scripts
----------------------------------------
-- StartMovie
--
-- this is called when the projector is
-- initially launched
----------------------------------------
on startMovie
InitGlobals
InitDB
end

----------------------------------------
-- InitGlobals
--
-- This function will initialize and set
-- all of the global variables.It should
-- be called once at startup
----------------------------------------
on InitGlobals
global DBHandle --A handle to a database
global RSHandle --A handle to a recordset
global QDHandle --A handle to a querydef
global picCastMem --The member to hold the pics
global waveCastMem --The member that will hold the wave file

--
--Initially set these handles to 0 since
--any handle that is returned will be
--greater than 0
--
set DBHandle = 0
set RSHandle = 0
set QDHandle = 0
set picCastMem = 64
set waveCastMem = 65
end

----------------------------------------
--InitDB
--
-- This function will initially open the
-- database and create a recordset that
-- will allow us to read and edit all of
-- the contacts in our database
----------------------------------------
on InitDB
global dbHandle
global rsHandle
global qdHandle

--
--Open the contacts database assuming
--that it exists in the local directory.
--If it doesn't we will get an error back
--that we can use to communicate with the user
--
set dbHandle = DGOpenDatabase(the moviePath & "Tutor.mdb")
if dbHandle = "#ERROR#" then
alert "Error: " & GetLastDGError()

Datagrip User Manual, Version 2.0 117 August 21, 1998


alert "Now exiting the program."
ClearDGError()
quit
end if

--
--This SQL string will define our
--recordset. It essentially means
--Select everything that exists
--inside the Contacts table.
--
set sqlString = "SELECT * FROM Contacts"

--
--Open a recordset using our above created
--SQL string and our database handle
--
set rsHandle = DGCreateRecordset(sqlString, dbHandle)
if rsHandle = "#ERROR#" then
alert "Error: " & GetLastDGError()
alert "Now exiting the program."
quit
end if

--
--Link each field to its appropriate Database field
--
DGRSBindField("FirstName_Field", "FirstName", rsHandle)
DGRSBindField("LastName_Field", "LastName", rsHandle)
DGRSBindField("Company_Field", "Company", rsHandle)
DGRSBindField("Title_Field", "Title", rsHandle)

--
--Open a stored query that will retrieve all of
--the phone numbers for us
--
set qdHandle = DGQDOpen("PhoneQuery", dbHandle)
if qdHandle = "#ERROR#" then
alert "Error: " & GetLastDGError()
alert "Now exiting the program."
quit
end if
end

Button Scripts
--NEXT BUTTON SCRIPT

on mouseUp
GoToNextRecord()
end

--PREV BUTTON SCRIPT

on mouseUp
GoToPrevRecord()
End

--ADD BUTTON SCRIPT

on mouseUp
AddNumberToDB()
set the text of field "tmpDesc_Field" = ""
set the text of field "tmpNum_field" = ""
FillPhoneNumFields()
End

--NEW RECORD BUTTON

Datagrip User Manual, Version 2.0 118 August 21, 1998


on mouseUp
CreateNewRecord()
ClearFields()
End

--DIAL BUTTON SCRIPT

on mouseUp
global rsHandle
global waveCastMem

--
--Pull our wave file out of the database
--
DGRSImportResource(member waveCastMem, "Wave", rsHandle)
puppetSOund member waveCastMem
end

Frame Scripts
--GO TO THE FRAME

on exitFrame
go to the frame
end

Interface Scripts
----------------------------------------
--ClearFields
--
-- Description:
-- Clears all of the fields on the stage
--
----------------------------------------
on ClearFields
global picCastMem

set the text of member "FirstName_Field" = ""


set the text of member "LastName_Field" = ""
set the text of member "Address_Field" = ""
set the text of member "Title_Field" = ""
set the text of member "Company_Field" = ""
set the text of member "PhoneNum_Field" = ""

--
--picCastMem holds the member number where the
--pictures are stored. When we create a
--new entry we will want to erase this
--since there won't be a pic in the DB
--
erase member picCastMem
end

------------------------------------------
--SaveCurrentData
--
-- Description:
-- Runs through each of the fields on the
-- stage and calls a save function which
-- takes the text and calls the save function
-- in the database.
--
------------------------------------------
on SaveCurrentData
global rsHandle
global dbhandle

Datagrip User Manual, Version 2.0 119 August 21, 1998


--
--Put the database in edit mode so we
--can change the data
--
if DGRSGetEditMode(rsHandle) = 0 then
put DGRSEdit(rsHandle)
end if

--
--Save all of the data
--
SaveDBField("FirstName")
SaveDBField("LastName")
SaveDBField("Address")
SaveDBField("Title")
SaveDBField("Company")

--
--Call the final save for the rest of
--the data
--
DGRSUpdate(rsHandle)
end

Database Scripts
----------------------------------
--SetFieldVal
--
-- params:
-- fieldName: the name of the field on the stage
-- dbField : the field in the DB
--
-- Returns:
-- The value in the field. If an error
-- occurs nothing will be returned but
-- an error dialog will be displayed
--
-- Notes:
-- This function uses a global variable as
-- the recordset handle.
----------------------------------
on SetFieldVal fieldName, dbField
global rsHandle

set val = DGRSGetFieldValue(dbFIeld, rsHandle)


if val = "#ERROR#" then
alert "Error while retrieving from " & fieldName & RETURN & GetLastDGError()
ClearDGError()
set the text of member fieldName = ""
else
set the text of member fieldName = val
end if
end

-----------------------------------
--GoToNextRecord
--
-- Description:
-- Moves to the next record in the
-- current recordset.
-----------------------------------
on GoToNextRecord
global rsHandle
global qdHandle
global picCastMem

--

Datagrip User Manual, Version 2.0 120 August 21, 1998


--Check to see if the user has
--created a new record without
--saving. If this is the case
--save it and go on.
--
if DGRSGetEditMode(rsHandle) = 2 then
SaveCurrentData()
DGRSUpdate(rsHandle)
end if

--
--Make sure we don't go past
--the end of the file
--
DGRSMoveNext(rsHandle)

if DGRSIsEof(rsHandle) then
DGRSMovePrev(rsHandle)
return
end if

--
--There is one field in our user interface
--that we have decided to handle manually.
--This is for no other reason that to provide
--an example of another data retrieval method.
--
set txt = DGRSGetFieldValue("Address", rsHandle)
if txt <> "#ERROR#" then
set the text of member "Address_Field" = txt
end if

--
--The following will erase the last member
--make it in visible, replace it, and turn
--it back on. Usually this is not needed.
--If you just replace the cast member with
--a simple call to DGImportResource() it all
--happens extremely fast!
--
erase member picCastMem
set the visible of sprite 2 = 0
DGRSImportResource(member picCastMem, "Photo", rsHandle)
set the visible of sprite 2 = 1

FillPhoneNumFields

end

---------------------------------
--GoToPrevRecord
--
-- Description:
-- Moves to the previous record
-- in the current recordset
---------------------------------
on GoToPrevRecord
global rsHandle
global qdHandle
global picCastMem

--
--Check to see if the user has
--created a new record without
--saving. If this is the case
--save it and go on.
--

Datagrip User Manual, Version 2.0 121 August 21, 1998


if DGRSGetEditMode(rsHandle) = 2 then
SaveCurrentData()
DGRSUpdate(rsHandle)
end if

--
--Make sure we don't go passed
--the begining of the file
--
DGRSMovePrev(rsHandle)

if DGRSIsBOF(rsHandle) then
DGRSMoveNext(rsHandle)
return
end if

--
--There is one field in our user interface
--that we have decided to handle manually.
--This is for no other reason that to provide
--an example of another data retrieval method.
--
set txt = DGRSGetFieldValue("Address", rsHandle)
if txt <> "#ERROR#" then
set the text of member "Address_Field" = txt
end if

--
--The following will erase the last member
--make it in visible, replace it, and turn
--it back on. Usually this is not needed.
--If you just replace the cast member with
--a simple call to DGImportResource() it all
--happens extremely fast!
--
erase member picCastMem
set the visible of sprite 2 = 0
DGRSImportResource(member picCastMem, "Photo", rsHandle)
set the visible of sprite 2 = 1

FillPhoneNumFields

end

-----------------------------------
--CreateNewRecord
--
-- Description:
-- Creates a new record inside the
-- database that is ready to be
-- filled with data.
----------------------------------
on CreateNewRecord
global rsHandle

--
--Check to see if there is an
--unsaved record. If so save it
--
if DGRSGetEditMode(rsHandle)=2 then
SaveCurrentData()
put DGRSUpdate(rsHandle)
end if

--
--Once you create a new record and
--append it to the database the engine

Datagrip User Manual, Version 2.0 122 August 21, 1998


--moves the current record to the record
--that was being displayed before the
--addnew call was made. This will mess
--with our next/prev scheme so we need
--to be sure that we are at the last
--record before we create a new one
--

DGRSMoveLast(rsHandle)
DGRSAddNew(rsHandle)
end

----------------------------------
--SaveDBField
--
-- params:
-- fieldName:
-- the name of the field on
-- the stage.
--
-- Description:
-- This will pull all of the data
-- from the fields on the stage
-- and save it in the corresponing
-- database field
--
----------------------------------
on SaveDBField fieldName
global rsHandle

--
--Append a "_Field" to the member name, get its text
--and then save it to the database.
--
put "SetFieldValue Result: " && DGRSSetFieldValue(FieldName , the text of member
(fieldName & "_Field"), rsHandle)
end

--------------------------------------------
--AddNumberToDB()
--
-- Description:
-- Takes the number and description from
-- the temp fields and records them
-- in the database.
--------------------------------------------
on AddNumberToDB
global rsHandle
global dbHandle

--
--Check to see if the user has
--created a new record without
--saving. If this is the case
--save it and go on.
--
if DGRSGetEditMode(rsHandle) = 2 then
SaveCurrentData()
DGRSUpdate(rsHandle)
DGRSMoveLast(rsHandle)
end if

--
--Get our data
--
set descStr = the text of member "tmpDesc_Field"
set NumStr = the text of member "tmpNum_Field"

Datagrip User Manual, Version 2.0 123 August 21, 1998


--
-- Do a check to make sure there is data in
-- atleast one of the fields.
--
if the number of words in descStr =0 and the number of words in numStr =0 then
return
end if

--
--Get the associated contact id and enter it in the new records
--
set id = DGRSGetFieldValue("ContactID", rsHandle)
if id <> "#ERROR#" then
set tmpRS = DGCreateRecordset("SELECT * FROM PhoneNumbers Where ContactID =" && id,
dbHandle)
DGRSAddNew(tmpRS)
DGRSSetFieldValue("ContactID", id, tmpRS)
DGRSSetFieldValue("Description", descStr, tmpRS)
DGRSSetFieldValue("PhoneNumber", numStr, tmpRS)
DGRSUpdate(tmpRS)
DGRSClose(tmpRS)
end if
end

--------------------------------------------
--FillPhoneNumFields()
--
-- Description:
-- Creates a grid in the phone number box
--
--------------------------------------------
on FillPhoneNumFields
global rsHandle
global qdHandle

--
-- First, get the value of the contact ID from the current
-- record of the contact recordset
--
set val = DGRSGetFieldValue("ContactID", rsHandle)

if val <> "#ERROR#" then


--
-- Set the parameter "pContactID" in the phone queryDef to
-- the contact ID and open the recordset.
--
DGQDSetParameterValue("pContactID", val, qdHandle)
set tmpRS = DGQDCreateRS(qdHandle)

if tmpRS <> "#ERROR#" then


--
--Create a grid and add the needed fields
--
set gridHandle = DGCreateGrid("PhoneNum_Field", tmpRS)
DGGridAddField("Description", 13, gridHandle)
DGGridAddField("PhoneNumber", 14, gridHandle)

--
--Tell the grid to fill in all of the data
--
DGGridUpdate(gridHandle)
end if
end if
end

Datagrip User Manual, Version 2.0 124 August 21, 1998


Appendix D:
Example Authorware Code

Startup Scripts
Initialize Arrays
-- Datagrip Demo V 1.0
--
--
-- This Data Grip Demo was Programmed by Don Cowper at TransTech Interactive Training Inc
--
-- "After spending weeks fighting with ODBC, what a pleasure to find a Access database
-- conductivity product that really works with Authorware. DataGrip has good error messaging,
-- all the functions you could require and blazing speed. I wrote this PIM demo in a single day!"
-- --Don Cowper
--
--
-- Special Note: If you want to use a string to query the database enclose it in single quotes
-- inside a set of double quotes.
--
-- eg FindLastName := "'Jones'" -- single quotes within double quotes
-- Array PhoneNum holds the description in field 1 and the number in field 2

PhoneNum := Array("",10,2)

Open Database
-- LastErrorTxt is shown across the bottom of the screen when it has a message in it.
dbHandle := DGOpenDatabase("Tutor.mdb")
if dbHandle = "#ERROR#" then
LastErrorTxt := "Error in icon: Open Database: "^GetLastDGError()
ClearDGError()
end if

Get Record Set & Phone Set Handles


--
--Create a recordset containing all of the contacts and sort them by last name
--
QueryStr := "Select * from Contacts ORDER BY Contacts.LastName"

rsHandle := DGCreateRecordset(QueryStr, dbHandle)


if rsHandle = "#ERROR#" then
LastErrorTxt := LastErrorTxt^"\rError in icon Get Record Set ...: "^GetLastDGError()
ClearDGError()
end if

qdHandle := DGQDOpen("PhoneQuery", dbHandle)


if qdHandle = "#ERROR#" then
LastErrorTxt := LastErrorTxt^"\rError opening stored Query...:"^GetLastDGError()
ClearDGError()
end if

--
--Bind the main fields to the database so that we don't have to
--update the fields every time the data changes.
--
DGRSBindVar("FirstNameStr", "FirstName", rsHandle)
DGRSBindVar("LastNameStr", "LastName", rsHandle)
DGRSBindVar("TitleStr", "Title", rsHandle)
DGRSBindVar("CompanyStr", "Company", rsHandle)

--
--Notice in the above list of bound fields we did not
--include the Address field. This is for no other reason
--than that we have decided to demonstrate the manual
--approach to retrieving data. This next call will fill in the data
--for the first record. Subsequent records will be updated
--in the Next and Prev icons.

Datagrip User Manual, Version 2.0 125 August 21, 1998


--
AddressStr := DGRSGetFieldValue("Address", rsHandle)

Retrieve First Record in Database


DGRSMoveLast(rsHandle)
HowManyEntries := DGRSGetRecordCount(rsHandle)
DGRSMoveFirst(rsHandle)
NoCurrentEntry := 1

Subroutines
Initialize Phone # & Fields
--Bank Previous Telephone Array
repeat with J := 1 to 10
PhoneNum[J,1] := PhoneNum[J,2] := ""
end repeat
FirstNameStr := LastNameStr := AddressStr := TitleStr := CompanyStr := ""

Get Form Fields


if DGRSGetRecordCount(rsHandle) > 0 then
FirstNameStr := DGRSGetFieldValue("FirstName",rsHandle)
LastNameStr := DGRSGetFieldValue("LastName",rsHandle)
AddressStr := DGRSGetFieldValue("Address",rsHandle)
TitleStr := DGRSGetFieldValue("Title",rsHandle)
CompanyStr := DGRSGetFieldValue("Company",rsHandle)
end if

Get Contact ID
--
--Get the ID of the current contact
--
CurContact := DGRSGetFieldValue("ContactID",rsHandle)
DGQDSetParameterValue("pContactID", CurContact, dbHandle)
phHandle := DGQDCreateRS(qdHandle)

if phHandle = "#ERROR#" then


LastErrorTxt := LastErrorTxt^"\rError in icon: Get Contact ID - "^GetLastDGError()
ClearDGError()
end if

Get Phone Fields


--
--Create a grid object and tie the phone number fields to it
--
gridHandle := DGCreateGrid("PhoneGrid", phHandle)
DGGridAddField("Description", 7, gridHandle)
DGGridAddField("PhoneNumber" ,15, gridHandle)
DGGridUpdate(gridHandle)

--
--Close the recordset since it will change
--every time we change records.
--
DGRSClose(phHandle)

Next
DGRSMoveNext(rsHandle)
NoCurrentEntry := NoCurrentEntry + 1
--
--At this point we will need to fill in the address field
--
txt := DGRSGetFieldValue("Address", rsHandle)
if txt <> "#ERROR#" then
AddressStr := txt
end if

Prev
DGRSMovePrev(rsHandle)
NoCurrentEntry := NoCurrentEntry -1

--
--At this point we will need to fill in the address field
--

Datagrip User Manual, Version 2.0 126 August 21, 1998


txt := DGRSGetFieldValue("Address", rsHandle)
if txt <> "#ERROR#" then
AddressStr := txt
end if

Store Values in Database


DGRSAddNew(rsHandle) -- Add a new record
CanWeEdit := DGRSGetEditMode(rsHandle)
if CanWeEdit = 2 then
DGRSSetFieldValue("FirstName", FirstNameStr, rsHandle)
DGRSSetFieldValue("LastName", LastNameStr, rsHandle)
DGRSSetFieldValue("Address", AddressStr, rsHandle)
DGRSSetFieldValue("Title", TitleStr, rsHandle)
DGRSSetFieldValue("Company", CompanyStr, rsHandle)
DGRSUpDate(rsHandle)
end if
--Adjust the count of records in the database.

Count the new number of entries


DGRSMoveLast(rsHandle)
HowManyEntries := DGRSGetRecordCount(rsHandle)
DGRSMoveFirst(rsHandle)
NoCurrentEntry := 1

Count the new number of entries


DGRSMoveLast(rsHandle)
HowManyEntries := DGRSGetRecordCount(rsHandle)
DGRSMoveFirst(rsHandle)
NoCurrentEntry := 1

Delete the current entry


DGRSDelete(rsHandle)
DGRSUpDate(rsHandle)

Datagrip User Manual, Version 2.0 127 August 21, 1998


Appendix E:
What’s new in Datagrip 2.0

1. The capability to import bitmaps and waves from the access DB:
Now you can store your bitmaps and wave files right in the database. Then when you need
them you can import them in to a cast member on the fly. This is useful for projects that have
many pictures each associated with some data. An example would be an online product
catalog. You could have all of the product information and a picture of that product stored in
the database. If you use our competitor products you will have to store a path name in the DB
and then import it off of the hard disk which is a very slow process.
2. Automatic data binding to variables:
This feature allows you to tie a variable in Director or Authorware to a specific field in a
database. When the variable is tied anything you do to the database is automatically reflected
in the variable. If you move to the next record, edit the record, delete the record, or cause any
change the variable is automatically updated for you. This saves the programmer from having
to write extra code to handle the retrieval of the data every time a change is made. An
example where a developer would want to use this tracking is an ID number. You could tie
the ID number of the current record to a variable and provide the user a way to move back and
forth through the records. No matter where the user navigates to your variable will always
hold the current ID.
3. Automatic data binding to field cast members:
The same as above except that the data is stored in a field object instead of a variable. This is
useful anytime you have to display a number of data items from a record all at the same time.
All you have to do is drop the fields on the stage and tie them to the database. Then any time a
change is made to the database your fields automatically get updated. They will always hold
the correct data and the programmer will never have to write the code to fill them!
4. Automatically fill a field or variable with the entire contents of a recordset:
This feature will take a text field or a variable and fill it with all of the data of a field in a
recordset. For instance if you wanted to create a list of every name in the database so that you
could display it in a field you previously had to manually retrieve the data out of each field
and build a large string. With this new feature you just tell Datagrip the field in the recordset
and it quickly retrieves all of the data for you. This greatly enhances performance since you
make one call instead of one for every record. This will prevent the programmer from making
thousands of extra calls that could slow down the application.
5. Capability to turn a field cast member or variable in to a grid:
This great feature will take a list of fields that you specify and build a multicolumn list box.
You just name the fields and give them a size and Datagrip takes care of the rest. It
automatically adjusts the size of the text in the database so that all of the data lines up in nice
columns. Say for instance you had a database that held names and phone numbers. Of course

Datagrip User Manual, Version 2.0 128 August 21, 1998


you want this data to be displayed in a nice format so you create this grid and tell Datagrip to
fill it. Datagrip goes out and gets all of the names and phone numbers and formats them for
you all with 3 lines of code. If you were to use another database Xtra you would have to make
an individual call for each field in each recordset and then handle the spacing for you. For a
1000 record database with 3 fields this generates over 3000 extra calls to the DB. With
Datagrip's new feature you could do it in 4 calls, saving a large amount of time.
6. You no longer have to install runtime files on the user’s computer. You can run
everything solely from the CD:
This is important to note because previously to use Datagrip you had to install some files on
the users hard drive. Now you can run the application solely off of the CDROM without ever
copying a file.
7. Datagrip now supports both Pessimistic and Optimistic locking schemes:
This will allow the developer to design more efficient multi-user applications. For instance
you would probably want to use a different scheme depending on whether users would try and
edit the same data or not.

Datagrip User Manual, Version 2.0 129 August 21, 1998


DATAGRIP SOFTWARE LICENSING AGREEMENT
INM's one-time licensing fee enables you to use DataGrip and any additional programs, samples and tools (collectively the
"Software") royalty-free, but some conditions apply. We invite you to carefully read and agree to the terms and conditions of the
license below before using the software.
DataGrip Xtra - License Agreement
PLEASE READ THIS LICENSE AGREEMENT CAREFULLY BEFORE INSTALLING, COPYING, OR OTHERWISE USING
DATAGRIP. BY USING DATAGRIP, YOU AGREE TO BECOME BOUND BY THE TERMS OF THIS LICENSE AGREEMENT.
IF YOU DO NOT AGREE TO THE TERMS OF THIS LICENSE, DO NOT INSTALL, COPY OR USE THIS SOFTWARE.
The Software is licensed, not sold, to you by Integration New Media, Inc. ("INM") for the purpose of using it for the development of
your own product ("Product") only under the terms of this Agreement. INM and its licensors reserve any rights not expressly granted
to you. You own the media on which the Software is recorded or fixed, but INM and its licensors grant you no right, title or interest in
or to the Software. The Software is owned by INM and its licensors and is protected by International copyright laws and treaties.
1. LICENSE.
INM grants you a non-exclusive, non-transferable, perpetual (unless terminated in accordance with this Agreement), royalty-free,
worldwide license to:
(a) Install one copy of the Software on a single computer. To "install" the Software means that the Software is either loaded or
installed on the permanent memory of a computer (i.e., hard disk). You may only install the Software on another computer if you first
remove the Software from the computer on which it was previously installed.
(b) Make one copy of the Software in machine-readable form solely for backup purposes, provided the backup copy is not installed or
used on any computer. As an express condition of this Agreement, you must reproduce on each copy any copyright notice or other
proprietary notice that is included with the original copy of the Software supplied by INM.
(c) Reproduce and distribute DGRel.X32 (the "End-User Kit") provided that: (i) you distribute the End-User Kit only in conjunction
with and as part of your own Product, and (ii) own a license for the Software that contains the End-User Kit, (iii) agree to indemnify,
hold harmless and defend INM and its licensors from and against any claims or lawsuits, including attorney's fees, that arise or result
from the use or distribution of your Products with the End-User Kit.
(d) Your license is limited to the particular version (collectively "Version") of the Software you have purchased. Therefore, use of a
Version other than the one encompassed by this License Agreement requires a separate license.
(e) Any third party who will use the End-User Kit in an authoring environment must purchase its own license of the Software.
(f) If the Software is licensed as an upgrade or update, then you may only use the Software to replace previously validly licensed
versions of the same software. You agree that the upgrade or update does not constitute the granting of a second license to the
Software (i.e., you may not use the upgrade or update in addition to the software it is replacing, nor may you transfer the software
which is being replaced to a third party).
(g) If the Software is licensed for evaluation, you may only use it for the purpose of evaluating it with the intent of purchasing it. In
any case, if the Software is not purchased within 30 days of the commencement of the evaluation, then the Software shall be
destroyed.
(h) If the Software is licensed for educational purposes and in a purely educational environment, you may only use it (i) to teach how
to use the Software, or (ii) in non-commercial projects developed by schools, colleges or universities as part of an educational
experience. Commercial projects developed by students, instructors or other members of an educational facility, whether for
consideration or not, do not qualify as educational.
(i) If you develop your Product using the Software for another party (the "Publisher") who (i) publishes the Product; or (ii) otherwise
redistributes the Products to end-users under any label other than yours, then the Publisher is also required to be a licensee of the
Software.
(j) All intellectual property rights in and to the assets which may be accessed through the use of the Software are the property of the
respective asset owners and may be protected by applicable copyright or other intellectual property laws and treaties. This Agreement
grants you no rights to use such content.
2. RESTRICTIONS.
(a) The Software contains a design-time Xtra (DGDes.X32) that may not be distributed by you in any way.
(b) You may not sublease, rent, loan or lease the Software.
(c) You may not transfer or assign your rights under this License to another party without INM's prior written consent. Assignment
application forms can be obtained from INM's sales department.
(d) The Software contains trade secrets and, to protect them, YOU MAY NOT MODIFY, ADAPT, TRANSLATE OR CREATE
DERIVATIVE WORKS BASED UPON THE SOFTWARE OR ANY PART THEREOF. YOU MAY NOT TO MODIFY, ADAPT,
TRANSLATE, REVERSE ENGINEER, DECOMPILE, DISASSEMBLE OR OTHERWISE REDUCE THE SOFTWARE TO ANY
HUMAN PERCEIVABLE FORM. YOU MAY NOT ALTER OR CHANGE THE COPYRIGHT NOTICES AS CONTAINED IN
THE SOFTWARE.

Datagrip Software Licensing Agreement 130 August 21, 1998


(f) THE SOFTWARE IS NOT INTENDED FOR USE IN THE OPERATION ENVIRONMENTS IN WHICH THE FAILURE OF
THE SOFTWARE COULD LEAD TO DEATH, PERSONAL INJURY, OR PHYSICAL OR ENVIRONMENTAL DAMAGE.
3. Copyright Notices.
(a) You may not alter or change INM's and its licensors' copyright notices as contained in the Software.
(b) You must include a copyright notice, in direct proximity to your own copyright notice, in substantially the following form:
"Portions of code are Copyright ©2000 used under license by Integration New Media, Inc. http://www.INM.com".
4. Acceptance.
The Software shall be deemed accepted by you upon delivery unless you provide INM, within two (2) weeks therein, with a written
description of any bona fide defects in material or workmanship.
5. Termination.
This Agreement is effective until terminated. This Agreement will terminate immediately without notice from INM or judicial
resolution if you fail to comply with any provision of this Agreement. Upon such termination you must destroy the Software, all
accompanying written materials and all copies thereof, and Sections 7, 8, 9 and 10 will survive any termination.
6. Limited Warranty.
INM warrants for a period of ninety (90) days from your date of purchase (as evidenced by a copy of your receipt) that the media on
which the Software is recorded will be free from defects in materials and workmanship under normal use and the Software will
perform substantially in accordance with the user manual. INM's entire liability and your sole and exclusive remedy for any breach of
the foregoing limited warranty will be, at INM's option, replacement of the disk, refund of the purchase price or repair or replacement
of the Software.
7. Limitation of Remedies and Damages.
In no event will INM or its licensors, directors, officers, employees or affiliates of any of the foregoing be liable to you for any
consequential, incidental, indirect or special damages whatsoever (including, without limitation, loss of expected savings, loss of
confidential information, presence of viruses, damages for loss of profits, business interruption, loss of business information and the
like), whether foreseeable or not, arising out of the use of or inability to use the Software or accompanying materials, regardless of the
basis of the claim and even if INM or an INM representative has been advised of the possibility of such damage. INM's liability to you
for direct damages for any cause whatsoever, and regardless of the form of the action, will be limited, at INM's option to refund of the
purchase price or repair or replacement of the Software.
THIS LIMITATION WILL NOT APPLY IN CASE OF PERSONAL INJURY ONLY WHERE AND TO THE EXTENT THAT
APPLICABLE LAW REQUIRES SUCH LIABILITY. BECAUSE SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION
OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY
NOT APPLY TO YOU.
8. Indemnity.
By using the Software, you agree to indemnify, hold harmless and defend INM and its licensors from and against any claims or
lawsuits, including attorney's fees that arise or result from the use or distribution of your Product with the Software.
9. General Provisions.
This Agreement will be construed under the laws of the Province of Quebec, except for that body of law dealing with conflicts of law.
If any provision of this Agreement shall be held by a court of competent jurisdiction to be contrary to law, that provision will be
enforced to the maximum extent permissible, and the remaining provisions of this Agreement will remain in full force and effect.
10. Language.
The parties acknowledge having requested and being satisfied that this Agreement and its accessories be drawn in English. Les parties
reconnaissent avoir demandé que cette entente et ses documents connexes soient rédigés en anglais et s'en déclarent satisfaits.

Datagrip Software Licensing Agreement 131 August 21, 1998

You might also like