Link to home
Start Free TrialLog in
Avatar of SysExpert
SysExpertFlag for Israel

asked on

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

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 !
Avatar of behenderson
behenderson
Flag of United States of America image

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


 
Avatar of SysExpert

ASKER

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 !
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
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
And lose the strNoteID if it is not R5.02 or higher...
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.

SOLUTION
Avatar of marilyng
marilyng

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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.
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 !

Avatar of marilyng
marilyng

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. :)
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Well shucks, I was adding a friendly alternative solution, as per the EE rules.  beHenderson, when you get a moment, please read: https://www.experts-exchange.com/help.jsp#hs4.

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 :)
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.
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.

Arrgh!! not fighting, and am miffed that you think that.  Sheesh!! Now removing myself from this question.
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).
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
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.
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.

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.

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 !