Schultz’s PowerBuilder Notes

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:

itemstatus

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
About these ads

January 1, 2009 - Posted by | 2. Datawindows, Datawindow PowerScript, Powerscript | , , , , , , , , , ,

9 Comments »

  1. 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

    Comment by Chris Werner | January 21, 2009 | Reply

    • 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.

      Comment by rick130 | January 22, 2009 | Reply

  2. 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

    Comment by Ismail | January 27, 2009 | Reply

    • 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

      Comment by rick130 | January 27, 2009 | Reply

  3. Why not write SIMPLY???

    http://www.zuskin.com/pb_tricks.htm#SetItemStatus

    Comment by Michael Zuskin | May 24, 2012 | Reply

    • 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.

      Comment by rick130 | May 25, 2012 | Reply

      • 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 .

        Comment by Michael Zuskin | March 10, 2013

  4. 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.

    Comment by Michael Zuskin | March 10, 2013 | Reply

    • You are right, the rows should be longs not integers. I have updated the script. Thanks for the correction.

      Comment by rick130 | March 11, 2013 | Reply


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: