Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
GetNextModified and GetFldState don't agree
Message
Information générale
Forum:
Visual FoxPro
Catégorie:
Autre
Divers
Thread ID:
01222033
Message ID:
01222185
Vues:
15
But, if you use views, you CAN check if a field WAS defaulted.
***************************************************************************
*!*	Method:			IsRecChanged
*!*	Purpose:		Determine if changes are pending for a record
*!*	Author:			bxk 10.15.01
*!*	Parameters:		tcAlias
*!*	Returns:
*!*	Modifications:	08.20.03 bxk Exit from loop if change detected
***************************************************************************
LPARAMETERS tcAlias

LOCAL i, lnFields, laFields[1], lcFldState, lcChr, lcAlias, llRetval, ;
	lcSaveAlias, lcName

STORE 0 TO i, lnFields
STORE SPACE(0) TO laFields[1], lcFldState, lcChr, lcAlias, lcSaveAlias, ;
	lcName
STORE .F. TO llRetVal

ASSERT !EMPTY(lcAlias) ;
	MESSAGE 'IsRecChanged() requires the alias of an open table be passed'

lnBuffMode = CURSORGETPROP('buffering', lcAlias)
IF lnBuffMode < 2
	*!* Bail if buffering not enabled
	RETURN .F.
ENDIF

lcSaveAlias = ALIAS()
SELECT (lcAlias)

lcFldState = GETFLDSTATE(-1, lcAlias)

lnFields = AFIELDS(laFields, lcAlias)
FOR i = 1 TO lnFields

	*!* If field hasn't been defaulted
	IF EMPTY(laFields[i, 9])

		*!* If the field has been changed
		*!* remember, the first chr in lcFldState is the delete flag
		lcChr = SUBSTR(lcFldState, i + 1, 1)
		IF lcChr $ '2,4'

			*!* get field name
			lcName = laFields[i, 1]

			*!* See if user changed, then reverted field
			*!* Check for .NULL., appended records return .NULL. for oldval
			llRetVal = NVL(EVAL(lcName) != OLDVAL(lcName, lcAlias), .T.)
			
			*!* Found a change, we can exit
			IF llRetVal
				EXIT
				
			ENDIF	
			
		ENDIF

	ENDIF

ENDFOR

IF !EMPTY(lcSaveAlias)
	SELECT (lcSaveAlias)
	
ELSE
	SELECT 0
ENDIF

RETURN llRetVal
Our defaulted fileds are not user editable, so we don't check to see if they were changed

Bruce

>Thanks, Marcia. I've known about this issue for awhile and it's one reason I don't use default values a lot when setting up a table structure.
>
>However, this case is different. First, it did not do this until recently after moving them from VFP 8 (SP 1 maybe) to VFP 9 SP 1. Not sure that's truly related, but it's something to note. Additionally, this is not a case of adding a new record. It just occurs when you move between preexisting records on which no changes have been made.
>
>It's been fixed in the sense that it will not incorrectly give the message anymore (due to the CheckEachRecord feature in my framework), but - behind the scenes - it thinks there is a change until it goes to the supposedly changed record and GetFldState determines GetNextModified was lying.
>
>BTW, I don't scan the table/view, I only check the records that GetNextModified has indicated are changed.
>
>
>>This is what I had to say on the subject in a conference session that I did called "It Seemed Like a Good Idea at the Time":
>>
>>When SetFldState() Doesn’t Work as Expected (Example: SetFldStateProblem.scx and FixFldStateProblem.scx)
>>
>>In the previous section, I discussed how using default values can be the source of problems when using views. They can also be the source of some minor irritation to our end users if our application does not handle them properly. Take, for example, the case where the user clicks on the “Add” button in a form and then changes his mind. He may decide to navigate to a new record or to close the form. If the underlying data uses default values, and you have a routine that checks for pending changes in order to prompt the user to save them, this routine will see the newly appended record as having changes and display the prompt. This is, understandably, confusing because the user did not make any changes. This is also a problem any time we force a bound combo box to display a specific value with a command like this:
>>
>>
>>Thisform.cboCountries.ListIndex = 1
>>
>>
>>The problem is that this makes a change to the underlying data and could then trigger a ‘do you want to save changes’ message. So what can be done about it? Fortunately, we can use SETFLDSTATE() to reset the field state flag so that the changes made by inserting default values are no longer seen as changes. Or can we?
>>
>>Suppose our form has a data entry grid on it and we want to either commit or discard all of the changes made to the data in the grid. We could put code like this in our “Add” method to ensure that the default value inserted for the primary key is not later seen as a change:
>>
>>
>>APPEND BLANK IN Clients
>>*** make sure we do not see default values as changes
>>SETFLDSTATE( 'iClientPK', 3, 'Clients' )
>>
>>
>>We could then use code like this in our method that checks for pending changes and prompt the user to save if any are found:
>>
>>
>>LOCAL lnModified, lnAnswer
>>*** see if we have pending changes
>>lnModified = GETNEXTMODIFIED( 0, 'Clients' )
>>IF lnModified # 0
>>  GO lnModified IN Clients
>>  *** If so, see if they want to save
>>  lnAnswer = MESSAGEBOX( 'Do You Want to Save Your Changes?', 3, 'Pending Changes' )
>>  IF lnAnswer = 6   && Yes
>>    Thisform.DoSave()
>>  ELSE
>>    IF lnAnswer = 7  && No
>>      TABLEREVERT( .F., 'Clients' )
>>    ELSE  && Cancel
>>      RETURN .F.
>>    ENDIF
>>  ENDIF
>>ELSE
>>  *** We may have a new and empty record here
>>  *** so let's tablerevert. If there are no changes
>>  *** it doesn't hurt anything
>>  TABLEREVERT( .F., 'Clients' )
>>ENDIF
>>
>>
>>There is just one small technical problem here. You cannot use GETNEXTMODIFIED() to get the job done because it still thinks that record has pending changes! You can prove this to yourself by checking for
>>
>>
>>GETFLDSTATE( -1, ‘Clients’ )
>>
>>
>>Immediately after the line
>>
>>
>>GO lnModified IN Clients
>>
>>
>>GETFLDSTATE() returns a string of 3’s.
>>
>>So, if you have a process that needs to find all of the pending changes in a table or a cursor, and you have used SETFLDSTATE() to reset the field state flags on some records that you do not want to process, you cannot rely on GETNEXTMODFIED() to do the job. Instead, you have to scan the table and use GETFLDSTATE() to check each record for pending changes.
Précédent
Suivant
Répondre
Fil
Voir

Click here to load this message in the networking platform