FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin for Harbour/xHarbour Checking for updated fields
Posts: 363
Joined: Wed Feb 15, 2006 02:06 PM
Checking for updated fields
Posted: Thu Jun 18, 2009 01:39 PM

Hi,

I'm looking to put a message in my app to check if the user has updated any fields in a dialog (these can be gets/radio/checkboxes etc) and then if the user tries to quit, display a message saying "Data not saved, are you sure you wish to quit?"

Is there a global setting that i can put into my dialog that can get updated if any updates occur, or do i have to put an ON CHANGE onto each of my controls?

Any ideas will be appreciated

Pete

Posts: 2706
Joined: Fri Oct 07, 2005 01:50 PM
Re: Checking for updated fields
Posted: Thu Jun 18, 2009 01:54 PM

Peter

I don't have a direct answer for you .. but consider a couple options ..

1) In a network environment you could have issues with two people having buffered up the same record .. very typical in a small office situation .. if one person saves the record and the other saves on top of that same record .. you now have a delima. In this case I use a 'signature' numeric field that gets incremented once each time the record is saved. If workstation A saves a record the signature field in the table gets incremented .. the trick is before workstation B saves the same record .. you go out once again to the table and verify the signature field buffered on workstation B is the same as what the table says .. if not .. then workstation A has slipped behind workstation B and changed the information and workstation B should not be allowed to save if the signature field is not the same.

2) It may seem redundant .. but many times I will thru up a MsgYesNo() and even if nothing has changed and ask the user to Save or Cancel during the end of an Edit session .. let the user confirm if they have changed a record.

Just my 2 cents..

Rick Lipkin

Posts: 363
Joined: Wed Feb 15, 2006 02:06 PM
Re: Checking for updated fields
Posted: Thu Jun 18, 2009 02:03 PM

Thanks for your reply - i've always said to our customers that i could change my app to work as you suggested in point 2, so i'm probably going to go with that. Just wondered if there was an "hidden" automated procedure somewhere :wink:

Regards,

Pete

Posts: 663
Joined: Mon Dec 05, 2005 11:22 PM
Re: Checking for updated fields
Posted: Thu Jun 18, 2009 04:58 PM
This bit of code might point you in the right direction. This code would run after the ON INIT for the dialog. It does not take into account if you already have bChange block already assigned. You might have to add other types of controls also. It also does not do folder within folder.

Code (fw): Select all Collapse
   FOR nI := 1 TO LEN( oDlg:aControls )
       IF oDlg:aControls[ nI ]:ClassName() = "TGET" .or. oDlg:aControls[ nI ]:ClassName() = "TCHECKBOX"
         if oDlg:aControls[ nI ]:bChange == nil
           // Here is where you can assign variable or use function to turn on save checking. 
           // There is another place further down.
           oDlg:aControls[ nI ]:bChange = { || ::togglesaveon() } 
         endif
       ENDIF
       IF oDlg:aControls[ nI ]:ClassName() = "TFOLDER"
         FOR nIFold := 1 TO LEN( oDlg:aControls[ nI ]:aDialogs )
            FOR nFoldI := 1 TO LEN( oDlg:aControls[ nI ]:aDialogs[ nIFold ]:aControls )
               IF oDlg:aControls[ nI ]:aDialogs[ nIFold ]:aControls[ nFoldI ]:ClassName() = "TGET" .or. ;
                     oDlg:aControls[ nI ]:aDialogs[ nIFold ]:aControls[ nFoldI ]:ClassName() = "TCHECKBOX"
                 if oDlg:aControls[ nI ]:aDialogs[ nIFold ]:aControls[ nFoldI ]:bChange == nil
                   // Here is where you can assign variable or use function to turn on save checking.
                   oDlg:aControls[ nI ]:aDialogs[ nIFold ]:aControls[ nFoldI ]:bChange = { || ::togglesaveon() }
                 endif
               ENDIF
            NEXT
         NEXT
      ENDIF
   NEXT
Posts: 4840
Joined: Fri Nov 18, 2005 04:52 PM
Re: Checking for updated fields
Posted: Thu Jun 18, 2009 05:05 PM

Pete,

Personally, I am against such a design. The software should assume that the user wants to do what they said they did. I hate confirmations! Consider that 99 times out of a hundred, the answer will be the same. The user will be so used to getting rid of the annoying message by answering in a certain matter that it will be so automatic, that the one time in a hundred that they really needed to answer it differently, it will be too late. The confirmation message will have already been dismissed by the user in the usual way.

So confirmations don't work and they just create more work for the user.

If you really wish to do this, however, there is a modified() method of the TDatabase class that will tell you if the data has been changed. The database class holds the data in an array, the user can then edit it and the modified() method will check the array against the original record. Of course, you must change your code to use a database object in order to use the modified() method.

Regards,
James

FWH 18.05/xHarbour 1.2.3/BCC7/Windows 10
Posts: 6983
Joined: Fri Oct 07, 2005 07:07 PM
Re: Checking for updated fields
Posted: Thu Jun 18, 2009 06:59 PM

Hello James,
would you be so kind to explain the modified() method a bit.
Is modified asking if you want save.
It would also be a good step to have a undo build in.
Thanks in advance.
Best regards,
Otto

Posts: 4840
Joined: Fri Nov 18, 2005 04:52 PM
Re: Checking for updated fields
Posted: Thu Jun 18, 2009 09:27 PM

Otto,

>would you be so kind to explain the modified() method a bit.
>Is modified asking if you want save.

No, calling Modified() simply checks the buffer agianst the record and returns .t. if they are different.

>It would also be a good step to have a undo build in.

Yes, Undo is much better than a confirmation. In order to create a undo you will have to save the previous data somewhere, then provide an Undo button or menu choice.

James

FWH 18.05/xHarbour 1.2.3/BCC7/Windows 10
Posts: 10733
Joined: Sun Nov 19, 2006 05:22 AM
Re: Checking for updated fields
Posted: Fri Jun 19, 2009 05:20 AM

I fully agree with Mr. James on user psychology.

About checking whether any data is modified by a dialog, in a network environment, we need to consider two kinds of changes.

1) If our user has modified the data by editing the dialog.
2) If any other user changed the data, after our user read the data.

I normally use a class derived from TDataBase. I maintain two buffers, aOriginal and aBuffer. Comparing aOriginal and aBuffer tells me if our user has changed the data. If changed it needs to be saved. This comparison does not require a diskread, which is costly in network environments. ( This has another advantage. User might have edited a few Gets and again re-edited to the original values. In such a case we need not save the record ). Also maintaining two buffers aOriginal and aBuffer enables 'UNDO' without another diskread.

By comparing aOriginal with data in the table ( similar to modified method of TDataBase ) we know if some other user changed the data already. ( Comparing Version fields if maintained may appear to be faster, but our normal RDDs anyway read the entire record ).

Mr James' TData class stood the test of time. I do not know how TData class helps the programmer in this regard. Would Mr James or any user of TData like to enlighten us on this aspect of TData ?

It may be noted that ADO recordset also maintains these values to enable the programmer to do these kinds of comparisons. Every field has OriginalValue, UnderlyingValue and Value. Comparing Value with OriginalValue tells us if our user has modified data. Resync method to update only underlyingvalues reads the current data into this value. Comparing Value with UnderlyingValues tells is if other user modified the data. ( Using Version fields is faster while dealing with RDMSs )

In case, I am not using any classes, I normally have all the values in an array at the outset and compare with edited values in the dialog.

Incidentally I would like to share my views on oGet:Changed. This such a handy feature that we are tempted to use this value to determine if our user has changed the data. But this can be dangerously misleading. Every time a Get gets focus, the oGet;Changed is reset to .f. The user might have edited the data once and might have gone back to the same get and did not modify this time. oGet:changed shows .f.

Regards



G. N. Rao.

Hyderabad, India
Posts: 6983
Joined: Fri Oct 07, 2005 07:07 PM
Re: Checking for updated fields
Posted: Fri Jun 19, 2009 05:37 AM

Hello Mr. NagesWaraRao,

would you please show how you compare to arrays.
I always use a FOR-NEXT statement. Is there a better way?
Thanks in advance
And best regards,
Otto

Posts: 1467
Joined: Mon Oct 10, 2005 11:26 AM
Re: Checking for updated fields
Posted: Fri Jun 19, 2009 12:43 PM
I have solved this problem many years ago, even already in my Clipper times.

I always use this kind of code :

Code (fw): Select all Collapse
LOCAL cField1,cField2,cField2
LOCAL cUpdate := .F.
.................
cFIELD1 := DBF1->FIELD1
cFIELD2 := DBF1->FIELD2
cFIELD3 := DBF1->FIELD3
.................
DEFINE DIALOG ........
REDEFINE GET cFIELD1 ID 101 OF oDlg
REDEFINE GET cFIELD2 ID 102 OF oDlg
REDEFINE GET cFIELD3 ID 103 OF oDlg
ACTIVATE DIALOG ........
.................
IF !(cFIELD1 = DBF1->FIELD1 .AND. ;
     cFIELD2 = DBF1->FIELD2 .AND. ;
     cFIELD3 = DBF1->FIELD3)
    cUPDATED := .T.
ENDIF

IF cUPDATED
   DBF1->FIELD1 := cFIELD1
   DBF1->FIELD2 := cFIELD2
   DBF1->FIELD3 := cFIELD3
ENDIF


You could make a cUPDATED for each field if you want to know which fields are updated.

Good luck.

Regards,

Michel D.
Genk (Belgium)


_____________________________________________________________________________________________

I use : FiveWin for (x)Harbour v. 25.12 - Harbour 3.2.0 (May 2025) - xHarbour Builder (January 2020) - Bcc773

Posts: 10733
Joined: Sun Nov 19, 2006 05:22 AM
Re: Checking for updated fields
Posted: Fri Jun 19, 2009 04:17 PM

Mr Otto

>
I always use a FOR-NEXT statement. Is there a better way?
>

I also do the same thing. I think this is the best way I can think of.

Regards



G. N. Rao.

Hyderabad, India

Continue the discussion