Check if column/row has REALLY been modified


Link to this posting

Postby Ursego » 03 Apr 2013, 15:15

Do not trust DWItemStatus. Instead of GetItemStatus, use uf_col_modified() and uf_row_modified(), suggested below.

uf_col_modified()

Reports if the passed column has been modified, i.e. its value has been changed since the row was retrieved/inserted/updated, but not been saved yet. If the value was changed, but later the original value was restored, the field is NOT considered modified regardless its DWItemStatus.

Checking of the field's DWItemStatus doesn't work always: 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 uf_col_modified() 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:         Reports if the passed column has been modified, i.e. its value has been changed since the row was
            retrieved/inserted/updated, but not been saved yet. If the value was changed, but later the original value
            was restored, the field is NOT considered modified regardless its DWItemStatus.
           
            If your script deals only with the current record of the Primary! buffer (i.e. it's a FORM DW),
            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 -  http://linkedin.com/in/zuskin | http://code.intfast.ca/
**********************************************************************************************************************/
string         ls_col_type
string         ls_old
string         ls_new
DWItemStatus   l_col_status

l_col_status = adw.GetItemStatus(al_row, as_col, a_buf)
if l_col_status = NotModified! then
   return false
end if

// If this code reached, it's DataModified!. That does not guarantee that the column has actually been
// modified - user could change its value (making it DataModified!), but restore
// the original value later (unfortunately, that doesn't rollback the status to NotModified!).
// So, we will compare the original and the 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

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 the passed row has been modified, i.e. at least one of its columns has been changed. A column is considered modified if its value has been changed since the row was retrieved/inserted/updated, but that change has not been saved yet. If the value was changed, but later the original value was restored, the column is NOT considered modified regardless its DWItemStatus.

Code: Select all
/**********************************************************************************************************************
Dscr:         Reports if the passed row has been modified, i.e. at least one of its columns has been changed.
            A column is considered modified if its value has been changed since the row was retrieved/inserted/updated,
            but that change has not been saved yet. If the value was changed, but later the original value was restored,
            the column is NOT considered modified regardless its DWItemStatus.
           
            If your script deals only with the current record of the Primary! buffer (i.e. it's a FORM DW),
            then you can use the overloaded version with 1 argument only (adw).
***********************************************************************************************************************
Arg:         adw            DataWindow
            al_row         long
            DWBuffer         a_buf
***********************************************************************************************************************
Ret:         boolean
***********************************************************************************************************************
Developer:   Michael Zuskin -  http://linkedin.com/in/zuskin | http://code.intfast.ca/
**********************************************************************************************************************/
int            i
int            li_col_count
string         as_col
DWItemStatus   l_row_status

l_row_status = adw.GetItemStatus(al_row, 0 /* get the status of the whole row */, a_buf)
choose case l_row_status
case New!, NotModified!
   return false
end choose

// If this code reached, it's NewModified! or DataModified!. That does not guarantee that the row has actually been
// modified - user could change a column in the row (marking it as NewModified! or DataModified!), but restore
// the original value later (unfortunately, that doesn't rollback the status to New! or NotModified!).
// So, we will utilize uf_col_modified() which compares the original and the current values.

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: 143
Joined: 19 Feb 2013, 20:33



Ketones are a more high-octane fuel for your brain than glucose. Become a biohacker and upgrade yourself to version 2.0!



cron
Traffic Counter

eXTReMe Tracker