Setting the RowStatus
If you have worked with PowerBuilder for a while, you have learned that setting the status of a row is not always a straight forward procedure. I have created a handy utility which will simplify this process.
Row Status
Each row contains a status which determines what type of SQL statement the datawindow needs to generate when it is asked to update. The possible enumerated values are:
- New!
- NewModified!
- NotModified!
- DataModified!
The datawindow automatically maintains the row status in the background.
SetItemStatus
There are times when you want to change the row status programmatically. This is done with the SetItemStatus() function which contains the following arguments:
- Row
- Column
- Buffer
When setting the row status, the column argument needs to be zero. I have never selected the Delete! buffer, if you have played around with this, let me know if there is anything special about this.
The problem is that setting the row status to a new value may result in a new unexpected value. To get around this, Powerbuilder supplies the following table:

If a row begins with a status of NewModified! and you set the row status to NotModifed!, the actual row status changes to New!
So in order to change the row status of a NewModified! row to NotModified!, you must set the row to DataModified! Then you must set the row NotModifed! with a second SetItem function.
This is not exactly programmer friendly. For the life of me, I don’t know why PowerBuilder makes us do this dance. If I want to set a row’s status to DataModified!, it should be a one function call, regardless of what the current status of the row is. And I should not have to refer to this mysterious chart.
To ease this burden, I wrote the following function, and I put it in a nvo with other home built datawindow utilities. It is overloaded with a function which assumes the Primary!buffer.
This function resides on a nvo inherited from the PFC’s n_base object. This object supplies the constants SUCCESS and FAILURE.
of_SetRowStatus()
</pre>
//////////////////////////////////////////////////////////////////////////////
//
// Function: of_SetRowStatus (overloaded function to include buffer)
//
// Access: Public
//
// Description: Sets the Rowstatus of the passed row. It changes the rowstatus
// of the row and datastore specified in ai_row and adw, to the
// status specified in astatus_new.
//
// Arguments: u_dw adw
// integer ai_row
// dwItemStatus astatus_new
// dwbuffer adwbuffer
//
// Returns: integer
//
//////////////////////////////////////////////////////////////////////////////
// Revision History
//
// Date By Description/Comments
// -------- --- -------------------------------------------
// 05/10/06 fjs Initial Version (overloaded from original)
// 05/24/06 fjs Only Primary! and Filter! buffers supported.
// 02/06/09 fjs Fixed bug with New! going to NotModified!
//////////////////////////////////////////////////////////////////////////////
dwItemStatus lstatus_cur, lstatus_changed
integer li_rc = SUCCESS, li_row_cnt
string ls_msg
// validate arguments
if li_rc = SUCCESS then
if Not IsValid(adw) then
li_rc = FAILURE
ls_msg = "Passed datastore is not valid"
end if
end if
if li_rc = SUCCESS then
if IsNull(ai_row) then
li_rc = FAILURE
ls_msg = "Passed row must not be null"
end if
end if
if li_rc = SUCCESS then
if ai_row < 1 then
li_rc = FAILURE
ls_msg = "Passed row must be greater than 0"
end if
end if
if li_rc = SUCCESS then
choose case adwbuffer
case Primary!
li_row_cnt = adw.RowCount()
case Filter!
li_row_cnt = adw.FilteredCount()
// case Delete! // got to test this
// li_row_cnt = adw.DeleteCount()
case else
li_rc = FAILURE
ls_msg = "Passed adwbuffer is not known or not supported"
end choose
end if
if li_rc = SUCCESS then
if ai_row > li_row_cnt then
li_rc = FAILURE
ls_msg = "Passed row is greater than number of rows in datastore"
end if
end if
//change the rows status
if li_rc = SUCCESS then
lstatus_cur = adw.GetItemStatus(ai_row, 0, adwbuffer)
choose case lstatus_cur
case New!
choose case astatus_new
case New!
li_rc = NO_ACTION
case NewModified!, DataModified!
adw.SetItemStatus(ai_row, 0, adwbuffer, astatus_new)
case NotModified!
adw.SetItemStatus(ai_row, 0, adwbuffer, DataModified!)
adw.SetItemStatus(ai_row, 0, adwbuffer, NotModified!)
end choose
case NewModified!
choose case astatus_new
case New!
adw.SetItemStatus(ai_row, 0, adwbuffer, NotModified!)
case NewModified!
li_rc = NO_ACTION
case DataModified!
adw.SetItemStatus(ai_row, 0, adwbuffer, astatus_new)
case NotModified!
adw.SetItemStatus(ai_row, 0, adwbuffer, DataModified!)
adw.SetItemStatus(ai_row, 0, adwbuffer, NotModified!)
end choose
case DataModified!
choose case astatus_new
case New!
adw.SetItemStatus(ai_row, 0, adwbuffer, NotModified!)
adw.SetItemStatus(ai_row, 0, adwbuffer, New!)
case NewModified!, NotModified!
adw.SetItemStatus(ai_row, 0, adwbuffer, astatus_new)
case DataModified!
li_rc = NO_ACTION
end choose
case NotModified!
choose case astatus_new
case New!, NewModified!, DataModified!
adw.SetItemStatus(ai_row, 0, adwbuffer, astatus_new)
case NotModified!
li_rc = NO_ACTION
end choose
end choose
end if
//Validate that the new status is the desired change.
if li_rc = SUCCESS then
lstatus_changed = adw.GetItemStatus(ai_row, 0, adwbuffer)
if lstatus_changed <> astatus_new then
li_rc = FAILURE
ls_msg = "Row status changed to undesired status"
end if
end if
//Print error message
if li_rc = FAILURE then
if IsNull(ls_msg) then
ls_msg = "[null]"
end if
MessageBox("Error - of_SetRowStatus", ls_msg)
end if
Return li_rc
Here is the overloaded function
////////////////////////////////////////////////////////////////////////////// // // Function: of_SetRowStatus (overloaded function to include buffer) // // Access: Public // // Description: Sets the Rowstatus of the passed row. It changes the rowstatus // of the row and datastore specified in ai_row and adw, to the // status specified in astatus_new. // // Arguments: u_dw adw // integer ai_row // dwItemStatus astatus_new // // Returns: integer // ////////////////////////////////////////////////////////////////////////////// // Revision History // // Date By Description/Comments // -------- --- ------------------------------------------- // 05/10/06 fjs Initial Version (overloaded from original) // 05/24/06 fjs Only Primary! and Filter! buffers supported. // ////////////////////////////////////////////////////////////////////////////// int li_rc = SUCCESS li_rc = of_SetRowStatus(adw, ai_row, astatus_new, Primary!) Return li_rc
9 Comments »
Leave a Reply
-
Archives
- August 2009 (2)
- May 2009 (1)
- March 2009 (1)
- January 2009 (2)
- December 2008 (1)
- November 2008 (2)
- September 2008 (1)
- August 2008 (1)
- July 2008 (24)
- June 2008 (22)
- May 2008 (69)
- April 2008 (25)
-
Categories
-
RSS
Entries RSS
Comments RSS
Hi Mr. Schultz,
being a little bit pettifogging I guess that this
peace of code contains an error:
if ai_row li_row_cnt then
li_rc = FAILURE
ls_msg = “Passed row is greater than number …”
end if
I guess it must be:
if ai_row > li_row_cnt then
No offense!
Best regards,
Chris Werner
f+s software gmbh
Thanks for the note Chris,
This error does not exist in my production code, honest!
WordPress has a way of messing around with the “greater than” and “less than” signs when it is busy mangling the indenting. (sigh)
I have updated the post. Thanks for the code review.
Hi Schultz,
I’m getting the warning message “Undefined variable: success” while compile the code.
And I’m wondering how can we declare an integer variable li_rc as SUCCESS
Regards,
Ismail
Ismail,
The function sits on an NVO which is inherited from the PFC’s n_base class. n_base has the following instance variable constants:
Protected:
constant integer SUCCESS = 1
constant integer FAILURE = -1
constant integer NO_ACTION = 0
Why not write SIMPLY???
http://www.zuskin.com/pb_tricks.htm#SetItemStatus
Thanks for sharing your link with your code. Yes, your case statement looks slicker than what I wrote.
I did notice that your function does not validate any of the passed arguments. So if you pass an invalid datawindow, or a negative row, or a null row, or a row greater than the number of rows on the datawindow, etc., you will get a run time error. And if there is a flaw in your logic and the rowstatus is set to something other than what you intend, you get an unreported bug. This is the trade off when you write SIMPLY.
Yes, you are right – my version didn’t validate DW, row and the result, so I have added those validations. But I throw an exception instead of the old-style “return -1″ (of course, we cannot change the function if it is already in use and the calling scripts don’t process the exception). BTW, my function has moved here” http://forum.powerbuilder.us/viewtopic.php?f=4&t=9 .
The vars ai_row and li_row_cnt are of type integer while the possible actual parameter for ai_row and the ret value of RowCount/FilteredCount/DeletedCount are “long”. It’s a good chance to get a “quiet bug”! Fortunately, changing of their type to long solves the problem.
You are right, the rows should be longs not integers. I have updated the script. Thanks for the correction.