
---------------------------------------------------------- back to tips menu
DataWindow Code Samples
ItemChanged Code Sample
The following sample ItemChanged code could be used on a typical descendant window.
integer li_Return = 0 // default is that validation succeeded
CHOOSE CASE Lower(dwo.Name)
CASE "quantity"
// only perform validation if data was entered
IF NOT IsNull(data) AND Len(data) > 0 THEN
// check if quantity is in its valid range
IF long(data) < 1 OR long(data) > 999 THEN
MessageBox("Error", "Quantity must be between 1 and 999.")
li_Return = 1
END IF
END IF
CASE "group_code" // DDDW
// only perform validation if data was entered
IF NOT IsNull(data) AND Len(data) > 0 THEN
// verify code is valid (i.e. it is in drop down)
li_DddwResult = f_CheckDdddwValue(dwo.Name, data, "description", ls_Desc)
// Entry not in DDDW -- tell user of error
IF li_DddwResult < 0 THEN
MessageBox("Error", "Invalid value specified in drop down.")
li_Return = 1
ELSE
// entry empty or OK, update corresponding description on DW
This.SetItem(1,"Description Field",ls_DddwDesc)
END IF
END IF
END CHOOSE
// set flag so ItemError know to suppress its default message
IF li_Return = 1 THEN
ib_SuppressMsg = True
END IF
Return li_Return
ote: if this ItemChanged event were written under PFC, it would use the DW function f_message() (instead of MessageBox) as suggested under the PFC tips
ItemError Code Sample
Sample ItemError Event
The sample ItemError code is appropriate for use in an ancestor DataWindow. The sample
does the following error checking:
integer li_Return
string ls_ColType
n_cst_conversion lnv_conversion
ls_ColType = Lower(left(dwo.ColType,5))
// if problem found in ancestor ItemError, don't check error further
IF AncestorReturnValue <> 0 THEN
li_Return = AncestorReturnValue
ELSE
// if the error originated in ItemChanged a message will have been displayed there,
// so simply suppress the standard ItemError error message.
IF ib_SuppressMsg THEN
ib_SuppressMsg = False
li_Return = 1
// check if it is a missing "NilIsNull" property
ELSEIF ls_ColType <> "char(" AND NOT IsNull(data) AND Len(data) = 0 THEN
MessageBox("Error", "You cannot empty this field due to a software " + &
"fault.~r~n To continue, you must supply a valid value.")
// write missing NilIsNull property error to central error log ...
li_Return = 1
ELSE
// Determine if the problem is a data type mismatch
CHOOSE CASE ls_ColType
CASE "datet"
// datetime type mismatch
IF IsNull(lnv_conversion.f_DateTime(data)) THEN
// Many DB's only have datetime columns but the user might consider it a "date".
// For that reason, use more generic message wording.
MessageBox("Error","Value is not a valid Date or DateTime")
li_Return = 1
END IF
CASE "date"
// date type mismatch
IF NOT IsDate(data) THEN
MessageBox("Error","Value is not a valid Date")
li_Return = 1
END IF
CASE "time"
// time type mismatch
IF NOT IsTime(data) THEN
MessageBox("Error","Value is not a valid Time")
li_Return = 1
END IF
CASE "decim", "long", "ulong", "numbe", "real"
// if data type mismatch, determine cause ...
IF NOT IsNumber(data) THEN
MessageBox("Error","Value is not a valid Number")
li_Return = 1
END IF
END CHOOSE
END IF
END IF
Return li_Return
Note: if this ItemError event were written under PFC, it would use the DW function f_message() (instead of MessageBox) as suggested under the PFC tips
DBError Code Sample
When a DataWindow update fails due to a database error, PowerBuilder invokes the DBError event. By default, DBError displays an error message with the full error text from the database. By coding the DBError event, special processing can be performed and a custom error message can be displayed for appropriate database error codes. The next coding sample shows handling for two error conditions: a duplicate row and a row that changed between retrieve and update. If you are using PFC, see note below.
integer li_Return
CHOOSE CASE SqlDbCode
CASE 1 // 1 is Oracle for duplicate (2601 for Sybase, -193/-196 for SQL Anywhere)
MessageBox("Error","Duplicate value on this Row")
// set focus to enterable unique key column
This.SetColumn("Product")
li_Return = 1 // suppress default message
CASE -3 // standard PB number for row changed between retrieve and update
MessageBox("Error","Row Changed between since it was retrieved. " + &
"Data must be re-retrieved and the changes re-applied.")
li_Return = 1
CASE ELSE
li_Return = 0 // use the default message for any other errors
END CHOOSE
IF li_Return = 1 THEN
// if row is visible (i.e. in Primary buffer), set focus to that row
IF buffer = Primary! THEN
This.ScrollToRow(row)
This.f_SetFocus() // uses f_SetFocus() function shown above
ELSEIF buffer = Filter! THEN
// if bad row is filtered, make it visible (in primary buffer) first
This.RowsMove(row, row, Filter!, This, 1, Primary!)
This.ScrollToRow(1)
This.f_SetFocus()
END IF
END IF
Return li_Return
Note: DB Error handling for PFC has to be handled differently since there is ancestor logic in the PFC DataWindow DBError event. Unfortunately, the primitive PFC 5 DBError logic is not easily extended -- fixing the PFC 5 DBError logic requires some real effort. The PFC 6 DBError logic is improved but it still gives no simple hook where the descendant can opt to do its own handling for certain errors.