- About using DataWindow objects
- Putting a DataWindow object into a control
- Accessing the database
- Accessing a Web service data source (Obsolete)
- Importing data from an external source
- Manipulating data in a DataWindow control
- Accessing the properties of a DataWindow object
- Handling DataWindow errors
- Updating the database
- Creating reports
- Using nested reports
- Using crosstabs
- Generating HTML
About this chapter
This chapter describes how to use DataWindow objects in an application.
Before you begin
This chapter assumes that you know how to build DataWindow objects in the DataWindow painter, as described in the section called “Defining DataWindow Objects” in Users Guide.
Building DataWindow objects
Before you can use a DataWindow object in an application, you need to build it. PowerBuilder has separate painters for database management, DataWindow definition, and library management.
You define and edit a DataWindow object in the DataWindow painter. You specify its data source and presentation style, then enhance the object by specifying display formats, edit styles, and more.
The DataWindow painter is also where you make Powersoft report (PSR) files, which you might also want to use in applications. A PSR file contains a report definition -- essentially a nonupdatable DataWindow object -- as well as the data contained in that report when the PSR file was created.
Report objects only in InfoMaker
Older versions of PowerBuilder had a Report painter as well as a DataWindow painter. A report object could retrieve but not update data; it was essentially a nonupdatable DataWindow object. The Report painter is now available only in InfoMaker.
Managing DataWindow objects
Several painters let you manage and package your DataWindow objects for use in applications.
In particular, you can maintain DataWindow objects in one or more libraries (PBL files). When you are ready to use your DataWindow objects in applications, you can package them in more compact runtime libraries (PBD files).
For further details on how to build and organize DataWindow objects, see the section called “Defining DataWindow Objects” in Users Guide.
Using DataWindow objects
After you build a DataWindow object (or PSR file) in the DataWindow painter, you can use it to display and process information from the appropriate data source. The sections that follow explore the details of how to do this.
The DataWindow control is a container for DataWindow objects in an application. It provides properties, methods, and events for manipulating the data and appearance of the DataWindow object. The DataWindow control is part of the user interface of your application.
You also use DataWindow objects in the nonvisual DataStore and in child DataWindows, such as drop-down DataWindows and composite presentation styles. For more information about DataStores, see Using DataWindow Objects. For more information about drop-down DataWindows and composite DataWindows, see Working with DataWindows in Users Guide.
To use the DataWindow object in an application, you add a DataWindow control to a window or form, then associate that control with the DataWindow object, as illustrated in the following figure:
Figure 2-1: Putting a DataWindow object into a DataWindow control
This section has information about:
-
Procedures for inserting a control and assigning a DataWindow object to the control
There are two names to be aware of when you are working with a DataWindow:
-
The name of the DataWindow control
-
The name of the DataWindow object associated with the control
The DataWindow control name
When you place a DataWindow control in a window or form, it gets a default name. You should change the name to be something meaningful for your application.
In PowerBuilder, the name of the control has traditionally had a prefix of dw_. This is a useful convention to observe in any development environment. For example, if the DataWindow control lists customers, you might want to name it dw_customer.
Using the name
In code, always refer to a DataWindow by the name of the control (such as dw_customer). Do not refer to the DataWindow object that is in the control.
The DataWindow object name
To avoid confusion, you should use different prefixes for DataWindow objects and DataWindow controls. The prefix d_ is commonly used for DataWindow objects. For example, if the name of the DataWindow control is dw_customer, you might want to name the corresponding DataWindow object d_customer.
To place a DataWindow control in a window:
-
Open the window that will contain the DataWindow control.
-
Select Insert>Control>DataWindow from the menu bar.
-
Click where you want the control to display.
PowerBuilder places an empty DataWindow control in the window:
-
(Optional) Resize the DataWindow control by selecting it and dragging one of the handles.
Specifying a DataWindow object
After placing the DataWindow control, you associate a DataWindow object with the control.
To associate a DataWindow object with the control:
-
In the DataWindow Properties view, click the Browse button for the DataObject property.
-
Select the DataWindow object that you want to place in the control and click OK.
The name of the DataWindow object displays in the DataObject box in the DataWindow Properties view.
-
(Optional) Change the properties of the DataWindow control as needed.
Allowing users to move DataWindow controls
If you want users to be able to move a DataWindow control during execution, give it a title and select the Title Bar check box. Then users can move the control by dragging the title bar.
You might want all the DataWindow controls in your application to have similar appearance and behavior. For example, you might want all of them to do the same error handling.
To be able to define these behaviors once and reuse them in each window, you should create a standard user object based on the DataWindow control: define the user object's properties and write scripts that perform the generic processing you want, such as error handling. Then place the user object (instead of a new DataWindow control) in the window. The DataWindow user object has all the desired functionality predefined. You do not need to respecify it.
For more information about creating and using user objects, see the section called “Working with User Objects” in Users Guide.
Once you have associated a DataWindow object with a DataWindow control in a window, you can go directly to the DataWindow painter to edit the associated DataWindow object.
Changing the DataWindow object
In PowerBuilder, set the DataObject property to one of the DataWindow objects built into the application.
Setting the transaction object when you change the DataWindow object
When you change the DataWindow object during execution, you might need to call setTrans or setTransObject again.
For more information, see Setting the transaction object for the DataWindow control.
Dynamically creating a DataWindow object
You can also create a new DataWindow object during execution and associate it with a control.
For more information, see Dynamically Changing DataWindow Objects.
When you associate a DataWindow object with a control in the window, you are setting the initial value of the DataWindow control's DataObject property.
During execution, this tells your application to create an instance of the DataWindow object specified in the control's DataObject property and use it in the control.
Setting the DataObject property in code
In addition to specifying the DataWindow object in the Window painter, you can switch the object that displays in the control during execution by changing the value of the DataObject property in code.
For example: to display the DataWindow object d_emp_hist from the library emp.pbl in the DataWindow control dw_emp, you can code:
dw_emp.DataObject = "d_emp_hist"
The DataWindow object d_emp_hist was created in the DataWindow painter and stored in a library on the application search path. The control dw_emp is contained in the window and is saved as part of the window definition.
Preventing redrawing
You can use the SetRedraw method to turn off redrawing in order to avoid flicker and reduce redrawing time when you are making several changes to the properties of an object or control. Dynamically changing the DataWindow object at execution time implicitly turns redrawing on. To turn redrawing off again, call the SetRedraw method every time you change the DataWindow object:
dw_emp.DataObject = "d_emp_hist" dw_emp.SetRedraw(FALSE)
Using PSR files
To put a PSR file into a DataWindow control at execution time, change the control's DataObject property to specify that PSR file name.
Before you can display data in a DataWindow control, you must get the data stored in the data source into that control. The most common way to get the data is to access a database.
An application goes through several steps in accessing a database:
-
Set the appropriate values for the transaction object.
-
Connect to the database.
-
Set the transaction object for the DataWindow control.
-
Retrieve and update data.
-
Disconnect from the database.
This section provides instructions for setting the transaction object for a DataWindow control and for using the DataWindow object to retrieve and update data.
To learn more about setting values for the transaction object, connecting to the database, and disconnecting from the database, see:
-
PowerBuilder
the section called “Using Transaction Objects” in Application Techniques.
There are two ways to handle database connections and transactions for the DataWindow control. You can use:
-
Internal transaction management
-
A separate transaction object
The two methods provide different levels of control over database transactions.
If you are displaying a PSR file in the control
You do not need to use a transaction object or make a database connection if you are displaying a PSR file in the DataWindow control.
If you change the DataWindow object
If you change the DataWindow object associated with a DataWindow control during execution, you might need to call the SetTrans or SetTransObject method again.
PowerBuilder
You always need to call one of the methods to set the transaction object.
What it does
When the DataWindow control uses internal transaction management, it handles connecting, disconnecting, commits, and rollbacks. It automatically performs connects and disconnects as needed; any errors that occur cause an automatic rollback.
Whenever the DataWindow needs to access the database (such as when a Retrieve or Update method is executed), the DataWindow issues an internal CONNECT statement, does the appropriate data access, then issues an internal DISCONNECT.
Whether to use it
When not to use it
Do not use internal transaction management when:
-
Your application requires the best possible performance
Internal transaction management is slow and uses considerable system resources because it must connect and disconnect for every database access.
-
You want control over when a transaction is committed or rolled back
Because internal transaction management must disconnect after a database access, any changes are always committed immediately.
When to use it
If the number of available connections at your site is limited, you might want to use internal transaction management because connections are not held open.
Internal transaction management is appropriate in simple situations when you are doing pure retrievals (such as in reporting) and do not need to hold database locks -- when application control over committing or rolling back transactions is not an issue.
How it works
PowerBuilder
To use internal transaction management, you specify connection values for a transaction object, which could be the automatically instantiated SQLCA. Then you call the SetTrans method, which copies the values from a specified transaction object to the DataWindow control's internal transaction object.
SQLCA.DBMS = ProfileString("myapp.ini", & "database", "DBMS", " ") ... // Set more connection parameters dw_employee.SetTrans(SQLCA) dw_employee.Retrieve( )
Connecting to the database
When you use SetTrans, you do not need to explicitly code a CONNECT or DISCONNECT statement in a script. CONNECT and DISCONNECT statements are automatically issued when needed.
For more information about PowerBuilder transaction objects, see the section called “Using Transaction Objects” in Application Techniques.
How it works
When you use a separate transaction object, you control the duration of the database transaction. Your scripts explicitly connect to and disconnect from the database. If the transaction object's AutoCommit property is set to false, you also program when an update is committed or rolled back.
Typically, a script for data retrieval or update involves these statements:
Connect |
SetTransObject |
Retrieve or Update |
Commit or Rollback |
Disconnect |
In PowerBuilder, you use embedded SQL for connecting and committing.
The transaction object also stores error messages returned from the database in its properties. You can use the error information to determine whether to commit or roll back database changes.
When to use it
When the DataWindow control uses a separate transaction object, you have more control of the database processing and are responsible for managing the database transaction.
There are several reasons to use a separate transaction object:
-
You have several DataWindow controls that connect to the same database and you want to make one database connection for all of them, saving the overhead of multiple connections
-
You want to control transaction processing
-
You require the improved performance provided by keeping database connections open
How it works
PowerBuilder
The SetTransObject method associates a transaction object with the DataWindow control. PowerBuilder has a default transaction object called SQLCA that is automatically instantiated. You can set its connection properties, connect, and assign it to the DataWindow control.
The following statement uses SetTransObject to associate the DataWindow control dw_emp with the default transaction object (SQLCA):
// Set connection parameters in the transaction object SQLCA.DBMS = ... SQLCA.database = ... CONNECT USING SQLCA; dw_emp.SetTransObject(SQLCA) dw_emp.Retrieve( )
Instead of or in addition to using the predefined SQLCA transaction object, you can define your own transaction object in a script. This is necessary if your application needs to connect to more than one database at the same time.
The following statement uses SetTransObject to associate dw_customer with a programmer-created transaction object (trans_customer):
transaction trans_customer trans_customer = CREATE transaction // Set connection parameters in the transaction object trans_customer.DBMS = ... trans_customer.database = ... CONNECT USING trans_customer; dw_customer.SetTransObject(trans_customer) dw_customer.Retrieve( )
For more information
For more information about database transaction processing:
-
PowerBuilder
See the section called “Using Transaction Objects” in Application Techniques
For more information about SetTrans and SetTransObject methods, see the section called “SetTrans” in DataWindow Reference and the section called “SetTransObject” in DataWindow Reference.
You call the following two methods to access a database through a DataWindow control:
Retrieve |
Update |
After you have set the transaction object for your DataWindow control, you can use the Retrieve method to retrieve data from the database into that control:
dw_emp.Retrieve( )
About retrieval arguments
Retrieval arguments qualify the SELECT statement associated with the DataWindow object, reducing the rows retrieved according to some criteria. For example, in the following SELECT statement, Salary is a retrieval argument defined in the DataWindow painter:
SELECT Name, emp.sal FROM Employee WHERE emp.sal > :Salary
When you call the Retrieve method, you supply a value for Salary. In PowerBuilder, the code looks like this:
dw_emp.Retrieve( 50000 )
Special considerations are explained below.
When coding Retrieve with arguments, specify them in the order in which they are defined in the DataWindow object. Your Retrieve method can provide more arguments than a particular DataWindow object expects. Any extra arguments are ignored. This allows you to write a generic Retrieve that works with several different DataWindow objects.
Omitting retrieval arguments
If your DataWindow object takes retrieval arguments but you do not pass them in the Retrieve method, the DataWindow control prompts the user for them when Retrieve is called.
More than 16 arguments
The Retrieve method is limited to 16 arguments in some environments.
PowerBuilder
You can specify any number of retrieval arguments.
After users have made changes to data in a DataWindow control, you can use the Update method to save those changes in the database.
In PowerBuilder, the code looks like this:
dw_emp.Update()
Update sends to the database all inserts, changes, and deletions made in the DataWindow control since the last Update method. When you are using an external transaction object, you can then commit (or roll back) those database updates. In PowerBuilder, you use SQL statements.
For more specifics on how a DataWindow control updates the database (that is, which SQL statements are sent in which situations), see Updating the database.
Examples
The following example shows code that connects, retrieves, updates, commits or rolls back, and disconnects from the database.
Although the example shows all database operations in a single script or function, most applications separate these operations. In a PowerBuilder application, for example, an application could connect to the database in the application Open event, retrieve and update data in one or more window scripts, and disconnect from the database in the application Close event.
PowerBuilder
The following statements retrieve and update data using the transaction object EmpSQL and the DataWindow control dw_emp:
// Connect to the database specified in the // transaction object EmpSQL CONNECT USING EmpSQL; // Set EmpSQL as the transaction object for dw_emp dw_emp.SetTransObject(EmpSQL) // Retrieve data from the database specified in // EmpSQL into dw_emp dw_emp.Retrieve( ) // Make changes to the data... ... // Update the database IF dw_emp.Update( ) > 0 THEN COMMIT USING EmpSQL; ELSE ROLLBACK USING EmpSQL; END IF // Disconnect from the database DISCONNECT USING EmpSQL;
Handling retrieval or update errors
A production application should include error tests after each database operation. For more about checking for errors, see Handling DataWindow errors.
You do not use a transaction object to access data from a Web service data source. However, some Web services support or require a user ID and password, and other session-related properties like firewall settings. The WSConnection object can provide this information for your DataWindow connections.
You use an instance of the WSConnection object to connect to a Web service by calling the SetWSObject method.
For more information about setting properties for a Web service connection, see WSConnection and SetWSObject in the section called “WSConnection object (Obsolete)” in Objects and Controls and the section called “SetWSObject (Obsolete)” in DataWindow Reference.
PowerBuilder
If the data for a DataWindow is not coming from a database or a Web service data source (that is, the data source was defined as External in the DataWindow wizard), you can use these methods to import data into the DataWindow control:
ImportClipboard |
ImportFile |
ImportString |
You can also get data into the DataWindow by using the SetItem method or by using a DataWindow expression.
For more information on the SetItem method and DataWindow expressions, see Manipulating data in a DataWindow control.
To handle user requests to add, modify, and delete data in a DataWindow, you can write code to process that data, but first you need to understand how DataWindow controls manage data.
As users add or change data, the data is first handled as text in an edit control. If the data is accepted, it is then stored as an item in a buffer.
About the DataWindow buffers
A DataWindow uses three buffers to store data:
Buffer |
Contents |
---|---|
Primary |
Data that has not been deleted or filtered out (that is, the rows that are viewable) |
Filter |
Data that was filtered out |
Delete |
Data that was deleted by the user or through code |
About the edit control
As the user moves around the DataWindow control, the DataWindow places an edit control over the current cell (row and column):
About text
The contents of the edit control are called text. Text is data that has not yet been accepted by the DataWindow control. Data entered in the edit control is not in a DataWindow buffer yet; it is simply text in the edit control.
About items
When the user changes the contents of the edit control and presses Enter or leaves the cell (by tabbing, using the mouse, or pressing up arrow or down arrow), the DataWindow processes the data and either accepts or rejects it, depending on whether it meets the requirements specified for the column. If the data is accepted, the text is moved to the current row and column in the DataWindow Primary buffer. The data in the Primary buffer for a particular column is referred to as an item.
Events for changing text and items
When data is changed in the edit control, several events occur.
Event |
Description |
---|---|
EditChanged (not available on client control) |
Occurs for each keystroke the user types in the edit control |
ItemChanged |
Occurs when a cell has been modified and loses focus |
ItemError |
Occurs when new data fails the validation rules for the column |
ItemFocusChanged |
Occurs when the current item in the control changes |
How text is processed in the edit control
When the data in a column in a DataWindow has been changed and the column loses focus (for example, because the user tabs to the next column), the following sequence of events occurs:
-
The DataWindow control converts the text into the correct datatype for the column. For example, if the user is in a numeric column, the DataWindow control converts the string that was entered into a number. If the data cannot be converted, the ItemError event is triggered.
-
If the data converts successfully to the correct type, the DataWindow control applies any validation rule used by the column. If the data fails validation, the ItemError event is triggered.
-
If the data passes validation, then the ItemChanged event is triggered. If you set an action/return code of 1 in the ItemChanged event, the DataWindow control rejects the data and does not allow the focus to change. In this case, the ItemError event is triggered.
-
If the ItemChanged event accepts the data, the ItemFocusChanged event is triggered next and the data is stored as an item in a buffer.
Figure 2-2: How text is processed in edit controls
Action/return codes for events
You can affect the outcome of events by specifying numeric values in the event's program code. For example, step 3 above describes how you can force data to be rejected with a code of 1 in the ItemChanged event.
To specify action/return codes:
-
PowerBuilder
Use a RETURN statement
For information about codes for individual events, see DataWindow Reference.
Using methods
The following methods allow you to access the text in the edit control:
-
GetText - Obtains the text in the edit control
-
SetText - Sets the text in the edit control
In event code
In addition to these methods, the following events provide access to the text in the edit control:
EditChanged |
ItemChanged |
ItemError |
Use the Data parameter, which is passed into the event, to access the text of the edit control. In your code for these events, you can test the text value and perform special processing depending on that value.
For an example, see Coding the ItemChanged event.
When you want to further manipulate the contents of the edit control within your DataWindow control, you can use any of these methods:
CanUndo | Scroll |
Clear | SelectedLength |
Copy | SelectedLine |
Cut | SelectedStart |
LineCount | SelectedText |
Paste | SelectText |
Position | TextLine |
ReplaceText | Undo |
For more information about these methods, see DataWindow Reference.
If data passes conversion and validation, the ItemChanged event is triggered. By default, the ItemChanged event accepts the data value and allows focus to change. You can write code for the ItemChanged event to do some additional processing. For example, you could perform some tests, set a code to reject the data, have the column regain focus, and trigger the ItemError event.
Example
The following sample code for the ItemChanged event for a DataWindow control called dw_Employee sets the return code in dw_Employee to reject data that is less than the employee's age, which is specified in a SingleLineEdit text box control in the window.
This is the PowerBuilder version of the code:
int a, age age = Integer(sle_age.text) a = Integer(data) // Set the return code to 1 in the ItemChanged // event to tell PowerBuilder to reject the data // and not change the focus. IF a < age THEN RETURN 1
The ItemError event is triggered if there is a problem with the data. By default, it rejects the data value and displays a message box. You can write code for the ItemError event to do some other processing. For example, you can set a code to accept the data value, or reject the data value but allow focus to change.
For more information about the events of the DataWindow control, see DataWindow Reference.
You can access data values in a DataWindow by using methods or DataWindow data expressions. Both methods allow you to access data in any buffer and to get original or current values.
The method you use depends on how much data you are accessing and whether you know the names of the DataWindow columns when the script is compiled.
For guidelines on deciding which method to use, see Accessing Data in Code in DataWindow Reference.
Using methods
There are several methods for manipulating data in a DataWindow control.
These methods obtain the data in a specified row and column in a specified buffer:
-
PowerBuilder
GetItemDate, GetItemDateTime, GetItemDecimal, GetItemNumber, GetItemString, GetItemTime
This method sets the value of a specified row and column:
-
PowerBuilder
SetItem
For example, the following statement, using PowerBuilder syntax, assigns the value from the empname column of the first row to the variable ls_Name in the Primary buffer:
ls_Name = dw_1.GetItemString (1, "empname")
This PowerBuilder statement sets the value of the empname column in the first row to the string Waters:
dw_1.SetItem(1, "empname", "Waters")
Uses
You call the GetItem methods to obtain the data that has been accepted into a specific row and column. You can also use them to check the data in a specific buffer before you update the database. You must use the method appropriate for the column's datatype.
For more information about the methods listed above, see Methods for the DataWindow Control in DataWindow Reference.
Using expressions
DataWindow data expressions refer to single items, columns, blocks of data, selected data, or the whole DataWindow.
In PowerBuilder, you construct data expressions using dot notation.
Expressions in PowerBuilder
The Object property of the DataWindow control lets you specify expressions that refer directly to the data of the DataWindow object in the control. This direct data manipulation allows you to access small and large amounts of data in a single statement, without calling methods:
dw_1.Object.jobtitle[3] = "Programmer"
The next statement sets the value of the first column in the first row in the DataWindow to Smith:
dw_1.Object.Data[1,1] = "Smith"
For complete instructions on how to construct DataWindow data expressions, see Accessing Data in Code in DataWindow Reference.
There are many more methods you can use to perform activities in DataWindow controls. Here are some of the more common ones:
Method |
Purpose |
---|---|
AcceptText |
Applies the contents of the edit control to the current item in the DataWindow control |
DeleteRow |
Removes the specified row from the DataWindow control, placing it in the Delete buffer; does not delete the row from the database |
Filter |
Displays rows in the DataWindow control based on the current filter |
GetRow |
Returns the current row number |
InsertRow |
Inserts a new row |
Reset |
Clears all rows in the DataWindow control |
Retrieve |
Retrieves rows from the database |
RowsCopy, RowsMove |
Copies or moves rows from one DataWindow control to another |
ScrollToRow |
Scrolls to the specified row |
SelectRow |
Highlights a specified row |
ShareData |
Shares data among different DataWindow controls. |
Update |
Sends to the database all inserts, changes, and deletions that have been made in the DataWindow control |
For complete information on DataWindow methods, see Methods for the DataWindow Control in DataWindow Reference.
About DataWindow object properties
DataWindow object properties store the information that controls the behavior of a DataWindow object. They are not properties of the DataWindow control, but of the DataWindow object displayed in the control. The DataWindow object is itself made up of individual controls -- column, text, graph, and drawing controls -- that have DataWindow object properties.
You establish initial values for DataWindow object properties in the DataWindow painter. You can also get and set property values during execution in your code.
You can access the properties of a DataWindow object by using the Describe and Modify methods or DataWindow property expressions. Which you use depends on the type of error checking you want to provide and on whether you know the names of the controls within the DataWindow object and properties you want to access when the script is compiled.
For guidelines on deciding which method to use and for lists and descriptions of DataWindow object properties, see Accessing Data in Code in DataWindow Reference.
Using methods to access object properties
You can use the following methods to work with the properties of a DataWindow object:
-
Describe - Reports the values of properties of a DataWindow object and controls within the DataWindow object
-
Modify - Modifies a DataWindow object by specifying a list of instructions that change the DataWindow object's definition
PowerBuilder
For example, the following statements assign the value of the Border property for the empname column to a string variable:
string ls_border ls_border = dw_1.Describe("empname.Border")
The following statement changes the value of the Border property for the empname column to 1:
dw_emp.Modify("empname.Border=1")
About dynamic DataWindow objects
Using Describe and Modify, you can provide an interface through which application users can alter the DataWindow object during execution. For example, you can change the appearance of a DataWindow object or allow an application user to create ad hoc reports. For more information, see Dynamically Changing DataWindow Objects
Using expressions
DataWindow property expressions provide access to properties with fewer nested strings. In PowerBuilder, you can handle problems with incorrect object and property names in the Error event:
PowerBuilder
Use the Object property and dot notation. For example:
integer li_border li_border = Integer(dw_1.Object.empname.Border) dw_1.Object.empname.Border = 1
For reference material on the available variations for property expressions, see the the section called “PowerBuilder: DataWindow property expressions” in DataWindow Reference.
There are several types of errors that can occur during DataWindow processing:
-
Data items that are invalid (discussed in Manipulating data in a DataWindow control)
-
Failures when retrieving or updating data
-
Attempts to access invalid or nonexistent properties or data
This section explains how to handle the last two types of errors.
Retrieve and update testing
When using the Retrieve or Update method in a DataWindow control, you should test the method's return code to see whether the activity succeeded.
Do not test the SQLCode attribute
After issuing a SQL statement (such as CONNECT, COMMIT, or DISCONNECT) or the equivalent method of the transaction object, you should always test the success/failure code (the SQLCode attribute in the transaction object). However, you should not use this type of error checking following a retrieval or update made in a DataWindow.
For more information about error handling after a SQL statement, see the section called “Using Transaction Objects” in Application Techniques.
Method |
Return code |
Meaning |
---|---|---|
Retrieve |
>=1 |
Retrieval succeeded; returns the number of rows retrieved. |
-1 |
Retrieval failed; DBError event triggered. |
|
0 |
No data retrieved. |
|
Update |
1 |
Update succeeded. |
-1 |
Update failed; DBError event triggered. |
Example
PowerBuilder
If you want to commit changes to the database only if an update succeeds, you can code:
IF dw_emp.Update() > 0 THEN COMMIT USING EmpSQL; ELSE ROLLBACK USING EmpSQL; END IF
Using the DBError event
The DataWindow control triggers its DBError event whenever there is an error following a retrieval or update; that is, if the Retrieve or Update methods return -1. For example, if you try to insert a row that does not have values for all columns that have been defined as not allowing NULL, the DBMS rejects the row and the DBError event is triggered.
By default, the DataWindow control displays a message box describing the error message from the DBMS, as shown here:
In many cases you might want to code your own processing in the DBError event and suppress the default message box. Here are some tips for doing this:
To |
Do this |
---|---|
Get the DBMS's error code |
Use the SQLDBCode argument of the DBError event. |
Get the DBMS's message text |
Use the SQLErrText argument of the DBError event. |
Suppress the default message box |
Specify an action/return code of 1. |
About DataWindow action/return codes
Some events for DataWindow controls have codes that you can set to override the default action that occurs when the event is triggered. The codes and their meaning depend on the event. In PowerBuilder, you set the code with a RETURN statement.
Example
PowerBuilder
Here is a sample script for the DBError event:
// Database error -195 means that some of the // required values are missing IF sqldbcode = -195 THEN MessageBox("Missing Information", & "You have not supplied values for all " & +"the required fields.") END IF // Return code suppresses default message box RETURN 1
During execution, the user would see the following message box after the error:
A DataWindow control's Error event is triggered whenever an error occurs in a data or property expression at execution time. These expressions that refer to data and properties of a DataWindow object might be valid under some execution-time conditions but not others. The Error event allows you to respond with error recovery logic when an expression is not valid.
PowerBuilder syntax checking
In PowerBuilder, when you use a data or property expression, the PowerScript compiler checks the syntax only as far as the Object property. Everything following the Object property is evaluated at execution time. For example, in the following expression, the column name emp_name and the property Visible are not checked until execution time:
dw_1.Object.emp_name.Visible = "0"
If the emp_name column did not exist in the DataWindow, or if you had misspelled the property name, the compiler would not detect the error. However, at execution time, PowerBuilder would trigger the DataWindow control's Error event.
Using a Try-Catch block
The Error event is triggered even if you have surrounded an error-producing data or property expression in a Try-Catch block. The catch statement is executed after the Error event is triggered, but only if you do not code the Error event or do not change the default Error event action from ExceptionFail!. The following example shows a property expression in a Try-Catch block:
TRY dw_1.Object.emp_name.Visible = "0" CATCH (dwruntimeerror dw_e) MessageBox ("DWRuntimeError", dw_e.text) END TRY
Determining the cause of the error
The Error event has several arguments that provide information about the error condition. You can check the values of the arguments to determine the cause of the error. For example, you can obtain the internal error number and error text, the name of the object whose script caused the error, and the full text of the script where the error occurred. The information provided by the Error event's arguments can be helpful in debugging expressions that are not checked by the compiler.
If you catch a DWRuntimeError error, you can use the properties of that class instead of the Error event arguments to provide information about the error condition. The following table displays the correspondences between the Error event arguments and the DWRuntimeError properties.
Error event argument |
DWRuntimeError property |
---|---|
errornumber |
number |
errorline |
line |
errortext |
text |
errorwindowmenu |
objectname |
errorobject |
class |
errorscript |
routinename |
Controlling the outcome of the event
When the Error event is triggered, you can have the application ignore the error and continue processing, substitute a different return value, or escalate the error by triggering the SystemError event. In the Error event, you can set two arguments passed by reference to control the outcome of the event.
Argument |
Description |
---|---|
Action |
A value you specify to control the application's course of action as a result of the error. Values are: ExceptionIgnore! ExceptionSubstituteReturnValue! ExceptionFail! (default action) |
ReturnValue |
A value whose datatype matches the expected value that the DataWindow would have returned. This value is used when the value of action is ExceptionSubstituteReturnValue!. |
For a complete description of the arguments of the Error event, see the section called “Error” in DataWindow Reference.
When to substitute a return value
The ExceptionSubstituteReturnValue! action allows you to substitute a return value when the last element of an expression causes an error. Do not use ExceptionSubstituteReturnValue! to substitute a return value when an element in the middle of an expression causes an error.
The ExceptionSubstituteReturnValue! action is most useful for handling errors in data expressions.
After users have made changes to data in a DataWindow control, you can use the Update method to save the changes in the database. Update sends to the database all inserts, changes, and deletions made in the DataWindow since the last Update or Retrieve method was executed.
When updating the database, the DataWindow control determines the type of SQL statements to generate by looking at the status of each of the rows in the DataWindow buffers.
There are four DataWindow item statuses, two of which apply only to rows:
Status |
Applies to |
|
---|---|---|
PowerBuilder name |
Numeric value |
|
New! |
2 |
Rows |
NewModified! |
3 |
Rows |
NotModified! |
0 |
Rows and columns |
DataModified! |
1 |
Rows and columns |
Note
The named values are values of the enumerated datatype dwItemStatus. You must use the named values, which end in an exclamation point.
How statuses are set
When data is retrieved
When data is retrieved into a DataWindow, all rows and columns initially have a status of NotModified!.
After data has changed in a column in a particular row, either because the user changed the data or the data was changed programmatically, such as through the SetItem method, the column status for that column changes to DataModified!. Once the status for any column in a retrieved row changes to DataModified!, the row status also changes to DataModified!.
When rows are inserted
When a row is inserted into a DataWindow, it initially has a row status of New!, and all columns in that row initially have a column status of NotModified!. After data has changed in a column in the row, either because the user changed the data or the data was changed programmatically, such as through the SetItem method, the column status changes to DataModified!. Once the status for any column in the inserted row changes to DataModified!, the row status changes to NewModified!.
When a DataWindow column has a default value, the column's status does not change to DataModified! until the user makes at least one actual change to a column in that row.
When Update is called
For rows in the Primary and Filter buffers
When the Update method is called, the DataWindow control generates SQL INSERT and UPDATE statements for rows in the Primary and/or Filter buffers based upon the following row statuses:
A column is included in an UPDATE statement only if the following two conditions are met:
-
The column is on the updatable column list maintained by the DataWindow object
For more information about setting the update characteristics of the DataWindow object, see the section called “Controlling Updates in DataWindow objects” in Users Guide.
-
The column has a column status of DataModified!
The DataWindow control includes all columns in INSERT statements it generates. If a column has no value, the DataWindow attempts to insert a NULL. This causes a database error if the database does not allow NULLs in that column.
For rows in the Delete buffer
The DataWindow control generates SQL DELETE statements for any rows that were moved into the Delete buffer using the DeleteRow method. (But if a row has a row status of New! or NewModified! before DeleteRow is called, no DELETE statement is issued for that row.)
You might need to change the status of a row or column programmatically. Typically, you do this to prevent the default behavior from taking place. For example, you might copy a row from one DataWindow to another; and after the user modifies the row, you might want to issue an UPDATE statement instead of an INSERT statement.
You use the SetItemStatus method to programmatically change a DataWindow's row or column status information. Use the GetItemStatus method to determine the status of a specific row or column.
Changing column status
You use SetItemStatus to change the column status from DataModified! to NotModified!, or the reverse.
Change column status when you change row status
Changing the row status changes the status of all columns in that row to NotModified!, so if the Update method is called, no SQL update is produced. You must change the status of columns to be updated after you change the row status.
Changing row status
Changing row status is a little more complicated. The following table illustrates the effect of changing from one row status to another:
Original status |
Specified status |
|||
---|---|---|---|---|
New! |
NewModified! |
DataModified! |
NotModified! |
|
New! |
- |
Yes |
Yes |
No |
NewModified! |
No |
- |
Yes |
New! |
DataModified! |
NewModified! |
Yes |
- |
Yes |
NotModified! |
Yes |
Yes |
Yes |
- |
In the preceding table, Yes means the change is valid. For example, issuing SetItemStatus on a row that has the status NotModified! to change the status to New! does change the status to New!. No means that the change is not valid and the status is not changed.
Issuing SetItemStatus to change a row status from NewModified! to NotModified! actually changes the status to New!. Issuing SetItemStatus to change a row status from DataModified! to New! actually changes the status to NewModified!.
Changing a row's status to NotModified! or New! causes all columns in that row to be assigned a column status of NotModified!. Change the column's status to DataModified! to ensure that an update results in a SQL Update.
Changing status indirectly
When you cannot change to the desired status directly, you can usually do it indirectly. For example, change New! to DataModified! to NotModified!.
You can use DataWindow objects to create standard business reports such as financial statements, sales order reports, employee lists, or inventory reports.
To create a production report, you:
-
Determine the type of report you want to produce
-
Build a DataWindow object to display data for the report
-
Place the DataWindow object in a DataWindow control on a window or form
-
Write code to perform the processing required to populate the DataWindow control and print the contents as a report
Calling InfoMaker from an application
If your users have installed InfoMaker (the Appeon reporting product), you can invoke InfoMaker from an application. This way you can let your users create and save their own reports. To do this in PowerBuilder, use the Run function. For information about invoking InfoMaker, see the InfoMaker Users Guide.
To design the report, you create a DataWindow object. You select the data source and presentation style and then:
-
Sort the data
-
Create groups in the DataWindow object to organize the data in the report and force page breaks when the group values change
-
Enhance the DataWindow object to look like a report (for example, you might want to add a title, column headers, and a computed field to number the pages)
Using fonts
Printer fonts are usually shorter and fatter than screen fonts, so text might not print in the report exactly as it displays in the DataWindow painter. You can pad the text fields to compensate for this discrepancy. You should test the report format with a small amount of data before you print a large report.
After you build the DataWindow object and fill in print specifications, you can place it in a DataWindow control on a window or form, as described in Putting a DataWindow object into a control.
To allow users to print the report, your application needs code that performs the printing logic. For example, you can place a button on the window or form, then write code that is run when the user clicks the button.
To print the contents of a single DataWindow control or DataStore, call the Print method. For example, this PowerBuilder statement prints the report in the DataWindow control dw_Sales:
dw_Sales.Print(TRUE)
For information about the Print method, see the DataWindow Reference. For information about using nested reports to print multiple DataWindows, see Using nested reports.
Separate DataWindow controls in a single print job
For PowerBuilder applications only
If the window has multiple DataWindow controls, you can use multiple PrintDataWindow method calls in a script to print the contents of all the DataWindow controls in one print job.
These statements print the contents of three DataWindow controls in a single print job:
int job job = PrintOpen("Employee Reports") // Each DataWindow starts printing on a new page. PrintDataWindow(job, dw_EmpHeader) PrintDataWindow(job, dw_EmpDetail) PrintDataWindow(job, dw_EmpDptSum) PrintClose(job)
For information about PowerBuilder system functions for printing, see the section called “PowerScript Functions” in PowerScript Reference.
When designing a DataWindow object for a report, you can choose to nest other reports (which are also DataWindow objects) within it. The basic steps for using nested reports in an application are the same ones you follow for the other report types. There are, however, some additional topics concerning nested reports that you should know about.
To learn about designing nested reports, see the section called “Using Nested Reports” in Users Guide.
Printing multiple updatable DataWindows on a page
An advantage of composite reports is that you can print multiple reports on a page. A limitation of composite reports is that they are not updatable, so you cannot directly print several updatable DataWindows on one page. However, there is an indirect way to do that, as follows.
You can use the GetChild method on named nested reports in a composite report to get a reference to a nested report. After getting the reference to the nested report, you can address the nested report during execution like other DataWindows.
Using this technique, you can call the ShareData method to share data between multiple updatable DataWindow controls and the nested reports in your composite report. This allows you to print multiple updatable DataWindows on a page through the composite report.
To print multiple DataWindows on a page using a composite DataWindow:
-
Build a window or form that contains DataWindow controls with the updatable DataWindow objects.
-
Define a composite report that has reports corresponding to each of the DataWindows in the window or form that you want to print. Be sure to name each of the nested reports in the composite report.
Naming the nested report
To use GetChild on a nested report, the nested report must have a name. To name a nested report in the DataWindow painter, double-click it in the workspace and enter a name in the Name box on the General property page.
-
Add the composite report to the window or form (it can be hidden).
-
In your application, do the following:
-
Retrieve data into the updatable DataWindow controls.
-
Use GetChild to get a reference to the nested reports in the composite report.
-
Use ShareData to share data between the updatable DataWindow objects and the nested reports.
-
When appropriate, print the composite report.
-
The report contains the information from the updatable DataWindow objects.
Re-retrieving data
Each time you retrieve data into the composite report, all references (handles) to nested reports become invalid, and data sharing with the nested reports is terminated. Therefore, be sure to call GetChild and ShareData each time after retrieving data.
Creating and destroying nested reports during execution
You can create and destroy nested reports in a DataWindow object dynamically during execution using the same technique you use to create and destroy other controls in a DataWindow object.
Creating nested reports
To create a nested report, use the CREATE keyword with the Modify method. Supply the appropriate values for the nested report's properties.
Viewing syntax for creating a nested report
The easiest way to see the syntax for creating a nested report dynamically is to export the syntax of an existing DataWindow object that contains a nested report. The export file contains the syntax you need.
For more information about exporting syntax in the Library painter, see Users Guide.
When creating a nested report, you need to re-retrieve data to see the report. In a composite report, you can either retrieve data for the whole report or use GetChild to get a reference to the new nested report and retrieve its data directly. For nested reports in other reports, you need to retrieve data for the base report.
Destroying nested reports
To destroy a nested report, use the DESTROY keyword with the Modify method. The nested report disappears immediately.
For more about creating and destroying controls in a DataWindow object or report, see Dynamically Changing DataWindow Objects.
For a list of properties of nested reports, see the section called “Properties for Report controls in DataWindow objects” in DataWindow Reference.
To perform certain kinds of data analysis, you might want to design DataWindow objects in the Crosstab presentation style. The basic steps for using crosstabs in an application are the same ones you follow for the other DataWindow types, but there are some additional topics concerning crosstabs that you should know about.
To learn about designing crosstabs, see the section called “Working with Crosstabs” in Users Guide.
If you want users to be able to see the raw data as well as the cross-tabulated data, you can do one of two things:
-
Place two DataWindow controls on the window or form: one that is associated with the crosstab and one that is associated with a DataWindow object that displays the retrieved rows.
-
Create a composite DataWindow object that contains two reports: one that shows the raw data and one that shows the crosstab.
Do not share data between the two DataWindow objects or reports
They have the same SQL SELECT data definition, but they have different result sets.
For more about composite DataWindows, see Users Guide.
With the CrosstabDialog method, you can allow users to redefine which columns in the retrieved data are associated with the crosstab's columns, rows, and values during execution.
The CrossTabDialog method displays the Crosstab Definition dialog box for the user to define the data for the crosstab's columns, rows, and values (using the same techniques you use in the DataWindow painter). When the user clicks OK in the dialog box, the DataWindow control rebuilds the crosstab with the new specifications.
Displaying informational messages
You can display informational messages when a crosstab is rebuilt during execution as a result of the call to CrosstabDialog. (The messages are the same ones you see when building a crosstab in the DataWindow painter, such as Retrieving data and Building crosstab.) You might want to do this if you are working with a very large number of rows and rebuilding the crosstab could take a long time.
PowerBuilder
In PowerBuilder, you use a user event to display the crosstab's informational messages.
To display informational messages when a crosstab is rebuilt:
-
Define a user event for the DataWindow control containing the crosstab. Associate it with the event ID pbm_dwnmessagetext.
-
In the script for the user event, get the value of the text argument (which holds the message that PowerBuilder would display when building the crosstab in the DataWindow painter) and display it to the user.
Examples
PowerBuilder
In the example, code for the DataWindow control's user event for pbm_dwnmessagetext displays informational messages in a static text control in the window containing the crosstab:
st_message.Text = text
With that script in place, after CrosstabDialog has been called and the user has redefined the crosstab, as the crosstab is being rebuilt, your application dynamically displays the informational messages in the static text control st_message. (You might want to reset st_message.Text to be the empty string in the line following the CrosstabDialog call.)
In this example, code in the user event for pbm_dwnmessagetext displays informational messages as MicroHelp in an MDI application (w_crosstab is an MDI frame window):
w_crosstab.SetMicroHelp(text)
The informational messages are displayed in the MDI application's MicroHelp as the crosstab is rebuilt.
For more information
For more about user events in PowerBuilder, see the section called “Working with User Events” in Users Guide.
For more about the CrosstabDialog method and MessageText event, see the section called “CrosstabDialog” in DataWindow Reference and the section called “MessageText” in DataWindow Reference.
As with other DataWindow objects, you can modify the properties of a crosstab during execution using the Modify method. Some changes require the DataWindow control to dynamically rebuild the crosstab; others do not. (If the original crosstab was static, it becomes a dynamic crosstab when it is rebuilt.)
Changes that do not force a rebuild
You can change the following properties without forcing the DataWindow control to rebuild the crosstab:
Properties |
Objects |
---|---|
Alignment |
Column, Compute, Text |
Background |
Column, Compute, Line, Oval, Rectangle, RoundRectangle, Text |
Border |
Column, Compute, Text |
Brush |
Line, Oval, Rectangle, RoundRectangle |
Color |
Column, Compute, Text |
Edit styles (dddw, ddlb, checkbox, edit, editmask, radiobutton, richtext) |
Column |
Font |
Column, Compute, Text |
Format |
Column, Compute |
Pen |
Line, Oval, Rectangle, RoundRectangle |
Pointer |
Column, Compute, Line, Oval, Rectangle, RoundRectangle, Text |
Changes that force a rebuild
If you change any other properties, the DataWindow control rebuilds the structure of the crosstab when Modify is called. You should combine all needed expressions into one Modify call so that the DataWindow control has to rebuild the crosstab only once.
Default values for properties
For computations derived from existing columns, the DataWindow control by default uses the properties from the existing columns. For completely new columns, properties (such as font, color, and so on) default to the first column of the preexisting crosstab. Properties for text in headers default to the properties of the first text control in the preexisting crosstab's first header line.
For more about the Modify method, see Dynamically Changing DataWindow Objects. For details on the DataWindow object properties, see DataWindow Object Properties in DataWindow Reference.
You can use the data in a DataWindow object to create HyperText Markup Language (HTML) syntax. Once the HTML has been created, you can display it in a Web browser.
Techniques you can use
You can use any of several techniques to generate HTML from a DataWindow object.
In a painter
In both the DataWindow painter and the Output view in the Database painter, you can save retrieved data in HTML format. To do this in the DataWindow painter, select File>Save Rows As from the menu. In the Database painter, open the Output view, then select Rows>Save Rows As from the menu. In both painters, specify HTML Table as the format for the file.
In your application code
You can obtain an HTML string of the DataWindow presentation and data from the Data.HTMLTable property. You can save the string in a variable and modify the HTML with string manipulation operations. In PowerBuilder, you can also use the FileOpen and FileWrite functions to save the HTML to a file.
The HTMLTable property has its own properties which you can set to control the HTML attributes and style sheet associated with the Table HTML element.
PowerBuilder only
In PowerBuilder, there are two more techniques available to you. You can:
-
Call the SaveAs method to save the contents of a DataWindow directly to a file on disk. To save the data in HTML format, you need to specify HTMLTable as the file type when you call SaveAs.
-
Call the GenerateHTMLForm method to create an HTML form from data contained in a DataWindow control or DataStore whose DataWindow object uses the Freeform or Tabular presentation style.
Choosing presentation styles
Some DataWindow presentation styles translate better into HTML than others. The following presentation styles produce good results:
Tabular |
Group |
TreeView |
Freeform |
Crosstab |
Grid |
The Composite, Graph, RichText, and OLE 2.0 presentation styles produce HTML output that is based on the result only, and not on the presentation style. DataWindows that have overlapping controls might not produce the expected results. Nested reports are ignored; they are not included in the generated HTML.
Example
This example illustrates how you might use DataWindow-generated HTML in an application.
The key line of code gets the HTML from the DataWindow by referring to its HTMLTable property. In PowerBuilder, you can use the Describe method or a property expression.
PowerBuilder
ls_htmlstring = dw_1.Object.DataWindow.Data.HTMLTable
The complete example that follows is implemented in PowerBuilder.
The window below displays customer data in a tabular DataWindow object. By pressing the Browse button, the user can translate the contents of the DataWindow object into HTML format and invoke a Web browser to view the HTML output. By pressing the Select Browser button, the user can tell the application which Web browser to use:
Script for the Select Browser button
The script for the Select Browser button displays a dialog box where the user can select an executable file for a Web browser. The path to the executable is stored in is_Browser, which is an instance variable defined on the window:
String ls_BrowserName Integer li_Result // Open the dialog to select a browser. li_Result = GetFileOpenName("Select Browser", & is_Browser, ls_BrowserName, & "exe", "Executable Files (*.EXE),*.EXE") IF li_Result = -1 THEN MessageBox("No Browser", "No Browser selected") END IF
Script for the Browse button
The script for the Browse button creates an HTML string from the data in the DataWindow by assigning the Data.HTMLTable property to a string variable. After constructing the HTML string, the script adds a header to the HTML string. Then the script saves the HTML to a file and runs the Web browser to display the output.
String ls_HTML, ls_FileName, ls_BrowserPath Integer li_FileNumber, li_Bytes, Integer li_RunResult, li_Result // Generate the HTML. ls_HTML = dw_1.Object.DataWindow.Data.HTMLTable IF IsNull(ls_HTML) Or Len(ls_HTML) <= 1 THEN MessageBox ("Error", "Error generating HTML!") Return ELSE ls_HTML ="<H1>HTML Generated From a DataWindow"& + "</H1><P>" + ls_HTML END IF //Create the file. ls_FileName = "custlist.htm" li_FileNumber = FileOpen(ls_FileName, StreamMode!, & Write!, LockReadWrite!, Replace! ) IF (li_FileNumber >= 0) THEN li_Bytes = FileWrite(li_FileNumber, ls_HTML) FileClose(li_FileNumber) IF li_Bytes = Len(ls_HTML) THEN // Run Browser with the HTML file. IF Not FileExists(is_Browser) THEN cb_selbrowser.Trigger Event Clicked() IF NOT FileExists(is_Browser) THEN MessageBox("Select Browser", "Could & not find the browser.") RETURN END IF END IF li_RunResult = Run(is_Browser + " file:///"+& ls_FileName) IF li_RunResult = -1 THEN MessageBox("Error", "Error running browser!") END IF ELSE MessageBox ("Write Error", & "File Write Unsuccessful") END IF ELSE MessageBox ("File Error", "Could not open file") END IF
You control table display and style sheet usage through the HTMLTable.GenerateCSS property. The HTMLTable.GenerateCSS property controls the downward compatibility of the HTML found in the HTMLTable property. If HTMLTable.GenerateCSS is FALSE, formatting (style sheet references) is not referenced in the HTMLTable property; if it is TRUE, the HTMLTable property includes elements that reference the cascading style sheet saved in HTML.StyleSheet.
This screen shows an HTML table in a browser using custom display features:
HTMLTable.GenerateCSS is TRUE
If the HTMLTable.GenerateCSS property is TRUE, the HTMLTable element in the HTMLTable property uses additional properties to customize table display. For example, suppose you specify the following properties:
HTMLTable.NoWrap=Yes HTMLTable.Border=5 HTMLTable.Width=5 HTMLTable.CellPadding=2 HTMLTable.CellSpacing=2
Describe, Modify, and dot notation
You can access these properties by using the Modify and Describe PowerScript methods or by using dot notation.
The HTML syntax in the HTMLTable property includes table formatting information and class references for use with the style sheet:
<table cellspacing=2 cellpadding=2 border=5 width=5> <tr> <td CLASS=0 ALIGN=center>Employee ID <td CLASS=0 ALIGN=center>First Name <td CLASS=0 ALIGN=center>Last Name <tr> <td CLASS=6 ALIGN=right>102 <td CLASS=7>Fran <td CLASS=7>Whitney </table>
HTMLTable.GenerateCSS is FALSE
If HTMLTable.GenerateCSS is FALSE, the DataWindow does not use HTMLTable properties to create the Table element. For example, if GenerateCSS is FALSE, the HTML syntax for the HTMLTable property might look like this:
<table> <tr> <th ALIGN=center>Employee ID <th ALIGN=center>First Name <th ALIGN=center>Last Name <tr> <td ALIGN=right>102 <td>Fran <td>Whitney </table>
Merging HTMLTable with the style sheet
The HTML syntax contained in the HTMLTable property is incomplete: it is not wrapped in <HTML></HTML> elements and does not contain the style sheet. You can write code in your application to build a string representing a complete HTML page.
PowerBuilder example
This example sets DataWindow properties, creates an HTML string, and returns it to the browser:
String ls_html ds_1.Modify & ("datawindow.HTMLTable.GenerateCSS='yes'") ds_1.Modify("datawindow.HTMLTable.NoWrap='yes'") ds_1.Modify("datawindow.HTMLTable.width=5") ds_1.Modify("datawindow.HTMLTable.border=5") ds_1.Modify("datawindow.HTMLTable.CellSpacing=2") ds_1.Modify("datawindow.HTMLTable.CellPadding=2") ls_html = "<HTML>" ls_html += & ds_1.Object.datawindow.HTMLTable.StyleSheet ls_html += "<BODY>" ls_html += "<H1>DataWindow with StyleSheet</H1>" ls_html += ds_1.Object.DataWindow.data.HTMLTable ls_html += "</BODY>" ls_html += "</HTML>" return ls_html
This technique provides control over HTML page content. Use this technique as an alternative to calling the SaveAs method with the HTMLTable! Enumeration.
As an alternative to creating HTML pages dynamically, you can call the SaveAs method with the HTMLTable! Enumeration:
ds_1.SaveAs & ("C:\TEMP\HTMLTemp.htm", HTMLTable!, TRUE)
This creates an HTML file with the proper elements, including the style sheet:
<STYLE TYPE="text/css"> <!-- .2 {COLOR:#000000;BACKGROUND:#ffffff;FONT-STYLE:normal;FONT-WEIGHT:normal;FONT:9pt "Arial", sans-serif;TEXT-DECORATION:none} .3{COLOR:#000000;BACKGROUND:#ffffff;FONT-STYLE:normal;FONT-WEIGHT:normal;FONT:8pt "MS Sans Serif", sans-serif;TEXT-DECORATION:none} .3{COLOR:#000000;BACKGROUND:#ffffff;FONT-STYLE:normal;FONT-WEIGHT:normal;FONT:8pt "MS Sans Serif", sans-serif;TEXT-DECORATION:none} --> </STYLE> <TABLE nowrap cellspacing=2 cellpadding=2 border=5 width=5> <tr> <td CLASS=2 ALIGN=right>Employee ID: <td CLASS=3 ALIGN=right>501 <tr> <td CLASS=2 ALIGN=right>Last Name: <td CLASS=3>Scott <tr> <td CLASS=2 ALIGN=right>First Name: <td CLASS=3>David <tr> <td CLASS=2 ALIGN=right>Status: <td CLASS=3>Active </TABLE>
The GenerateHTMLForm method creates HTML form syntax for DataWindow objects. You can create an HTML form that displays a specified number of columns for a specified number of rows. Note the following:
-
You create HTML form syntax by calling the GenerateHTMLForm method for the DataWindow control or DataStore
-
The GenerateHTMLForm method creates HTML form syntax for the detail band only
-
Embedded nested DataWindows are ignored; they are omitted from the generated HTML
Presentation styles
Although the GenerateHTMLForm method generates syntax for all presentation styles, the only styles that create usable forms are Freeform and Tabular.
The following HTML page shows a freeform DataWindow object converted into a form using syntax generated by the GenerateHTMLForm method:
Edit style conversion
The GenerateHTMLForm method converts column edit styles into the appropriate HTML elements:
Column edit style |
HTML element |
---|---|
CheckBox |
Input element specifying TYPE=CHECKBOX |
DropDownDataWindow |
Select element with a single Option element |
DropDownListBox |
Select element with one Option element for each item in the DropDownListBox |
Edit |
Input element specifying TYPE=TEXT |
RadioButton |
Input element specifying TYPE=RADIO |
Generating syntax
To generate HTML form syntax, you call the GenerateHTMLForm method:
instancename.GenerateHTMLForm ( syntax, style, action { , startrow, endrow, startcolumn, endcolumn { , buffer } } )
The method places the Form element syntax into the syntax argument and the HTML style sheet into the style argument, both of which are passed by reference.
Static texts in freeform DataWindow objects
All static texts in the detail band are passed through to the generated HTML form syntax. If you limit the number of columns to be converted using the startcolumn and endcolumn arguments, remove the headers from the detail band for the columns you eliminate.
Here is an example of the GenerateHTMLForm method:
String ls_syntax, ls_style, ls_action String ls_html Integer li_return ls_action = & "/cgi-bin/pbcgi60.exe/myapp/uo_webtest/f_emplist" li_return = ds_1.GenerateHTMLForm & (ls_syntax, ls_style, ls_action) IF li_return = -1 THEN MessageBox("HTML", "GenerateHTMLForm failed") ELSE // of_MakeHTMLPage is an object method, // described in the next section. ls_html = this.of_MakeHTMLPage & (ls_syntax, ls_style) END IF
After calling the GenerateHTMLForm method, the ls_syntax variable contains a Form element. Here is an example:
<FORM ACTION= "/cgi-bin/pbcgi60.exe/myapp/uo_webtest/f_emplist" METHOD=POST> <P> <P><FONT CLASS=2>Employee ID:</FONT> <INPUT TYPE=TEXT NAME="emp_id_1" VALUE="501"> <P><FONT CLASS=2>Last Name:</FONT> <INPUT TYPE=TEXT NAME="emp_lname_1" MAXLENGTH=20 VALUE="Scott"> <P><FONT CLASS=2>First Name:</FONT> <INPUT TYPE=TEXT NAME="emp_fname_1" MAXLENGTH=20 VALUE="David"> <P><FONT CLASS=2>Status:</FONT> <INPUT TYPE="RADIO" NAME="status_1" CHECKED CLASS=5 ><FONT CLASS=5 >Active <P> <INPUT TYPE="RADIO" NAME="status_1" CLASS=5 > <FONT CLASS=5 >Terminated <P> <INPUT TYPE="RADIO" NAME="status_1" CLASS=5 > <FONT CLASS=5 >On Leave <P> <P> <BR> <INPUT TYPE=SUBMIT NAME=SAMPLE VALUE="OK"> </FORM>
The ls_stylesheet variable from the previous example contains a Style element, an example of which is shown below:
<STYLE TYPE="text/css"> <!-- .2{COLOR:#000000;BACKGROUND:#ffffff;FONT-STYLE:normal;FONT-WEIGHT:normal;FONT:9pt "Arial", sans-serif;TEXT-DECORATION:none} .3{COLOR:#000000;BACKGROUND:#ffffff;FONT-STYLE:normal;FONT-WEIGHT:normal;FONT:8pt "MS Sans Serif", sans-serif;TEXT-DECORATION:none} .5{COLOR:#000000;BACKGROUND:#ffffff;FONT-STYLE:normal;FONT-WEIGHT:normal;FONT:8pt "MS Sans Serif", sans-serif;TEXT-DECORATION:none} --> </STYLE>
Unique element names
The GenerateHTMLForm method creates unique names for all elements in the form (even when displaying multiple rows in one form) by adding a _nextsequentialnumber suffix.
Creating an HTML page
To use the syntax and style sheet returned by the GenerateHTMLForm method, you must write code to merge them into an HTML page. A complete HTML page requires <HTML> and <BODY> elements to contain the style sheet and syntax.
One way to do this is to create a global or object function that returns a complete HTML page, taking as arguments the Form and Style elements generated by the GenerateHTMLForm method. Such a function might contain the following code:
// Function Name: of_MakeHTMLPage // Arguments: String as_syntax, String as_style // Returns: String //*********************************** String ls_html IF as_syntax = "" THEN RETURN "" END IF IF as_style = "" THEN RETURN "" END IF ls_html = "<HTML>" ls_html += as_style ls_html += "<BODY>" ls_html += "<H1>Employee Information</H1>" ls_html += as_syntax ls_html += "</BODY></HTML>" RETURN ls_html