@isvalid isn't working - help please!

I’ve done this in other applications, so I know it should work - but for this one, it doesn’t. My field validation formula for the Project field looks like this:

@If(Validate=“Y” & Sequence=21 & Project=“”;@Failure(“Please select a Project.”);@Success)

I set the Validate flag in my Save action button, which runs this formula:

FIELD Validate:=“Y”;

@Command([ViewRefreshFields]);

@If(@IsValid;“”;@Return(“”));

FIELD Validate:=“”;

@Command([ViewRefreshFields]);

I have a @prompt after this code which shows me the seq is indeed 21, and it always executes. I even made the field validation formula a simple @failure(…) and although I seen the failure message, the Save code continued to execute.

What am I missing??? I have 2 separate forms with the same problem. Is there a form property or db property I’m overlooking?

aargh! This is driving me nuts - spending time on something that should be so simple…

Any ideas?

Subject: @isvalid isn’t working - help please!

I would remove the Validate field and associated logic. The way you have it coded it is redundant and it might be blowing up the @if in the project field if the value change isn’t being handled the way you think. I don’t really use the Field Validation events. I usually code all validation into the querysave event. This helps prevent users from bypassing button logic by hitting control-S etc… Which is another reason to remove the Validate logic, currently even if it worked as you expected, if your validate field is != “Y”, a control-S save will bypass your validation.

Good luck!

Lee.

Subject: RE: @isvalid isn’t working - help please!

I use the flag because I actually have 2 action buttons - ‘Save & Close’ and ‘Submit for Processing’. I allow the user to Save the document without doing any validation. This keeps the doc at their workstep. But, when they use the Submit button, then I validate before assigning the doc to the next user.

Subject: @isvalid isn’t working - help please!

I would suggest that you do the Validation in the QuerySave event, and only run it if Validate=“Y”:

In the Save button:

@Command([FileSave]);

In the submit button:

FIELD Validate:=“Y”;

@Command([Filesave])

Subject: RE: @isvalid isn’t working - help please!

Is this really how it should work? - because my save and submit buttons do other things before I actually save the document. Save is the last thing I do and I don’t want to update other fields if, when I get to the querysave, the document cannot be saved with the validate flag set. Then I’ve changed fields erroneously, and the user can still save the doc with the ‘save & close’ button avoiding the validate flag…

I’m sure I have other applications out there using @isvalid in a submit button and they are working.

Have I been doing it wrong all along? Does this just work sometimes because its not designed to work in an action button?

Subject: RE: @isvalid isn’t working - help please!

The answer I gave is in the context you posted (i.e. limited code).

A rile of thumb I have had beaten into my thick head and that I still adhere to is there shouuld never be more than thrree or so lines of code behind a button. All that a button should do is call a script library subroutine to do stuff.

The QuerySave event can do your stuff and then do the validation. To me, the advantage of doing the validation in the QuerySave is that I have all the validation code in one place and do not overload the form load with code.

Subject: repost - I guess this is too much code then…

“Submit for Processing” action button:

REM {for normal processing};

FIELD Validate:=“Y”;

@Command([ViewRefreshFields]);

@If(@IsValid;“”;@Return(“”));

FIELD Validate:=“”;

@Command([ViewRefreshFields]);

REM {make sure the part attributes are set};

@If(Sequence=21 & BOMPartName_1=“”;@Prompt([Ok];“Missing Information”;“Please Set the Attributes for the New Part Number.”);@Success);

@If(Sequence=21 & BOMPartName_1_1=“”;@Prompt([Ok];“Missing Information”;“Please Set the Attributes for the New Assembly Number.”);@Success);

@If(Sequence=21 & (BOMPartName_1=“” | BOMPartName_1_1=“”);@Return(“”);@Success);

REM {if at apqp, make sure warrant has been signed};

@If(CurrentSection=“[APQP]” & QResults!=“Failed” & (DateWarrantS=“” | WarrantCh=“” | WarrantCh=“None”);@Prompt([Ok];“Submit for Processing”;“This Change cannot be submitted to Sales without a Warrant response from the Customer.”);@Success);

@If(CurrentSection=“[APQP]” & QResults!=“Failed” & (DateWarrantS=“” | WarrantCh=“” | WarrantCh=“None”);@Return(“”);@Success);

REM {update field};

@If(Sequence<23;@Do(@SetField(“OrigFARAreas”;FARAreas);@SetField(“OrigFeasDeptList”;FeasDeptList));“”);

REM {save comments};

user:=@Name([CN];@UserName);

init:=@Left(user;1)+“.”+@RightBack(user;" ");

stamp:=@Text(@Now;“D1T1”)+" “+init+” ";

cmt:=stamp+Comments;

newval:=@If(cmpComments=“”;cmt;cmpComments:cmt);

@If(Comments=“”;“”;@SetField(“cmpComments”;newval));

@SetField(“Comments”;“”);

REM {save notes and assumptions};

note:=stamp+Notes;

newval:=@If(cmpNotes=“”;note;cmpNotes:note);

@If(Notes=“”;“”;@SetField(“cmpNotes”;newval));

@SetField(“Notes”;“”);

REM {set a flag to assign the doc number};

FIELD SetNum:=SetNum;

@If(@IsNewDoc & NumT=“”;@SetField(“SetNum”;“Y”);@SetField(“SetNum”;“”));

REM {@If(@IsNewDoc & NumT=“”;@Command([RunAgent];“(AssignNumber)”);“”)};

REM {notify salesman if new result is entered};

REM {set email parameters};

sendto:=Salesman;

cclist:=“”;

subject:=WFText+" - PPAP Results";

remark:=@Name([CN];@UserName)+" has updated this Change with PPAP Results=“+QResults+”. Open the PLT System for further details.";

@If(QResultsin=QResults | Salesman=“”;“”;@MailSend(sendto;cclist;“”;subject;remark;“”));

REM {also check for ppap update to itemas};

@If(QResultsin=QResults;“”;QResults=“Passed” | QResults=“Not Required”;@Command([RunAgent];“(PPAPUpdate)”);“”);

REM {update the review log};

note:=“PPAP Results recorded as “+QResults+” by “+@Name([CN];@UserName)+” on “+@Text(@Today;“S0D0”)+” at “+@Text(@Now;“S1T1”)+”.”;

note2:=“PPAP Result Notification sent to “+@Name([CN];Salesman)+” on “+@Text(@Today;“S0D0”)+” at “+@Text(@Now;“S1T1”)+”.”;

update:=@If(ReviewLog=“”;note;ReviewLog:note:note2);

@If(QResultsin=QResults | Salesman=“”;“”;@SetField(“ReviewLog”;update));

@Command([ViewRefreshFields]);

@If(CurrentSection=“[APQP]” & QResults=“Failed”;@Command([ToolsRunMacro];“(Review Rejected)”);@Command([ToolsRunMacro];“(Review Completed)”))

Subject: Than this must be too much code…

“Submit for Processing”

REM {for normal processing};

FIELD Validate:=“Y”;

@Command([ViewRefreshFields]);

@If(@IsValid;“”;@Return(“”));

FIELD Validate:=“”;

@Command([ViewRefreshFields]);

REM {make sure the part attributes are set};

@If(Sequence=21 & BOMPartName_1=“”;@Prompt([Ok];“Missing Information”;“Please Set the Attributes for the New Part Number.”);@Success);

@If(Sequence=21 & BOMPartName_1_1=“”;@Prompt([Ok];“Missing Information”;“Please Set the Attributes for the New Assembly Number.”);@Success);

@If(Sequence=21 & (BOMPartName_1=“” | BOMPartName_1_1=“”);@Return(“”);@Success);

REM {if at apqp, make sure warrant has been signed};

@If(CurrentSection=“[APQP]” & QResults!=“Failed” & (DateWarrantS=“” | WarrantCh=“” | WarrantCh=“None”);@Prompt([Ok];“Submit for Processing”;“This Change cannot be submitted to Sales without a Warrant response from the Customer.”);@Success);

@If(CurrentSection=“[APQP]” & QResults!=“Failed” & (DateWarrantS=“” | WarrantCh=“” | WarrantCh=“None”);@Return(“”);@Success);

REM {update field};

@If(Sequence<23;@Do(@SetField(“OrigFARAreas”;FARAreas);@SetField(“OrigFeasDeptList”;FeasDeptList));“”);

REM {save comments};

user:=@Name([CN];@UserName);

init:=@Left(user;1)+“.”+@RightBack(user;" ");

stamp:=@Text(@Now;“D1T1”)+" “+init+” ";

cmt:=stamp+Comments;

newval:=@If(cmpComments=“”;cmt;cmpComments:cmt);

@If(Comments=“”;“”;@SetField(“cmpComments”;newval));

@SetField(“Comments”;“”);

REM {save notes and assumptions};

note:=stamp+Notes;

newval:=@If(cmpNotes=“”;note;cmpNotes:note);

@If(Notes=“”;“”;@SetField(“cmpNotes”;newval));

@SetField(“Notes”;“”);

REM {set a flag to assign the doc number};

FIELD SetNum:=SetNum;

@If(@IsNewDoc & NumT=“”;@SetField(“SetNum”;“Y”);@SetField(“SetNum”;“”));

REM {@If(@IsNewDoc & NumT=“”;@Command([RunAgent];“(AssignNumber)”);“”)};

REM {notify salesman if new result is entered};

REM {set email parameters};

sendto:=Salesman;

cclist:=“”;

subject:=WFText+" - PPAP Results";

remark:=@Name([CN];@UserName)+" has updated this Change with PPAP Results=“+QResults+”. Open the System for further details.";

@If(QResultsin=QResults | Salesman=“”;“”;@MailSend(sendto;cclist;“”;subject;remark;“”));

REM {also check for ppap update to itemas};

@If(QResultsin=QResults;“”;QResults=“Passed” | QResults=“Not Required”;@Command([RunAgent];“(PPAPUpdate)”);“”);

REM {update the review log};

note:=“PPAP Results recorded as “+QResults+” by “+@Name([CN];@UserName)+” on “+@Text(@Today;“S0D0”)+” at “+@Text(@Now;“S1T1”)+”.”;

note2:=“PPAP Result Notification sent to “+@Name([CN];Salesman)+” on “+@Text(@Today;“S0D0”)+” at “+@Text(@Now;“S1T1”)+”.”;

update:=@If(ReviewLog=“”;note;ReviewLog:note:note2);

@If(QResultsin=QResults | Salesman=“”;“”;@SetField(“ReviewLog”;update));

@Command([ViewRefreshFields]);

@If(CurrentSection=“[APQP]” & QResults=“Failed”;@Command([ToolsRunMacro];“(Review Rejected)”);@Command([ToolsRunMacro];“(Review Completed)”))

Subject: Oh lordy…

wayyyy too much, a lot of which could be consolidated into a script Libray or a single agent.

Subject: Thanx, but…

what exactly are the advantages - besides maybe getting my validation formulas to work? Is there another downside to what I’m doing - or is it just considered ‘poor coding ethics’?

Subject: RE: Thanx, but…

The adavantages (again other may differ on this view):

  1. Better form performnace as there is less code to load.

  2. Resuseability and portability of code.

  3. An easier time getting rid of all the hard coded stuff you have in the code. (messages, etc).

As far as I am concerened, if you just put all of this code into an agent as is and called the agent, you have done yourself some good.

While this may be an extreme example, I inherited an application almost 2 years ago that had 27 action buttons on it to process a workflow, all with about 100 lines of identical code. It was a performance dog and 1/2.

I took all the code and consolidated it into one script library and elminated 26 of the 27 buttons. I got rid of hard coding, made the code more flexible, and increased performance response times significantly.

How many times have you refreshed the doc in your code?

Subject: advantages

That sounds like some pretty good reasons to revamp my strategy. Thanx for the advice and your attentive responses.

Did you see my post about where to put the validation formulas?

Subject: where do you put the validation formula?

Am I supposed to leave the validation formula in the field validation event? - or put it in the querysave event? Does @failure work in querysave? - or would I have to just use @prompt?

Subject: Example of QuerySave validation

In this example, all of the required fields are stored in a workflow profile document that is looked up to based on the given state of a document. This example is before I have moved the validation to a script library, hence the length of the code:

Sub Querysave(Source As Notesuidocument, Continue As Variant)

'GET A HANDLE ON THE CURRENT DOCUMENT

Dim session As New NotesSession

Dim ws As New NotesUIWorkspace

Dim uidoc As NotesUIDocument

Dim doc As NotesDocument

Set db=session.currentdatabase

Set uidoc=ws.currentdocument

Set doc=uidoc.document

Dim strUserAbbreviate As String

Dim strName As String

Dim success As Variant

Dim vRequired As Variant

'GET A HANDLE ON THE DEFAULT WORKFLOW PROFILE DOCUMENT FOR THIS APPLICATION

Dim docWFDefaults As NotesDocument

Set docWFDefaults= getFirstDocument

(db, “luvaWFActors”)

'GET A HANDLE ON THE ACTION BEING PROCESSED

Dim strDocState As String

strDocState=uidoc.FieldGettext(“DocumentState”)

'GET A HANDLE ON THE NEWLY SELECTED ACTION SO THAT THE APPROPRIATE WORFLOW MANAGEMENT DOCUMENT CAN BE SELECTED

Dim strDocowner As String

strDocOwner=uidoc.FieldGetText(“DocumentOwner”)

'CALL THE getSelectedAction FUNCTION FROM THE SCRIPT LIBRARY TO GET THE VALUE FOR THE CURRENT ACTION bEING PROCESSED

Dim strSelectedAction As String

strSelectedAction=getSelectedAction (db, doc,

docWFDefaults, strDocState, strDocOwner,

strSelectedAction)

If strSelectedAction=“” Then

Messagebox (“You must select an action”)

continue=False

Exit Sub

End If

'THIS SECTION IS ONLY APPLICABLE TO ACTION 1

Dim strApplication As String

strApplication=uidoc.FieldGettext(“Application”)

If strApplication=“ApplicationName” Then

If strSelectedAction="Request Sent to

Production System" And 

doc.CIOApprovedFlag(0)="" Then

Messagebox ("This must be sent to the CIO

  for approval before it can be sent to   

  production.")

continue=False

Exit Sub

End If

If doc.tmpPriorAction(0) <> "Request

Successful on error checking System by

  Requester" And strSelectedAction=

   "Request Sent To CIO for Approval" Then

Messagebox ("This action cannot be sent to

the CIO until you have been notified by the

PM that it is ready for production.")

continue=False

Exit Sub

End If

End If

'GET THE WORKFLOW DOCUMENT ASSOCIATED WITH THE NEWLY SELECTED ACTION

If (strDocState <> strSelectedAction) Then

Dim docNewWorkflow As NotesDocument

Call GetWorkflowDocument(db, docNewWorkflow,

strSelectedAction )

If Not (docNewWorkflow Is Nothing) Then

Print(“Worflow Document Opened”)

'VALIDATE REQUIRED FIELDS ON THE REQUEST INFORMATION TAB OF THE FORM. IN ORDER TO MIMIC THE BEHAVIOR 'OF A QUERY SAVE AGENT, THE ROUTINE HAS BEEN WRITTEN THIS WAY

If strSelectedAction=

docWFDefaults.admWFDefaultAction(0) Then

Call CreateUserProfile(uidoc)

If Not (docNewWorkflow.HasItem

(“admValidateText”)) Then

Print(“admValidateText not found”)

Else

Dim strField As String

Dim strErrorMessage As String

vRequired=docNewWorkFlow.GetItemValue

("admRequiredFields")

Forall f In vRequired

strField=f

strErrorMessage="You must enter a value for

  the following field: " & strField

Call validateField (f, uidoc,

   strErrorMessage, continue)

				 

If Continue=False Then

Exit Sub

End If

etc etc

Subject: Thank you so much for all your help!

Subject: @isvalid isn’t working - help please!

In your validation formula use @return(“message prompt”) instead of @failure. @failure will prompt them fine, but as you have experienced, it will not stop executing the rest of the code.

So using your example:

Field Validation Formula - @If(Validate=“Y” & Sequence=21 & Project=“”;@Return(“Please select a Project.”);@Success)

Save action button, which runs this formula: FIELD Validate:=“Y”;

@Command([ViewRefreshFields]);

@If(@IsValid;“”;@Return(“”));

FIELD Validate:=“”;

@Command([ViewRefreshFields]);

@PostedCommand([FileSave]);

@PostedCommand([FileCloseWindow]);

The @return will stop the execution of the code when the validation formula doesn’t pass.

Subject: @return gives me the same result

I replaced the @failure with @return in the validation event formula for the Project field and I get the same result. I see the message, and the code continues. ??

Subject: RE: @return gives me the same result

Here is code from a save button, where this is working properly.

@If(@IsValid;@Success;@Return(“”));

FIELD ChkField:=“1”;

@Command([FileSave]);

@Command([FileCloseWindow])

The input validation formula on this form looks like this.

@If(Eff_dt = “”; @Return(“You must enter an Effective date”); @Success)

I would try to simplify your condition statement and put things in one at a time. Something is not evaluating correctly in your formula.