Solved

Need help Converting @functions to LS for submit and validation button

Posted on 2006-11-15
22
582 Views
Last Modified: 2013-12-18
I would like some suggested solutions to the following problem.

I have an applcation that uses a 3rp party workflow engine in it ( See wfs.com )

The problem is that I need 2 buttons to complete any document.
The first does a Validation and saves it, and the second submits it to the Workflow Engine.

I would like a way to make sure that the Valdation is done before calling the submit button or as part of it.
Also, I will need to change the submit button everytime I get a newer version of the template ( quarterly ), so It must be something consistent
I have status fields that can be used if needed to notify when a Save is done, but more importantly I need a validation done during the Submit button action.

It looks like I will need to convert the formlas to LS and work from there.
Any suggestions welcome.

Validation code is in a script library.

Here is the code for both.
 Save button
Sub Click(Source As Button)
            
      Dim w As New NotesUIWorkspace
      Set uidoc = w.CurrentDocument
      
      Set S= New NotesSession
      
      Set VLdoc=uidoc.Document      
      Set CurDb = S.CurrentDatabase
      s_form=VLdoc.GetItemValue("StFormName_h_cc")(0)  ' need field that is computed when composed with Form name
'      
      ii=   ValidateFieldsviaForm( VLdoc, s_form, curdb)
      If ii=False Then
'            Continue=False ' not used
      Else
            Call uiDoc.Save '

      End If
      
End Sub

Submit button from WFS template
FIELD ACAction := "Submit";
Continue := @If(@IsDocBeingEdited;@Command([FileSave]);@True);
@If(Continue;@Command([ToolsRunMacro];"(AC Submit)");"")

Querysave justs sets a status field

      Dim doc As notesdocument
      
      Dim  s_key1 As String, S_key2 As String, d_stat As String , s_DeptLU As String, strFrmName As String , s_Ptype As String
      
      d_stat= source.fieldgettext("t_DocStat")
      
      Select Case  Ucase ( d_stat)  
      Case "NO", "DRAFT" :
             
'            Else
            Call source.FieldSetText       ( "t_DocStat", "OK" )
      
      '      End If
      Case "OK" :
            
      End Select
End Sub

Thanks in advance !
0
Comment
Question by:SysExpert
  • 10
  • 7
  • 5
22 Comments
 
LVL 8

Expert Comment

by:behenderson
ID: 17959644
It is not clear but my guess is that you like @Formula Language and the darn button on the form was written in script so you did not want to change or alter it so you created a second button.  Is that correct?  If so you are already using a good solution in the button now.   @ToolsRunMacro.  You could put that pesky script code into an agent and then call it from a @Formula language button using @ToosRunMacro

BUT you have a problem...  There is more code in that button than you are seeing at first glance.   LotusScript buttons have different code sections in them  One Section is The Options section  See if you can find it in the button.. Another section might (But not necessarily) be  Function ValidateFieldsviaForm( VLdoc as NotesDocument, s_form as String, curdb as NotesDatabase) as Variant.  The function probably won't be there if you see something in the Options section.  If you can find all the code you can copy it in the correct section of an agent and call the agent using ToolsRunMacro...  I can even show you how to have one of the LotusScript Agents call the other agent you are calling using ToolsRunMacro... But you need to post all the code first


 
0
 
LVL 63

Author Comment

by:SysExpert
ID: 17962349
Actually it is almost the other way around.

I prefer LS not @functions, but the Workflow Engine used @functions in the Submit button subform.

The validate routine is LS  and is in the script library.

I still would like a way to convert the SUbmit button @function to LS.

Thanks !
0
 
LVL 8

Expert Comment

by:behenderson
ID: 17962472
Well that is easier to work with.. I prefer script as well and if you are using a library I won't have to spend a lot of time explaining

Submit button from WFS template
FIELD ACAction := "Submit";

First I would create a function to trap the results of UIDoc.Save

Function DidUIDSave( uidoc as NotesUIDocument ) as Variant
DidUIDSave = true
On error Goto errTrap
Call uidoc.Save
done:
exit function
errTrap:
DidUIDSave = false
resume done
End Function

Then you can simulate the @If( @Command([Filesave]) with it

So This:
Continue := @If(@IsDocBeingEdited;@Command([FileSave]);@True);
@If(Continue;@Command([ToolsRunMacro];"(AC Submit)");"")

Becomes This:

Dim sess as NotesSession
dim db as NotesDatabase
Dim ws as NotesUIWorkspace
dim uidoc as NotesUIDocument
dim doc as NotesDocument
dim agtAcSubmit as NotesAgent
dim strNoteID as String
set ws = new NotesUIWorkspace
set uidoc = ws.CurrentDocument
if uidoc.EditMode Then
   If DidUIDSave( uidoc ) Then
      Set sess = New NotesSession
      set db = sess.CurrentDatabase
      Set agtAcSubmit = db.GetAgent("(AC Submit)")
      Set doc = uidoc.Document
      strNoteId = doc.Noteid
      Call agtAcSubmit.Run(strNoteID)
   End If
End If
0
 
LVL 8

Expert Comment

by:behenderson
ID: 17962509
Correction... That agent runs if the uidoc is not in edit mode or if it saves ok..

(Function gets pasted into declarations section)

Function DidUIDSave( uidoc as NotesUIDocument ) as Variant
  DidUIDSave = true
  On error Goto errTrap
  Call uidoc.Save
done:
  exit function
errTrap:
  DidUIDSave = false
  resume done
End Function

Sub Click(Source As Button)
  Dim sess as NotesSession
  dim db as NotesDatabase
  Dim ws as NotesUIWorkspace
  dim uidoc as NotesUIDocument
  dim doc as NotesDocument
  dim agtAcSubmit as NotesAgent
  dim strNoteID as String
  dim vRunAgent as Variant
  vRunAgent = false
  set ws = new NotesUIWorkspace
  set uidoc = ws.CurrentDocument
  if uidoc.EditMode Then
     If DidUIDSave( uidoc ) Then
        vRunAgent = True
     End If
  Else
     vRunAgent = True
  End If
  if vRunAgent Then
      Set sess = New NotesSession
      set db = sess.CurrentDatabase
      Set agtAcSubmit = db.GetAgent("(AC Submit)")
      Set doc = uidoc.Document
      strNoteId = doc.Noteid
      Call agtAcSubmit.Run(strNoteID)
  End If
End Sub
0
 
LVL 8

Expert Comment

by:behenderson
ID: 17962520
And lose the strNoteID if it is not R5.02 or higher...
0
 
LVL 63

Author Comment

by:SysExpert
ID: 17968107
behenderson ,

Thanks, I will start testing Monday.

BTW. I am in a mixed R 6.5 and R 7.02 enviroment with some Users still on R5 clients but beiing upgraded.

0
 
LVL 18

Assisted Solution

by:marilyng
marilyng earned 100 total points
ID: 17975612
Another thought.. why not just  call the validation from the querysave  and then set the continue = false?

I use an actioninprogress field, similar to what the Notes Mail Script Library uses.  Each button I press then passes the constant actioninprogress - set in Library under instantiatevariablesUI.

Some of my constants are:

const SaveContinue=21
Const NoSave=20
Const SaveClose=22
Const ADMINAPPROVEYES=40

My buttons, then, are very simple:

FIELD actioninprogress :=21;

@if(@Command([FileSave]);@Do(
{Set whatever values you need};
@SetField("ActionInProgress";nextvaluenumber););"")


When I get to the querysave event, I grab the actioninprogress value and call the validation Function:

continue =  Validation(session,db,ws,uidoc,actioninProgress)

Function Validation(thisSession as NotesSession, thisDb as Notesdatabase, thisWs as NotesUIworkspace, thisuiDoc as NotesDocument,thisAction as Integer) as boolean
  Dim thisDoc as NotesDocument
  set thisDoc = thisUidoc.document

    SelectCase thisAction
        case 21
           'do this
           'do that
     end select

'destroy thisDoc
set thisDoc = nothing
...etc.

the form, also uses the script library i.e. Use "CommonUI"  and instantiates the constants during the initialize step.
 

----------
Don't know about you, but I really hate searching under buttons and events to debug a bug..  so, all my actions are shared, simple buttons that call script libraries.   I usually don't put any code in the events, either, I just call the script library event.

My validation fields I put into  a field on the form:

fldValidation
   "FieldName|Field Label|Validation Constant|Field Type"
   "Name|Customer Name|NotEmpty|String"
   "Address|Customer Address|NotEmpty|String"

then all I have to do in the validation section is loop through the array, split the index to get the field name, field title, what I'm testing for and the field type.

This way my validation code stays the same for every database and all I do is loop through a form field to see what I want to check

0
 
LVL 8

Expert Comment

by:behenderson
ID: 17977022
It is a great coding practice to put all the field validations in script from a debug perspective, and it also requires less effort to maintain especially if the form is poorly documented.  A script library is great to re-use.  That looks like a great logical way to handle field validation.

But there are still reasons to use Formula Language.  In my environment there is a delegation of work and my co-workers do well in formula language and not in script.  Formula language is almost always faster than script and in huge forms that can make a difference.  There are a lot of databases that I hardly ever have to look at and the formula language fanatics can handle them just fine.  

And should the maintanance of the database move to another area it is most likely that the only time they will bug me is with script questions. I get to spend part of my time coding and part of my time teaching others to code and when they finally get proficient they are gone.  DidUIDSave has been very helpful in trapping the results of the save, but you are right once that result comes back negative if you don't know why be prepared to work.
0
 
LVL 63

Author Comment

by:SysExpert
ID: 17979623
marilyng : Thanks for the advice, and normally this would be the correct way of handling it, but I need to have the option of saving the form even if it does NOT pass the validation checks, so QuerySave is out. I have all validations in one script Library and everything is well documented. No per field validations, just global ones called via the Save button.

behenderson : I will try testing your solution today.

Thanks for all your great suggestions !

0
 
LVL 18

Expert Comment

by:marilyng
ID: 17980392
Whatever works for you..  however, your logic escapes me.   You can continue=true or continue = false in the QS event without having to change the buttons to script.

But, like I said, it's your application. :)
0
 
LVL 8

Accepted Solution

by:
behenderson earned 400 total points
ID: 17981981
Marilyng  I do not believe that he wants two buttons he wants one.  My logic on using formula language was in reference to what I thought was your advice of putting all field validations into script.  My code above is simply the part that translates the formula language in the button to script which was in response to the question title: 'Need help Converting @functions to LS for submit and validation button.'  That title lead me to believe that he wanted to combine the two buttons but wanted clarification on the conversion of one of them.

The code I included only translated the Formula language into script @If(@IsDocBeingEdited;@Command([FileSave]);@True); and translating the formula language is the only part that I think SysExpert needed feedback on.  I looked at his profile after my first comment (which really underestimated his level) and I realized that he probably could figure it out with just the DidUIDSave function that I use to trap the results of a uidoc.save, to replace the @Command([FileSave]) evaluating to true in the formula language example.  The nice thing about the DidUIDSave function is that if the uidoc does not save correctly the user will get the Prompts from the field validation formulas and you can abort the rest of the code.  I did not combine the validate button with the submit button because I figured SysExpert would to that just fine on his own.  If I had bothered to combine the two it would look like this (assuming DidUIDSave is added as well):

  Dim S as NotesSession
  dim db as NotesDatabase
  Dim ws as NotesUIWorkspace
  dim uidoc as NotesUIDocument
  dim doc as NotesDocument
  dim agtAcSubmit as NotesAgent
  dim strNoteID as String
  dim vSavedOK as Variant
  dim s_form as String
 
  vRunAgent = false
  set w = new NotesUIWorkspace
  set uidoc = w.CurrentDocument
  if uidoc.EditMode Then
     If DidUIDSave( uidoc ) Then
        vSavedOK = True
     Else
        ' Possible messagebox here.
       Exit Sub
     End If
  Else
     vSavedOK = True
  End If
  if vSavedOK Then
      Set S = New NotesSession
      set CurDb = S.CurrentDatabase
      Set VLdoc=uidoc.Document
      s_form=VLdoc.GetItemValue("StFormName_h_cc")(0)
      ii=   ValidateFieldsviaForm( VLdoc, s_form, Curdb)
      If ii Then
          Set agtAcSubmit = CurDb.GetAgent("(AC Submit)")
          Set doc = uidoc.Document
          strNoteId = doc.Noteid
          Call agtAcSubmit.Run(strNoteID)
      End If
  End If

As you can probably see the DidUIDSave Preceeds the rest of the code so if it were sitting in the querysave it would not do it in the right order.  The code probably does that to prevent the AC Submit Agent from choking on a bad save.  I did not want to imply that the suggestion of handling field validation in script was bad, but I don't think it is ALWAYS the best solution either.
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 18

Expert Comment

by:marilyng
ID: 17983262
Well shucks, I was adding a friendly alternative solution, as per the EE rules.  beHenderson, when you get a moment, please read: http://www.experts-exchange.com/help.jsp#hs4.

0
 
LVL 8

Expert Comment

by:behenderson
ID: 17983863
My mistake

The comment 'Whatever works for you..  however, your logic escapes me.' must have not been directed at me or it was rhetorical and you did not want any commentary on it.  I am not sure which specific part of the Answering Questions section you were bringing to my attention, but I believe that you may have felt that the explanation of my logic was critical of you.  From what I see you are intelligent and have helped a lot of people with a lot of good suggestions.  The use of the actioninprogress field looked interesting When I made the comment: 'It is a great coding practice to put all the field validations in script from a debug perspective, and it also requires less effort to maintain especially if the form is poorly documented.  A script library is great to re-use.  That looks like a great logical way to handle field validation.' I thought I was engaging in a little friendly dialogue.   You seem like an interesting and intelligent person with a good deal of notes knowledge.  I thought that the comment I made previous to the 'Aw shucks" comment was a pretty straightforward explanation of the logic that I used from my first post on, and again the only reason I posted it was in response to the 'Whatever works for you..  however, your logic escapes me.'  comment.  I assumed that somehow there was content in my post that really made no sense to you.  You have many great posts out there I have enjoyed reading many of them.  I will try to avoid engaging in any direct dialog with you in the future, will not evaluate the quality of your feedback and I am sure that you will do the same.  Thanks for the feedback :)
0
 
LVL 18

Expert Comment

by:marilyng
ID: 17984245
The question is Mike's, and I was responding to his response.  We all have varying and different opinions for a solution, and what is important is that viable solutions and viewpoints are offered to the person posting the question.  It's up to the person asking the question to choose the path that best works for them.
0
 
LVL 63

Author Comment

by:SysExpert
ID: 17984583
Thanks for all the info, and please, no fighting.

There is a ot of expertise here and Notes is flexible enough to supply multiple ways to achieve a single goal.

In the meantime i  started testing and have issues.

The LS code does not appear to be calling the AC Submit agent in the same way it is called from te @function.

I put the LS and normal buttons and the Function button does submit the form and closes it, while the LS button gets to the submit section but for some reason it is not actually submitted. Nor does it close the form.

I'll have more info tomorrow.

0
 
LVL 18

Expert Comment

by:marilyng
ID: 17988664
Arrgh!! not fighting, and am miffed that you think that.  Sheesh!! Now removing myself from this question.
0
 
LVL 8

Expert Comment

by:behenderson
ID: 17989825
sorry for the hubub I should not have made any commentary on Mailyn's code, it was good code.  She is a smart and valuable member of the forum.  I regret causing her to leave because she has valuable knowledge that could help this thread.......

The NotesAgent Run cannot call an agent that works in the UI.  I will have to see if there is a solution to that issue out there.. Marilyn if you know of a quick solution we are all ears (or eyes).
0
 
LVL 8

Expert Comment

by:behenderson
ID: 17989861
Of course the contents of the agent could probably be easily transferred to a script library (If the agent is in Script) and the uid could be sent to it as a parameter
0
 
LVL 8

Expert Comment

by:behenderson
ID: 17990658
Of course if we borrow from Marilyn's solution we can create a field and put it on the form call the field RunAgent Type Text Editable (but hidden)

Change
      If ii Then
          Set agtAcSubmit = CurDb.GetAgent("(AC Submit)")
          Set doc = uidoc.Document
          strNoteId = doc.Noteid
          Call agtAcSubmit.Run(strNoteID)
      End If
to
      If ii Then
           Call uidoc.FieldSetText("RunAgent", "(AC Submit)")
      End If

Then to the postopen we add
   If Not Source.IsNewDoc Then
        Source.Document.RunAgent = ""
   End If

And to the QueryClose we add
@If( RunAgent = "(AC Submit)";
@Do( @Command([ToolsRunMacro]; "(AC Submit)")); "");

That will run the agent in the foreground instead of the background.  That presuposes that you do not have script in the Queryclose.
0
 
LVL 63

Author Comment

by:SysExpert
ID: 17996546
I am also sorry marilyng .

I should watch my language usage.
Fighting was incorrect, and I am in favor of spirited discussions as long as no one gets "hurt"

I am testing behenderson's idea since trying a direct call to the script that is in the (AC Submit)") agent did not work either.

Thanks for the input.

0
 
LVL 63

Author Comment

by:SysExpert
ID: 18028616
OK, I finally got something that appears to work in my test DB.

I'll post more info a little later after checking to see that it finished all the workflow stages.

0
 
LVL 63

Author Comment

by:SysExpert
ID: 18029343
Test DB worked OK

New submit button

Sub Click(Source As Button)
      
      Dim ws As NotesUIWorkspace
      Dim uidoc As NotesUIDocument
'      
      Dim vRunAgent As Variant  ' remove in final
      
      vRunAgent = False
      Set ws = New NotesUIWorkspace
      Set uidoc = ws.CurrentDocument
      
      If uidoc.EditMode Then
            
            Set S2= New NotesSession
            
            Set VLdoc=uidoc.Document      
            Set CurDb = S2.CurrentDatabase    
            s_form=VLdoc.GetItemValue("StFormName_h_cc")(0)  ' need field that is computed when composed with Form name
'      
            ii=   ValidateFieldsviaForm( VLdoc, s_form, curdb)
            If ii=False Then
                  
            Else
                  
                  VLdoc.ACAction = "Submit"
      
                  Call Vldoc.Save( True, False )
 
                  If DidUIDSave( uidoc ) Then
                        vRunAgent = True
                        VLdoc.t_Docstat= "Submit"
 
                        If  Vldoc.Save( True, False ) = True Then
                        '      Msgbox " saved"
                        End If
                  End If
            End If
            
      Else ' not Edit mode
            vRunAgent = False
      End If

----------------
Query Close of subform  has

@If( t_Docstat = "Submit";
@Do(FIELD ACAction := "Submit";
@Command([ToolsRunMacro];"(AC Submit)"));"")
---------------

Query open sets

VLdoc.t_Docstat= ""

Thanks for everyones help !
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Problem "Can you help me recover my changes?  I double-clicked the attachment, made changes, and then hit Save before closing it.  But when I try to re-open it, my changes are missing!"    Solution This solution opens the Outlook Secure Temp Fold…
This article covers general Notes 8.5 troubleshooting information including recreating the Notes\Data folder.
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now