Please feel free to use these tutorials for your own personal use, education, advancement, training, etc. However, I kindly ask that you respect the time and effort I have put into this work by not distributing copies, either in whole or in part, for your personal gain. You may not under any circumstances download, cache or host copies of these tutorials on your own servers. Use of these tutorials for commercial training requires a special arrangement with the author or authors.
This tutorial introduces the Oracle9i Developer Suite Release 2 (August, 2002) that includes Oracle Forms 9.0 and Oracle Reports 9.0. The main objectives are to demonstrate and provide hands-on instructions on creating and modifying data entry and query forms in various configurations, reports and graphics.
Caveats: Please note that Oracle tends to change things like menu items, prompts and other small things between each major (certainly) and often minor release. Depending on the exact release of Oracle9i Developer Suite you have, you may find some small discrepencies between what is shown in this tutorial and what you see on your screen.
If you have a local instance of the Oracle database, please do not use the SYSTEM (DBA) account to practice development. There is a good chance you can corrupt the entire database by mistake. You are much better off making use of the SCOTT/TIGER schema or (even better) creating a separate user (schema) for this tutorial work and for practicing.
One more word of caution. Oracle has designed Oracle9i as a three tier architecture. This means that the database (Oracle9i server) should run on one server, the application Server (oracle9i Application Server or Oracle9iAS Containers for Java (OC4J) server as used here) runs on a second server and the client application (written in Oracle Forms and Reports for example) runs on a third machine. One can get all of these components to run on the same machine, but it requires both a fast processor and a lot of RAM. Here is one example:
| Service/Application | RAM consumed while running |
|---|---|
| Oracel9i Database (minimal instance) | 140 MB |
| Oracle9i Forms Builder | 42 MB |
| Oracle9i Reports Builder | 80 MB |
| Oracle9i Forms Runtime web launcher | 12 MB |
| OC4J Service (Java) | 36 MB |
| Netscape 4.7 running a form | 35 MB |
| Oracle9i SQL*Plus | 8 MB |
| Total | 353 MB |
Therefore, having at least 512 MB of real RAM (not swap space) is a necessity. 1 GB of RAM will yield significantly better performance. If you have less than 512 MB of RAM, you should create a swap file (Virtual memory) of at least 1 GB.
The student should also be familiar with Oracle's SQL*Plus tools and should be comfortable connecting to a database schema, creating tables, inserting and manipulating data (with SQL INSERT, UPDATE and DELETE statements) and with querying table data (with SQL SELECT statements).
This tutorial relies on the existence of a few tables in the student's schema. Use the Oracle SQL*Plus tool to create three tables named EMPLOYEE, DEPARTMENT and DEPENDENT with the following attributes. Note: This schema originally appears in the book: Ramez Elmasri and Shamkant B. Navathe, Fundamentals of Database Systems. Second Edition. Addison-Wesley Pub Co, 1994.
| EMPLOYEE Table | |
| Attribute | Data Type |
|---|---|
| FNAME | VARCHAR(8) |
| MINIT | VARCHAR(2) |
| LNAME | VARCHAR(8) |
| SSN | NUMBER(12) |
| BDATE | DATE |
| ADDRESS | VARCHAR(30) |
| SEX | VARCHAR(1) |
| SALARY | NUMBER(7) |
| SUPERSSN | NUMBER(12) |
| DNO | NUMBER(2) |
| DEPARTMENT Table | |
| Attribute | Data Type |
|---|---|
| DNAME | VARCHAR(15) |
| DNUMBER | NUMBER(2) |
| MGRSSN | NUMBER(12) |
| MGRSTARTDATE | DATE |
| DEPENDENT Table | |
| Attribute | Data Type |
|---|---|
| ESSN | NUMBER(12) |
| DEPENDENT_NAME | VARCHAR(10) |
| SEX | VARCHAR(1) |
| BDATE | DATE |
| RELATIONSHIP | VARCHAR(10) |
The following CREATE TABLE and INSERT statements can be used to create the above tables and insert some baseline data using the Oracle SQL*Plus tool. Note that different versions of Oracle accept either 2 digit or 4 digit year designations in the DATE datatype. It seems the latest versions (Oracle8 and Oracle8i) default to accept 4 digit years. The INSERT statements below should be formatted accordingly.
|
|
Make certain you issue a COMMIT; after inserting these records otherwise your forms and reports will not see the uncommitted data. Existing out of SQL*Plus will also issue a COMMIT for you automatically.
This tutorial covers the Developer Forms and Reports components.
In the following section, the procedures to run Oracle Forms under MS Windows (98/NT/2000/XP) will be given.
A typical installation of Oracle9i Developer Suite (9iDS) creates several folders under the Start Programs menu. The two main folders are both named after the Oracle Home you chose to install 9iDS under. A brief guide to installing 9iDS can be found here: http://cisnet.baruch.cuny.edu/holowczak/oracle/install/9ids/
Pay particular attention to the post-installation steps regarding how the Oracle9iAS Containers for Java (OC4J) service runs and on how to install the JInit plugin for your web browser.
The main 9iDS programs represented in this tutorial are found under
the Oracle9i Developer Suite home and include
the following items:
To run the 9iDS Forms Builder under Windows , click on the Start -> Programs -> Oracle9i Developer Suite - Home -> Forms Developer -> Form Builder menu item.
To run the 9iDS Reports Builder under Windows , click on the Start -> Programs -> Oracle9i Developer Suite - Home -> Reports Developer -> Reports Builder menu item.
For older versions of Oracle Developer the start menu would might have items such as: Developer 2000 R2.1, Developer 2000 R2.0, Devloper 6i and so on.
For Oracle9iDS installs in UNIX or Linux, use the following scripts:
| Forms Builder | f90desm.sh |
| Reports Builder | rwbuilder.sh |
Note: In your organization, 9iDS may be installed or configured slightly differently. In particular, the programs may be grouped under different menus. Please contact your DBA or systems administrator, or refer to any local documentation to learn how to run the 9iDS tools.
This screen is called the Object Navigator and displays all of the form elements, data blocks, menu items, user defined code libraries, built in procedures and functions, and database objects (tables, views). The display is in the form of a collapsible tree. In general, clicking on a + will expand the current item to show its details. Clicking on a - will collapse the current list details.
The menu bar across the top provides access to almost all of the features of Oracle Forms.
By default, a button bar is provided on the left hand side of the Object Navigator window. Each button duplicates some functionality on the menus. For example, clicking on the top icon (an opened folder) is the same as pulling down the File menu and choosing the Open option. To see what a button might do if pressed, place the mouse cursor over the button and a short message will appear describing the button's function.
As with earlier versions of Developer, in Developer 9.0, a form, report or graphic is generally referred to as a Module. When first starting the Forms Builder, a default module is created called: MODULE1
The content of the Object Navigator is broken down into 6 major sections:
As objects are created, they are displayed under the appropriate section. Context sensitive menus can be displayed for each object by clicking on an object with the right mouse button.
Fill in your Oracle Username and Oracle Password (press the tab key to move between the fields).
For the Database field, type in the service name for your Oracle database. For example, if you are using Personal Oracle Lite, the Database: would be ODBC:POLITE. If you have a local database running on the same machine, you may be able to connect directly to it by leaving this field blank. If you are working in a client/server environment where the Oralce server resides on another machine, you will have to configure the Oracle Net8 middleware to establish a connection with that server. You would then supply the Net8 service name in the Database field. Alternatively, contact your system administrator to learn the service name for your Oracle database and provide that information in the Database: field.
Click on the Connect button to complete the connection (Under some versions of UNIX, the button is labeled OK). If the user name or password is mistyped or incorrect, the dialog box will be re-displayed. Be sure to provide your Oracle username and password (not your UNIX host or Local Area Network password).
Each time any of the Developer tools are executed, the first step will be to connect to an Oracle database in this fashion.
By default, every form in Oracle Forms has the capability to query existing data in a table, modify existing data and add new data (records) to the table. A form is built up using one or more data blocks that correspond to tables in the database. Fields within the data block correspond to columns in the database table. A data block is similar to a DataWindow object in PowerBuilder. In the following figure, a typical form is shown.
This form has two data blocks, one for the EMPLOYEE table, and one for the DEPENDENT table. These data blocks are arranged in a Master/Detail setup where a single Employee record (the master) is associated with one or more Dependents records (the details).
By default, forms also gives a button bar and a menu. These can be used to scroll through the records in a block, navigate between blocks, set up and perform queries against the tables, insert, update and delete records, clear the form and exit the form. Finally, at the bottom of each form is a status bar that displays any relevant prompts or error messages and an indication of the records in the current data block.
There are four main types of forms that can be designed.
| Single Block Form. This form contains a single data block corresponding to a single database table. |
| Single block Form with lookup field. This form contains a single data block corresponding to a single database table with the addition of one or more fields that display data from some other tables. Such data is "looked up" when the form runs. |
| Master/Detail Form. This form contains two data blocks that are arranged in a master/detail (one to many) relationship. |
| Master/Detail Form with lookup fields. This form is similar to the Master/Detail but has the additional lookup fields in the master and/or detail blocks. |
There are additional variations such as a Master/Detail/Detail form with 3 blocks and so on. However, the four types illustrated above are the most common ones. In this tutorial, all four types will be demonstrated.
In general, a Data Block on a form corresponds to a table in the database. This is called the Base Table for the data block. For each table displayed on the form, a new data block will be created. For this example, only one data block will be created for the EMPLOYEE table.
A block appears on a Canvas which is contained in a Window. There are many options to control multiple canvas views and multiple windows per form. In these examples, we concentrate on a simple arrangement using a single canvas and a single window.
There are a number of ways to create a data block. One way is to manually define the base table and columns, and their positions on the form. While this is possible, it can be very tedious.
Oracle Forms Builder provides two main wizards (programs that guide the developer in performing common tasks) to create data blocks:
Click on the Next button. The following dialog box will appear:
There are two types of data blocks that can be created. Table/View and Procedures. For this example, choose Table/View and click on the Next button.
The next step is to choose a base table and columns that will belong to the data block. The following dialog box should appear:
To associate a database table with the block, click on the Browse... button to the right of the Table or View field. The following dialog box will pop up.
Make sure the Current User and Tables buttons are selected A list of your tables will appear. If no list of tables appears, make certain you have created the tables and inserted data as directed in the Prerequisites section 2. If you are still logged in to SQL*Plus, make certain you issue a "COMMIT;" statement to commit all of the changes to the schema.
Highlight the name of the database table (EMPLOYEE in this example) and click on the OK button.
The wizard should reappear with the name of the table and a list of available columns displayed. To include a column in the data block, highlight the column name and click on the right arrow. The name of the column should move over to the right hand side.
For this example, select the FNAME, LNAME, SSN, BDATE, SALARY and DNO as in the following figure:
Click on the Next button, a dialog box will appear allowing you to name the data block. In general, it is best to simply use the name of the table as the name of the data block as shown below:
Click the Next button once more and the final dialog box for the Data Block wizard will appear:
In this example, we want to continue on to the Layout wizard in order to specify how the new form will appear. Make sure the Create the block, then call the Layout wizard option is selected and click on the Finish button.
The data block will be created (as can be seen in the Object Navigator in the background). The objects created include the EMPLOYEE data block containing items for each of the columns that were selected in the third step of the wizard.
Once the new data block and items are created, the first dialog box in the Layout wizard will appear:
Click on the Next button and the following dialog box will appear:
The layout for a data block may be placed on any existing canvas. In this case, there are no existing canvases so the only option available is to create a new canvas.
Click on the Next button to display the following dialog box:
In this dialog box, the columns from a given base table on a data block can be added to the layout. Since we are laying out the EMPLOYEE data block, it is highlighted automatically. Move all of the Available Columns over to the Displayed Items side by clicking on the double right arrow and click on the Next button.
In this dialog box, the field labels, field sizes and field heights can be altered. Change the field labels as shown below and click on the Next button:
The following dialog box will appear:
There are two main styles for forms. A Tabular layout arranges the field labels across the top of the form with a number of records below as in a spreadsheet.
A Form layout places the field labels to the left of the fields. Generally only one record is displayed at a time.
For this example, choose a Form layout and click on the Next button.
In the following dialog box, type a title for the frame (around the data block) and check the option to include a scroll bar.
The number of records displayed for a Form layout should be 1. The number of records displayed in a Tabular layout can be more than 1.
Click on the Next button and the final dialog box for the Layout wizard will appear.
Click on the Finish button to create the layout. A new Canvas will be created with the new block and all of the form items added in the layout wizard.
At this point the Layout Editor should appear and the new form with the data block will appear.
In the Layout Editor, fields and labels can be moved around by clicking and dragging. Other text, lines and boxes, etc. can be added using the tool palette on the left side of the window.
Some common operations on the Layout Editor include:
from the tool bar and then clicking on a
label. To stop editing the label, click anywhere
outside of the label text.
from the tool bar and then clicking on a
open area. Type the new text. To change the font,
highlight the text, pull down the Format
menu and click on the Font menu item.
to
highlight a label and then click on the Text Color
palette button
to choose the color.

to zoom in to the
form (e.g., make everything appear larger). Or use
the Zoom Out tool
to
zoom out of the form.
While in the Layout Editor, double clicking on an object will bring up that object's properties. Optionally, clicking on an object with the right mouse button will bring up a small menu which has the Properties menu item on it. The following figure shows the properties for the FNAME item.
Each type of object has a slightly different set of properties. For example, double clicking on the EMPLOYEE data block in the Object Navigator (pull down the Tools menu and choose Object Navigator) will display that data block's properties.
Some properties of interest for a data block include:
Under MS Windows, forms can be saved in a folder (subdirectory) on the local hard disk, on a file server or on a floppy disk. It is desirable to maintain separate subdirectories (folders) for forms associated with different projects. One significant item to be aware of is that Oracle Forms will have difficulty running any form saved in a folder that has spaces or punctuation other than the underscore character in the name. For example, it is common in Windows to just save files in "My Documents". However, since this has a space in the name, the form will not run.
Therefore, if you are developing on a local machine, it is recommended that you at least make a simple directory such as C:\forms or A:\forms if using a floppy disk and save all forms files there.
Under MS Windows, this dialog box looks like:
Note that in your company or organization, forms and other files may have to be saved on floppy disk or in a special directory. The above figure is simply an example.
It is critical that you do not save the file with spaces in the file name. In addition, you should save the files ina local directory where the directory name(s) have no spaces in the them. If you save the file in "My Documents" for example, or on the Windows desktop, you will be unable to run or test the forms.
Fill in a file name in the File Name: field. Be sure it contains no spaces and that it ends with .fmb
Click on the Save button to save the file. For this example, use the file name employee.fmb
To save this form on a floppy disk in the A: drive, use the file name: A:\employee.fmb
To enhance portability of forms across different operating systems, use file names that begin with a letter, contain no spaces or punctuation (except for the underscore character), have all lower case letters and are relatively short.
Reminder: Do not use spaces in the names of the file or the names of any folders (directories).
If you are working on a form and wish to save it under a different file name, follow the same steps as above, only select the Save As menu item in place of the Save menu item. For example, if you have finished working on the Employee form and wish to save off a copy before adding some code or programming some program units, the Save As menu item can be used to save off a copy before proceeding.
To compile a form, first make sure the form is saved. Pull down the Program menu and select the Compile Module menu item.
If a form has errors (e.g., in the PL/SQL code, or if the database schema changes) they will be displayed in a window as they are encountered. A record of the compilation process, including error messages, is kept in a file with a .err extension. For example, if the form is named employee then the record of the compilation will be stored in employee.err
Alternatively, Oracle Forms defaults to automatically compiling the form each time it is executed (run) from the forms Builder as will be demonstrated in the next step. For more details on the default behavior, pull down the Tools menu and check the Preferences menu item.
As discussed in the introduction section, Oraclce9i Forms are intended to urn in a three tier architecture. The database acts as the back-end tier. The Oracle9iAS Containers for Java (OC4J) service acts as the middle tier and a web browser (Internet Explorer 5.x or above or Netscape Navigator 4.7 or above) takes on the role of the user-interface tier.
Unless this environment has already been established, a local client-side OC4J service may be used in place of the middle tier.
Before running a form, the OC4J service should be started. Use the Start
Menu to navigate to:
Start -> Programs -> Oracle9i Developer Suite - Home -> Forms Developer -> Start IC4J Instance
A Command prompt will open (in Windows 2000) similar to the following:
Note that by default, OC4J runs on port 8888. If this conflicts with another service or if you have firewall software that prevents opening up such ports, you will need to change the configuration of either OC4J, your firewall software or both.
If you receive an error when running OC4J, it may be because another OC4J instance is already running. If you are uncertain, save your work and reboot the PC. Then run a single instance of OC4J.
With OC4J configured and running, and the form designed and saved, it can be executed. To run the form, pull down the Program menu and select the Run Form menu item. This will launch your default web browser which will then connect to OC4J (port 8888) on the local machine. Oracle's JInitiator will load and the form should appear.
Use the various menus and items to query the form, enter new data and save new and changed data. Please read the section below on Query By Example to see how to query data from the underlying tables and populate the fields in the form.
If OC4J service is not running, an error message similar to the following will be displayed:
If you see error FRM-10142, make sure the OC4J Instance is running. Look in the Windows Start Menu folder where you started Forms Builder. There should be a memu item called: Start OC4J Instance. Run that program (a DOS box will appear) and make sure it looks similar to the example above. If the OC4J Instance gives errors, it may be because your computer has a personal firewall (such as that included in Windows XP Service Pack 2). Make certain you configure your personal firewall to allow local connections to port 8888.
If you have previously not installed the latest JInitiator,
your browser will launch with the following message:
Click on the "Get the Plug-in" button and follow the instructions to install it. Note that the jinit.exe file is actually installed with Oracle9i Developer Suite.
Reminder: If you saved your form in a folder that has spaces in the name, or if your file name has spaces, the form will not load in the web browser. In such cases, you may see error: FRM-90928 Positional parameter after key on command line. If this occurs, simply use the "Save As" item on the File menu to save the form under a new name with no spaces. Then try to run the form again.
Technical Notes and Possible Errors:
When a Developer Form is first executed, no records will appear. That is, the blank form will appear with no data in the fields. This is similar to running a word processor where the opening screen is blank. From this blank or empty form, the user can immediately begin to enter new data records by simply typing them in.
However, in many cases, the user would first like to see if there are any records in the database. To do this, the user must query the database using the query capabilities that are built into every Oracle form. This will bring a copy of the records from the database into the form.
When a tool such as SQL*Plus is used, the user must form the SQL query by typing it directly in. In the case of embedded SQL, the SQL statements are programmed into the host language (such as "C" or Java) and automatically executed for the user. In the case of Oracle Forms, complex queries can be formulated and submitted to the database using a technique called Query By Example or QBE. In QBE, the name of the table or tables is fixed as are the names of the columns that will be returned from the tables. The user can supply their own criteria by supplying values for the fields. These values become part of the query that is submitted to the database on behalf of the user.
Querying a form in Oracle Forms is a two step process. Clicking on the Query button or choosing Enter Query from the Query menu places the form in Enter Query mode. In enter query mode, the form is cleared and the user can navigate in the various fields. Example values can be supplied as criteria for the query. For example, a user looking for all employees in the RESEARCH department might type a "5" in the DNO field while in enter query mode.
Clicking on the Query button a second time (or pulling down the Query menu and choosing Execute Query) executes the current query using any supplied data as criteria in a WHERE clause. If no criteria are supplied, then all records in the table will be displayed. Continuing the above example, supplying a "5" for the DNO field while in enter query mode would cause the following SQL query to be submitted to the database:
SELECT fname, lname, ssn, bdate, salary, dno FROM employee WHERE dno = 5;
Most of the commands on the menus and on the button bar can also be activated using special key combinations or function keys. For example, within the Java based forms display pressing the F11 function key places the form in Enter Query mode. Pressing the CTRL+F11 function key executes a query. (Note: Please check the Help menu to see if the keys in your system are the same). To see a list of keys and their functions, pull down the Help menu and choose the Keys option.
Once data has been queried, it is retrieved from the database and stored in a buffer in the associated data block on the form. This means that a local copy of the data now exists in the client's memory. Appropriate locks are placed on the data so that the client maintains a consistent view of the data in the associated tables.
The user can navigate through the data in a block by pressing the up and down arrow keys to scroll between records. To change data in a form, the user can TAB to the field of interest, and type over the existing data.
To enter new data into the form, the user can scroll to the last record and then down once more to move to a blank record. Data can then be typed into the fields and the TAB key can be pressed to move between fields on the form.
To save both changed and new records on a form, pull down the Action menu and choose the Save menu item. Any records that have been changed are collected and submitted to the database as SQL UPDATE statements. Any new records are collected and submitted to the database as INSERT statements. These statements are submitted as a single logical unit of work. Thus if a failure occurs during any of the statements, the entire transaction will be rolled back.
If the user attempts to clear the block or exit the form and there are some changes that have not yet been applied to the database, they will be prompted to commit the changes before exiting or clearing the form. The block is cleared when the Enter Query mode is invoked. A block can also be cleared using the Clear Block and Clear Form menu items.
To exit from a running form, pull down the Action menu and select the Exit menu item. Warning: Do not simply close the web browser as this will leave a Java Applet process running and this will lock your form (.fmx file).
As a review, here are a few basic functions that can be performed by default in any Form:
| Forms function | Notes |
|---|---|
| Querying a form | To see all records in the table, simply
"Execute Query" (via Query menu or by pressing F8 in Windows). To filter the record, "enter query" mode, specify the query parameters in the fields and then "Execute Query". |
| Inserting new records | Scroll to the last record and then scroll once more to
get a blank record. Type in data for each field and then commit
these changes by pulling down the Action menu and choose the
Save menu item. For master/detail forms (discussed below) first either query a master record or insert and save a master record (in the master data block), then navigate to the detail block and insert new records there. |
| Updating existing records | Query the database and scroll to the record of interest.
Change the values in the fields and then save the changes.
For master/detail forms, changes to the key in the master block may be prevented if detail records exist (thus insuring relational integrity). |
| Deleting records | Query the database and scroll to the record of
interest. Pull down the Records menu and choose Delete record.
Then save the changes. For master/detail forms, attempting to delete a master record when detail records exist typically results in an error. In such cases, all of the detail records should be deleted first and then the master record should be able to be deleted. |
| Exiting the Form | Pull down the Action menu and choose the Exit menu item. Existing in this way will release any Java processes that might lock up your forms files. |
For this exercise, create a simple data entry form for the DEPARTMENT table with the following characteristics:
The resulting form should look like the following:
Use the enter query mode and execute query functions to query the department table for a specific department name and/or number.
Oracle Forms implements the master-detail relationship using two data blocks. The first block corresponds to the master table and the second block corresponds to the detail table. There are two major functions in a Master-Detail form:
Note that a Master-Detail form is simply one way of viewing the data in two related tables. Forms do not affect the schema in terms of creating, dropping or enforcing database level referential integrity constraints.
The schema used is the same one suggested in the Prerequisites section at the beginning of this tutorial. Notice that the DNO column in the EMPLOYEE table gets its values from the DNUMBER column in the DEPARTMENT table. In other words, to join the two tables in a query, one might specify a WHERE clause such that: EMPLOYEE.DNO = DEPARTMENT.DNUMBER.
Using the same steps given in the prior section on 6. Creating a Form with a Single Block, create a new block named DEPARTMENT that contains all of the columns in the DEPARTMENT table. Briefly:
After this first step, the deptemp form should look like the following:

The wizard can construct the relationship based on
table level constraints it learns from the database schema.
For example, in the CREATE TABLE and ALTER TABLE statements
given at the start of this tutorial, foreign key constraints
were specified between DEPARTMENT and EMPLOYEE, and between
EMPLOYEE and DEPENDENT. However, such relationships are not
always implemented in table level constraints.
The developer can also specify the relationship manually.
In this case, the relationship will be specified manually.
De-select the Auto-join data blocks option.
Click on the Create Relationship button
to list the available data blocks.
In the next dialog box Relation Type, choose
Based on a join condition and click the OK
button.

When the list of blocks appears, choose the
DEPARTMENT data block.
Arrange the Detail Item (DNO) and Master Item
(DNUMBER) such as that
the join condition becomes:
EMPLOYEE.DNO = DEPARTMENT.DNUMBER


Notice that by scrolling the master block DEPARTMENT to a new department number (using the up and down arrow keys), the employees for that department are automatically queried and displayed.
To navigate between the Master and Detail blocks, use:
To view the properties for the DEPARTMENT_EMPLOYEE relation, open up the DEPARTMENT block and then open the Relations block by clicking on the + symbols. Then click on the DEPARTMENT_EMPLOYEE relation with the right mouse button and select Properties.
There are several interesting properties in the relations property sheet:
These settings are used to "tune" the overall performance of a master-detail form. As mentioned above, in cases where a large number of detail records are associated with each master record, it is a good idea to set coordination-Deferred to Yes to avoid unnecessary transfers of data between the server and client. This will also speed up the display of master records as the user can freely scroll through them without a pause to query and deliver the detail records.
PL/SQL is Oracle's procedural language extensions to SQL. To view the PL/SQL code for a Program Unit, click on the name of the program unit with the right mouse button and then choose PL/SQL Editor from the pop-up menu. The code for the CHECK_PACKAGE_FAILURE procedure is show here:
The CHECK_PACKAGE_FAILURE procedure checks to see if a prior form command or SQL statement was successful or if it failed.
Below is the PL/SQL code for the QUERY_MASTER_DETAILS procedure. The text after the -- (two minus signs) are comments.
|
|
The QUERY_MASTER_DETAILS procedure is executed whenever the user navigates to the detail block in a master detail form. If the Deferred Coordination property is set to false, then the detail block is automatically queried.
Finally, the CLEAR_MASTER_DETAILS procedure is called each time a new master record is retrieved (e.g., when the user scrolls to a different master record) or deleted. In this case, if any of the detail records have been inserted, updated or deleted, the changes must be saved into the database before the detail block can be cleared. If there are any outstanding changes to be saved, the user will be prompted to save those changes before the detail bock is cleared.
For this exercise, create a Master/Detail form using the EMPLOYEE and DEPENDENT tables. Employee will be the Master block and Dependents will be the Detail block. The join condition between the two tables is where the SSN column of EMPLOYEE is equal to the ESSN column of DEPENDENT.
The following is an outline of the steps:
The completed form should look like the following:
Query the master block and practice navigating between the two blocks using the CTRL-PageDown and CTRL-PageUp keys.
While in the Employee block, scroll to the Employee named JENNIFER WALLACE, navigate to the Dependents block and add a new record for a SON named ANDREW born on 20-OCT-1962. Navigate back to the Employee block and attempt to scroll to another employee record. A prompt should be displayed to save the new Dependent record.
While in the Master block for Employees, scroll to an employee who has some dependents. Try to delete the Employee record and see if an error message appears.
Finally, alter the EMPLOYEE_DEPENDENT relation properties and set the Coordination-Deferred to Yes and then run the form. Notice now that the detail records will not be displayed automatically. Navigate to the Dependents block and hit the Execute query button (or pull down the Query menu and choose Execute). Notice that only those Dependent records matching the Employee are displayed.
It is cumbersome for a user to have to remember various codes and numbers while entering data into a data entry form. For example, in the Employee form, it might be difficult to have all of the department numbers memorized when inserting new employee data.
One solution to this problem is to make a list of appropriate values available when the user navigates to Department Number field (DNO). In Oracle Forms, these are called List of Values (LOVs). The next section will illustrate creating LOVs for fields. These examples are based on the single block Employee form created at the beginning of this tutorial.
To prepare for this part of the tutorial, close any forms you currently have open by pulling down the File menu and selecting the Close menu item.
Once all of the forms are closed, pull down the File menu and choose the Open menu item to open up the employee.fmb form that was created previously.
A List of Values is based on a Record Group. In Oracle Forms, a record group is a query that returns some collection of records. Record groups can be used to populate blocks or LOVs and they can be used in procedures. When the user navigates to an item with an LOV attached to it, the LOV key (F9 in MS Windows) can be pressed to call up the LOV. At that time, the query associated with the record group is executed and the results are displayed in a pop up window. Once the user makes a selection from the list, the value or values are returned to the form and placed in the appropriate fields.
In the example below, a record group and LOV for the DNO (department number) field in the Employee table will be created.
To create an LOV, click on the LOVs node in the Object Navigator. Then pull down the Edit menu and choose the Create menu item. A dialog box will appear asking if you would like to create the LOV manually or if you would like to use the LOV Wizard.
Choose "Use the LOV Wizard" and click the OK button. The first step of the LOV Wizard will appear as below:
The default is set to create a new Record Group based on a query. Make sure this selection is highlighted and then click the Next button.
In most cases, you will not have a record group created previously. However, one can be created on the fly at this point by specifying a query. In this example, enter the LOV query as follows: SELECT dnumber FROM department
Then click on the Next button.
The next step is to specify which columns in the record group will be returned to for use by the LOV. In this example, we only return DNUMBER so select that column as shown below and click Next.
The next step is to specify the display properties of the LOV columns and also to map the LOV item to the field on the form.
To map the LOV column to a field, click on the DNUMBER entry and then click on the "Look up return Item" button. Highlight the EMPLOYEE.DNO field and click on the OK button.
Note that if your LOV contains more than one item, at this time you would also map them as well (this is not the case with this example, but in the next example we will need to map two LOV columns). Click on the Next button.
Specify a title for LOV window (e.g., "List of Department Numbers"). At this point you may also specify the size and positioning of the LOV. For this example, leave them as the defaults and click the Next button.
The advanced properties relate to how the records should be fetched for the LOV. If there are many hundreds or thousands of possible records returned by the LOV, you may consider changing these options. Otherwise, for this example, simply click Next.
In this final step, the LOV is returning some columns and they were assigned to fields on the form in a previous step. At this point, we need to associate the LOV with a particular item on the form. For example, by assigning the LOV to the EMPLOYEE.DNO field, the user will be able to call up the LOV only when the cursor is positioned in the EMPLOYEE.DNO field. Choose EMPLOYEE.DNO and click the Next button.
Finally, click Finish to create the Record Group and the LOV.
In the figure below, the LOV has been created. A default name of LOV6 was given to both the LOV and to its associated record group. Depending on what other parts of this tutorial you have completed, the default name may be slightly different.
Save, Compile and Run the form. When entering new data, navigate to the DNO (Department number) field. Notice at the bottom of the form, a message appears: List of Values indicating a list of values is available for this field.
Under UNIX and under the Java based applet, the key to display the list of values is Control-l (hold down the control key (Ctrl) and press the letter L). To see the appropriate keys to press, pull down the Help menu and choose the Keys item.
Below is an example of the list of values for the DNO item on the Employee form.
It would be more helpful to include the name of the department both in the pop-up list of values and on the form. However, the department name is not part of the EMPLOYEE table or data block. Thus we need a way to display this information on the EMPLOYEE data block in a non base table field.
Adding this item and making it functional will take several steps:
and create a new field on the EMPLOYEE block by clicking
and dragging the mouse next to the DNO item.
Enabled: Yes
Keyboard Navigable: No
Database Item: No
Query Only: No
Primary Key: No
Insert Allowed: No
Query Allowed: No
Update Allowed: No
At this point, the new item DEPTNAME has been added to the EMPLOYEE data block as a non-base table field.
Save the form at this point by pulling down the File menu and choosing the Save option.
Save, compile/build and run the form to test the functionality. Notice that when the EMPLOYEE block is queried, the associated department name now appears in the new DEPTNAME field. Each time the DNO field is changed, the POST-CHANGE trigger will fire and will fetch the appropriate DNAME column from the DEPARTMENT table and place it in the :DEPTNAME field on the form.
If you completed the previous section on creating the simple LOV, use the Object Navigator to delete this LOV before proceeding with this section.
SELECT DEPARTMENT.DNUMBER, DEPARTMENT.DNAME FROM DEPARTMENTThen click on the Next button.
Include both the DNUMBER and DNAME columns from the Record Group
in the LOV.
Map the DNUMBER LOV column to the :EMPLOYEE.DNO text item and
map the DNAME LOV column to the :EMPLOYEE.DEPTNAME text item (created
in the previous section).
SELECT ssn, lname FROM employeeMap the employee.ssn column to the :DEPARTMENT.MGRSSN field.
SELECT lname INTO :DEPARTMENT.MGR_LAST_NAME FROM employee WHERE employee.ssn = :DEPARTMENT.MGRSSN;This will automatically populate the non base table field MGR_LAST_NAME on the form when the form is queried.
The form should look like the following:
Procedures written in PL/SQL may also be stored within the Oracle Database itself as an object in the schema. Such Stored Program Units (also called Stored Procedures) are ideal for situations where highly standardized business rules or applications logic must be implemented across many forms or applications. In addition, procedures that require several queries be made to the database may be best implemented in the database as this reduces the network traffic and can significantly improve performance. A user may create stored procedures with the Oracle SQL*Plus command line tool.
Oracle Forms can make calls to both internal Program Units as well as to Stored Program Units. This flexibility allows application designers extensive control over the execution of applications and facilitates performance tuning.
In the following sections, examples of Oracle Forms Program Units and Stored Program Units will be given.
Call this field OTHER_MEMBERS. Be sure it is a non-database field and that a user will not be able to navigate there, insert, update or delete data in the field. Go to the Properties and check each of them:
Enabled: True
Navigable: No
Database Item: No
Query Only: No
Primary Key: No
Insert Allowed: No
Query Allowed: No
Update Allowed: No
Add a label to this field by switching to the Layout Editor, choosing the text tool and clicking next to the OTHER_MEMBERS field.
To create this procedure, switch to the Object Navigator and scroll down to the Program Units branch. Pull down the Edit menu and choose the Create menu item. A dialog box will appear asking you to name the new procedure. Type in the name OTHER_DEPARTMENT_MEMBERS and click on the OK button.
At this point, the PL/SQL editor will appear. Type in the following procedure body. An explanation of each part of the procedure is given afterwards:
|
|
The procedure is written in three main sections. Any lines starting with -- are comments and are ignored by Oracle forms.
The heading for the procedure definition indicates that one parameter, IN_EMPLOYEE_SSN, is a NUMBER data type and the procedure should expect a value to be passed in. The other parameter, OUT_COUNT_OTHER_MEMBERS, is also a NUMBER data type and a value will be passed back to the calling program through it.
To finish off the procedure header, the TEMP_COUNT variable is declared for use within this procedure only.
The BEGIN statement starts the body of the procedure. TEMP_COUNT is initialized to 0 and then a query is performed on the database to find the total number of employees in the same department as the employee whose SSN was supplied to the procedure.
The result in TEMP_COUNT is checked to see if it is a NULL value. If TEMP_COUNT is not NULL and it is not 0, then OUT_COUNT_OTHER_MEMBERS is set to equal TEMP_COUNT-1. Otherwise OUT_COUNT_OTHER_MEMBERS is set to 0.
The last END statement ends the body of the procedure.
Be sure to check to see that the procedure compiles by clicking on the Compile button. Any errors in the procedure will be highlighted. Some common problems include forgetting to use := in an assignment statement (like the Pascal language) and leaving off the END IF to finish up IF ... THEN statements.
When done, click on the Close button to close the PL/SQL editor.
Create a trigger to call the OTHER_DEPARTMENT_MEMBERS procedure. In the Object Navigator, open up the EMPLOYEE block and the SSN item. Highlight the Trigger branch for the SSN item, pull down the Edit menu and choose the Create menu item.
A pop up list of trigger names will appear. Choose POST-CHANGE and click on the OK button to open the PL/SQL editor for this new trigger. Type in the following code for the POST-CHANGE trigger on the SSN item:
|
|
Again, click on the Compile button to be sure the trigger compiles correctly and then click on the Close button to return to the Object Navigator.
To save you work, use the Save As menu item on the File menu and save this form under the name: emp_memb.fmb
Save, Compile/Build, and Run the form to check its functionality. Note that when scrolling to a new employee's record, the OTHER_MEMBERS field is automatically populated with values indicating the number of other employees in the same department.
In this exchange, the highest costs are incurred by the network traffic required to go back and forth between client and server (steps 2 and 3). The lowest costs are incurred by the local calls between trigger and procedure and the local processing (steps 1, 4 and 5).
In this example, the SQL Query in steps 2 and 3 does not return a significant amount of data. However, there are situations where, if a large amount of data were to be returned for each query, such queries would severely impact performance.
One solution to this problem is to move the queries and as much processing as possible "closer" to the data in the database. Thus our example for this section will be to implement the OTHER_DEPARTMENT_MEMBERS procedure in the Oracle database. To achieve this, we will need to use Oracle SQL*Plus (a command-line tool) to create a stored procedure.
Log in to SQL*Plus and enter the following CREATE PROCEDURE statement. Alternatively, save this statement in a text file and execute it using the START command in SQL*Plus.
|
|
After typing in this statement, be sure to RUN the command in the SQL*Plus buffer by typing RUN or by typing the forward slash /
Note: While creating a stored procedure, you may receive an error similar to the following:
ORA-01031: insufficient privilegesThis indicates the DBA has not granted you the authorization to create stored procedures. Please contact your DBA to obtain this authorization.
To see if the procedure compiled correctly, look in view USER_ERRORS as follows:
Another alternative is to use the SQL*Plus command called show errors. After submitting a trigger or a stored procedure, any errors found during compilation can be displayed using the show errors command.
In some versions of SQL*Plus, the show errors command will not work due to a lack of buffer memory on the client computer. An error message may appear as in the following example:
|
|
If the buffer overflow message appears, set the ARRAYSIZE variable to a lower number such as 2 with the following command:
Then use the show errors command as described:
|
|
To see what stored procedures you have created, query the USER_SOURCE view in the data dictionary.
The only major difference between the stored procedure created in the database schema through SQL*Plus and the procedure created in Oracle Forms is the way the header is formatted. Creating a stored procedure uses the following syntax:
CREATE PROCEDURE OTHER_DEPARTMENT_MEMBERS (IN_EMPLOYEE_SSN IN NUMBER, OUT_COUNT_OTHER_MEMBERS OUT NUMBER) ASContrast this with the procedure done in Oracle Forms:
PROCEDURE OTHER_DEPARTMENT_MEMBERS (IN_EMPLOYEE_SSN IN NUMBER, OUT_COUNT_OTHER_MEMBERS OUT NUMBER) IS
Once the OTHER_DEPARTMENT_MEMBERS procedure (Program Unit) has been created in SQL*Plus, it is stored as an object in your schema and will remain there until a DROP PROCEDURE OTHER_DEPARTMENT_MEMBERS statement is issued. Any Oracle Form, Report or other procedure can make calls to OTHER_DEPARTMENT_MEMBERS as if it were a local procedure.
To see the stored procedure in action, open the emp_memb.fmb form and remove (delete) the Program Unit (procedure) OTHER_DEPARTMENT_MEMBERS from it. Save the form, compile, generate and run it.
The POST-CHANGE trigger on :EMPLOYEE.SSN will automatically make a call to the stored procedure version of OTHER_DEPARTMENT_MEMBERS located in the schema.
To view the available Stored Program Units from within Oracle Forms, switch to the Object Navigator and open up the Database Objects tree. From there, a list of schemas (users) will appear. Scroll down to your username and open it up. Then open up the Stored Program Units tree. A list of your stored procedure should then appear.
There are countless ways in which stored procedures and triggers can be used to enforce business rules and to process data in an application. In this section, a few of the most commonly used triggers and procedures are described.
Many of the keys used in tables are based on a number sequence. For example, in our DEPARTMENT table, the DNUMBER is an integer that should increase for each new department. To automatically generate a new DNUMBER, create a query to capture the largest current DNUMBER value and add 1 to it. Then assign this new value to the DNUMBER item in the DEPARTMENT data block. A trigger to do this could be created at the block level and should execute before any new record is inserted into the database. A PRE-INSERT trigger on the DEPARTMENT data block would be used for this example:
One problem with the above method is that many users working on the same form to insert new records will run into concurrency problems. For each new record to be inserted, a full table scan must be done to find the largest identifier.
One solution to this problem is to use an Oracle Sequence. An Oracle Sequence is a schema object that keeps track of a simple integer and automatically increments this counter when it is accessed.
For example, in our DEPARTMENT table, the DNUMBER is an integer that should increase for each new department. To automatically generate a new DNUMBER, create an Oracle Sequence using the SQL*Plus tool:
The next step is to assign the next value of the sequence to the DNUMBER item in the DEPARTMENT data block. A trigger to do this would be created at the block level and should execute before any new record is inserted into the database. A PRE-INSERT trigger on the DEPARTMENT data block would be used for this example:
A PRE-INSERT trigger executes just before the INSERT statement for a new record is sent to the database.
Oracle Sequences are not applicable for master-detail forms such as purchase orders where an item number needs to be assigned in the detail table. For example, purchase order items are typically numbered: 1, 2, 3.... The next PO will also number the items 1, 2, 3, .... An Oracle Sequence is designed to deliver unique identifiers for primary keys and should not be used for such item numbers.
In any database system, it is always desirable to constrain the values certain columns can take on. It is possible to add constraints to the database tables themselves in order to enforce constraints, however, the enforcement only takes place when a transaction reaches the database. In addition, many constraints on the data that involve values of data from other tables may not be easily implemented as table constraints.
Many types of constraints on data can be checked in the client using triggers. For example, in an EMPLOYEE data entry form, we may want to enforce a constraint that no employee can act as their own supervisor. Thus for any record, SSN may not equal SUPERSSN. To implement such a constraint, add the SUPERSSN item to the EMPLOYEE form (or simply create a new form from scratch using the wizard that includes both SSN and SUPERSSN columns) and then create a WHEN-VALIDATE-ITEM trigger on the SUPERSSN item in the EMPLOYEE data block:
In the previous example, the MESSAGE procedure is used to display the error along the status bar at the bottom of the Forms window. A better approach may be to force the user's attention to the problem. This can be accomplished by creating a pop-up dialog box that forces the user to read the message and click an OK button (or some other button). In Oracle Forms, this is called an Alert.
To set up an Alert:
In general, Alerts may provide several different buttons for the user to click on. For example, to confirm exiting a form, a POST-FORM trigger might invoke an "Are you sure you want to Exit" Alert with "Yes" and "No" buttons. Or, to confirm deleting a record, a PRE-COMMIT trigger might invoke an "Are you sure you want ot delete this Employee?" Alert with "Yes" and "No" buttons. Based on the return_alert value, either a commit or rollback might be issued.
To automate this process, create a WHEN-NEW-FORM-INSTANCE
trigger that navigates to the master data block and then issues
the EXECUTE_QUERY built-in procedure. For example, assuming the master
block is named "EMPLOYEE", the following code will cause a
query to be executed immediately after the form opens:
9.3.5 Automatic Forms Query
As discussed earlier in the tutorial, by default, when a form runs,
the underlying table data is not automatically queried and displayed.
It is up to the user to execute a query, for example, by pulling down the
query menu and choosing Execute.
BEGIN
GO_BLOCK('EMPLOYEE');
EXECUTE_QUERY;
END;
There are many cases where default values can be suggested for certain data items based upon values already supplied in other data items. The method here is to use a POST-ITEM or WHEN-VALIDATE-ITEM trigger to populate another field, only if the other field is currently blank. For example, to populate the SUPERSSN data item of the EMPLOYEE block based upon the MGRSSN of the employee's department, the following WHEN-VALIDATE-ITEM trigger code might be used on the DNO data item:
Command buttons can be added on a form to carry out functions such as exiting a form, committing/saving changed records and so on. The basic command button object contains properties for the button Label (the text provided on the button itself). Additional properties include visual attributes including the ability to display a bitmap image in place of the button's normal appearance.
Once a button has been physically placed on a form, functionality is added but writing a WHEN-BUTTON-PRESSED trigger. As one might expect, this trigger executes when the user clicks on the button. So, for example, to create a button to exit the form when the user clicks on it the WHEN-BUTTON-PRESSED trigger might look like:
For this example, we wil make use of two forms: A basic EMPLOYEE form with all fields and the EMPLOYEE/DEPENDENT master/detail form (created in a previous exercise - the file name should have been empdepn.fmb). The idea is to place to button on the EMPLOYEE form that when pressed, will call the EMPLOYEE/DEPENDENT form and automatically query the dependents for the employee being viewed on the EMPLOYEE form. The main steps are:
Run_Product(FORMS, 'd:\myfiles\empdepn', SYNCHRONOUS, RUNTIME,
FILESYSTEM, pl_id, NULL);
If you receive error FRM-40010 Cannot read form empdepn.fmx
then you will need to include the full directory path to where
your forms are located.
The above examples are just a few of the great many things one can do with Oracle Forms. The on-line help that ships with Forms contains many example forms and example pieces of code (see the Forms PL/SQL Reference) that go far beyond the simple techniques demonstrated above.
DECLARE
reportid REPORT_OBJECT;
view_report VARCHAR2(100);
report_result VARCHAR(30);
rep_status VARCHAR2(20);
-- Declare pl_id as the identifier for the parameter list
pl_id ParamList;
BEGIN
-- NOTE: In order to launch a report from Forms, you must have the Reports server
-- running on your local machine.
-- At a DOS prompt type: rwserver -install localhost autostart=yes
-- This will install a reports server for your machine (localhost) and start it up.
-- Next, create a Reports Object in Forms Object Navigator.
-- This is named "MYREPORT" for this example. This reports
-- object will have properties including the path to the actual
-- report file (.rdf file) you want to run.
pl_id := Get_Parameter_List('tmpdata');
IF NOT Id_Null(pl_id) THEN
Destroy_Parameter_List( pl_id );
END IF;
-- Create a fresh parameter list
pl_id := Create_Parameter_List('tmpdata');
-- Add a new parameter to this list called MYDNUMBER
-- Note that in the report being called (empreport.rdf) the
-- report query should use :MYDNUMBER in the WHERE clause
-- as in SELECT * FROM employee WHERE dno = :MYDNUMBER
-- Assign this parameter the current value of the :DNUMBER field
Add_Parameter(pl_id, 'MYDNUMBER', TEXT_PARAMETER, :DNUMBER);
-- Now execute the report object. This object must be created
-- in the Object Navigator under REPORTS (just below "Record Groups")
report_result := RUN_REPORT_OBJECT('MYREPORT', pl_id);
-- Check on the report status and loop until it is done
rep_status := REPORT_OBJECT_STATUS(report_result);
WHILE rep_status in ('RUNNING','OPENING_REPORT','ENQUEUED') LOOP
rep_status := report_object_status(report_result);
END LOOP;
-- When the report is done, open up a new window and display it
IF rep_status = 'FINISHED' THEN
WEB.SHOW_DOCUMENT('http://localhost:8888/reports/rwservlet/getjobid'|| substr(report_result,instr(report_result,'_',-1)+1)||'?'||'server=localhost','_blank');
END IF;
END;
A typical installation of Developer creates several folders under the Start Programs menu.
To run Oracle9i Reports Builder under Windows, click on the Start -> Programs -> Oracle9i Developer Suite - Home -> Reports Developer -> Reports Builder menu item.
Under UNIX, run the rwbuilder.sh script.
An initial screen will appear:
Click on the Cancel button to proceed directly to the Object Navigator.
The main sections of the Object Navigator are:
As with Oracle Forms, the first step in using Oracle Reports is to Connect to an Oracle server. This is accomplished by pulling down the File menu and selecting the Connect menu item.
Fill in your Oracle Username and Oracle Password (press the tab key to move between the fields).
For the Database field, type in the service name for your Oracle database. For example, if you are using Personal Oracle Lite, the Database: would be ODBC:POLITE. Contact your system administrator to learn the service name for your Oracle database and provide that information in the Database: field.
Click on the Connect button to complete the connection (Under some versions of UNIX, the button is labeled OK). If the user name or password is mistyped or incorrect, the dialog box will be re-displayed. Be sure to provide your Oracle username and password (not your UNIX host password).
Oracle Reports version 3.0, 6i and 9iDS all support a wizard that takes the developer through all of these steps. This approach will be demonstrated next.
The first screen for the reports wizard will appear as below:
The first option is to decide the type of report to be created. Oracle Reports can be created to display on a web page (inside of a web browser), or by using the more traditional Oracle Reports runtime. The latter is called the "Paper Layout". For this example, both types of layouts will be created. Make certain the "Create both Web and Paper Layout" option is selected and click the Next button.
The next step in the wizard prompts for the style of the report and for the Report Title.
The eight layout choices include:
For this report, type in "Employee Report" as the title, choose the Tabular Layout and click on the Next button.
The next step is to specify the Type of query the report will be based on.
The five choices are:
For this example, choose the "SQL Query" and click the next button.
The next step is to specify the query that will form the basis of the report. In this case, type the following query in the SQL Query Statement: text box:
SELECT FNAME, LNAME, SSN, SALARY, DNO FROM EMPLOYEE ;
For future reference, one could also invoke the graphical Query Builder at this step, or choose to import a SQL query from a text file.
Once the SQL SELECT statement is entered, click on the Next button to move to the next step. Note: If you did not Connect to the database, you will be prompted for the Username, Password and Database.
In the next wizard dialog box, specify which columns from the SQL Query will be displayed in the report output. To specify all columns, click on the double right arrow to bring all of the Available Fields to the Displayed Fields side.
Click on the Next button to move to the next dialog box.
In the next step, aggregate functions can be applied to the fields on the report. For this example, we will display the average salary as well as a count of employees. Highlight the SALARY field and click on the Average button. Then highlight the SSN field and click on the Count button.
The next dialog box allows you to change the field labels and display widths for various fields in the report.
As a final step, a design template can be applied to the report. Design templates include specifications for fonts, colors and layout of the report. For this example, choose the "Blue" predefined template and then click on the Finish button.
After a short delay, the Reports Live Previewer will appear showing the report.
It is possible to make changes to the layout of the report (fonts, colors, positions of headings and titles, etc.) by using the tool palettes and tool bars. When you have finished touching up the report, close the Reports Live Previewer and the Ob