Check if column/row has REALLY been modified


Link to this posting

Postby Ursego » 03 Apr 2013, 15:15

uf_col_modified()

Reports if the column's value has been modified since the retrieval or last save.

Checking of the field's DWItemStatus doesn't work: if the value was changed, but later the original value was restored (so, the column has not been REALLY modified), the status is still DataModified! as it was set by the first change - the second change didn't bring it back to NotModified!. :twisted: . So, the only reliable way to get the answer is comparison of the current and the original values (keeping in mind that one of them, or both, can be NULL). And that is exactly what the proposed function does. It makes scripts shorter by exempting developers from:

1. Declaration and populating of two variables (to keep the compared values).
2. Processing of NULLs. "No change" is reported if both the values are NULLs, and "change occurred" if only one of them is NULL.

Code: Select all
/**********************************************************************************************************************
Dscr:         Checks if the column's value has been modified since the retrieval or last save.
            Use this function instead of checking the column's DWItemStatus (which remains DataModified!
            if user changed the value and after that restored the original one).
            
            This function makes scripts shorter beacuse it exempts them from:
               1. Declaration and populating of variables for the original and current values.
               2. Processing of NULLs (the value is reported as not modified if both the values, the old and the new,
                        are NULLs, and modified if only one of them is NULL).
            
            If the script deals only with the current record of the Primary! buffer (for example, in a FORM DW, or in
            a multi-rows DW with no filtering and deletion) then you can use the overloaded version with 2 arguments (adw & as_col).
***********************************************************************************************************************
Arg:         DataWindow   adw
            long         al_row
            string      as_col
            DWBuffer      a_buf
***********************************************************************************************************************
Ret:         boolean (true - has been changed, false - has NOT been changed)
***********************************************************************************************************************
Developer:   Michael Zuskin - LinkedIn: http://linkedin.com/in/zuskin
**********************************************************************************************************************/
long      ll_row_count
string   ls_col_type
string   ls_old
string   ls_new

choose case a_buf
case Primary!
   ll_row_count = adw.RowCount()
case Filter!
   ll_row_count = adw.FilteredCount()
case Delete!
   ll_row_count = adw.DeletedCount()
end choose

// Validate parameters:
choose case true
case IsNull(al_row)
   f_throw(PopulateError(1, "Arg al_row is null.")) // f_throw(): http://forum.powerbuilder.us/viewtopic.php?f=2&t=1
case adw.DataObject = ''
   f_throw(PopulateError(2, "DW doesn't have DataObject."))
case adw.Describe(as_col + '.Name') <> as_col // no such column in the DW
   f_throw(PopulateError(3, "DW doesn't have column '" + as_col + "'."))
case al_row < 0
   f_throw(PopulateError(4, "Arg al_row is negative (" + String(al_row) + ")."))
case al_row > ll_row_count
   f_throw(PopulateError(5, "Arg al_row (" + String(al_row) + ") is greater than the number of rows in DW (" + String(ll_row_count) + ")."))
end choose

// Obtain old (original) and new (current) values:
ls_col_type = Lower(Left(adw.Describe(as_col + ".coltype"), 5))
choose case ls_col_type
case "numbe", "long", "ulong", "real", "int", "decim"
   ls_old = String(adw.GetItemNumber(al_row, as_col, a_buf, true))
   ls_new = String(adw.GetItemNumber(al_row, as_col, a_buf, false))
case "char(", "char"
   ls_old = adw.GetItemString(al_row, as_col, a_buf, true)
   ls_new = adw.GetItemString(al_row, as_col, a_buf, false)
case "datet", "times"
   ls_old = String(adw.GetItemDateTime(al_row, as_col, a_buf, true))
   ls_new = String(adw.GetItemDateTime(al_row, as_col, a_buf, false))
case "date"
   ls_old = String(adw.GetItemDate(al_row, as_col, a_buf, true))
   ls_new = String(adw.GetItemDate(al_row, as_col, a_buf, false))
case "time"
   ls_old = String(adw.GetItemTime(al_row, as_col, a_buf, true))
   ls_new = String(adw.GetItemTime(al_row, as_col, a_buf, false))
end choose

// Define if the value has been changed:
if IsNull(ls_old) and IsNull(ls_new) then return false
if IsNull(ls_old) and not IsNull(ls_new) then return true
if not IsNull(ls_old) and IsNull(ls_new) then return true

return (ls_new <> ls_old)

If the script deals only with the current record of the Primary! buffer (for example, in a FORM DW, or in a multi-rows DW with no filtering and deletion) then you can create an overloaded version (with only 2 arguments - adw and as_col_name) having the following script:

Code: Select all
return uf_col_modified(adw, as_col, adw.GetRow(), Primary!)


uf_row_modified()

Reports if at least one field in the passed row has been modified. For that, it calls uf_col_modified() in a loop, for each column:

Code: Select all
/**********************************************************************************************************************
Dscr:         Reports if the passed row has been updated, i.e. at least one of its fields has been updated.
            A field is considered updated if its value has been changed since row is retrieved/inserted but not saved.
            If the value was changed and later the original value was restored, that is not considered updated
            (nothing to do with DWItemStatus which remains DataModified! even if user restored the original value later).
           
            If the script deals only with the current record of the Primary! buffer (for example, in a FORM DW, or in
            a multi-rows DW with no filtering and deletion) then you can use the overloaded version with 1 argument (adw).
***********************************************************************************************************************
Arg:         adw            DataWindow
            al_row         long
            DWBuffer         a_buf
***********************************************************************************************************************
Ret:         boolean
***********************************************************************************************************************
Developer:   Michael Zuskin - LinkedIn: http://linkedin.com/in/zuskin
**********************************************************************************************************************/
int      i
int      li_col_count
string   as_col

li_col_count = Integer(adw.Describe("datawindow.column.count"))
for i = 1 to li_col_count
   as_col = adw.Describe("#"+ String(i) + ".Name")
   if uf_col_modified(adw, as_col, al_row, a_buf) then
      return true
   end if
next

return false


The code of an overload to check only the current row in the Primary! buffer:

Code: Select all
return uf_row_modified(adw, adw.GetRow(), Primary!)
User avatar
Ursego
Site Admin
 
Posts: 120
Joined: 19 Feb 2013, 20:33


IF you want to ((lose weight) OR (have unbelievable (brain function AND mental clarity))) THEN click:




cron
free counters

eXTReMe Tracker