Generating a document link coming from another form (Web) - lotus-notes

I'm trying to generate document links from another form using a button I created (in pass through below). Upon clicking the button, an agent must run and document link/s should be generated, and the current form should still be in edit mode (web).
Here are the issues:
1. I am unable to generate document link/s coming from another form through the view. The key is PeopleID, the current document has the computed field which should match with another form.
2. When I click on the button, it redirects me to the agent page and says that the agent is done running (non-verbatim). It should still be on the current document (current page, only that the document link/s should be generated).
Below is the code I use on the form (in pass-through) for the button and JS function to run agent.
<input type="button" value="Generate Link" onclick="javascript:runAgent();">
<script language="JavaScript">
function runAgent() {
var path = document.forms[0].BaseLink.value; // BaseLink is the prefix url.
var completeUrl = path + '(GenerateDoc)?OpenAgent&UNID=' + document.forms[0].UniqueID.value;
self.location.href = completeUrl;
}
</script>
After this, I have a rich text field named "DocumentLink", computed.
For the agent code, here it is:
Dim session As New NotesSession
Dim db as NotesDatabase
Dim curDoc as NotesDocument
Dim difDoc as NotesDocument
Dim view as NotesView
Dim rtitem as NotesRichTextItem
Dim peopleID as String
Set db = session.currentDatabase
thisDocumentID = Right$(session.DocumentContext.query_string(0),32)
Set curDoc = db.GetDocumentByUNID(thisDocumentID) //For some reason I am not getting anything here.
Set view = db.GetView("MyView")
peopleID = curDoc.PeopleID(0)
Set difDoc = view.GetDOcumentByKey(peopleID,true)
If Not difDoc Is Nothing Then
Set rtitem = curDOc.GetFirstItem("DocumentLink")
rtitem.values = ""
Call rtitem.AppendDocLink(difDoc,"Link to other form")
Call curDoc.Save(True,False)
End If
Appreciate your help.

There are several issues with what you are doing.
First: The self.location.href = completeUrl; line in Javascript will redirect the browser to the agent which has no relationship to the currently selected or open document. Alternatives to this approach would be using AJAX techniques from jQuery or other framework to run your agent asynchronously. If you have not saved the current document then there might not be a UNID on the Query String using your current approach.
Second: You should put the PeopleId on the query string also so that the agent can read it. The agent should then parse the Query_String_Decoded to get the two elements UNID and PeopleId.
Third: your agent is not generating any output. You should use PRINT statements in the LotusSctipt to create some feedback. You can also create JavaScript Tags and calls to calls to redirect back to the original page/document.

Related

How to get field value from NotesUIDocument that just have been saved and display in other document

Before this I have post a question regarding my problem but still no answer. I will try again to post question about my problem in here. I will update new code and explaination about it. Before this I have done with dialog box, but I have been asked to change it, just use form in view.
My process start with open a form in view to set a new batch info. the form name is PCBatchInfo. In this form, I have 4 field which is BBatchNo, BInspector, BStart, and BEnd. Then in this form I have a button. When I click this button, it will do three process which is:
Create new batch info and save. This is current open document. I call this "dialogDoc".
Then, create a copy of Computer document. In this copy, it will replace BBatchNo as I created just now. I call this copy document as "newdoc" and original document as "doc"
After that, I create new report document and copy value from Computer document. Then I will get value from set batch no which is BInspector, BStart, and BEnd and insert into this report I call this "repdoc".
Below here my lotusscript in my button
Set db = session.CurrentDatabase
Set uidoc = ws.CurrentDocument
Set dialogDoc = uidoc.Document
Set view = db.GetView("Computer")
Set doc = view.GetFirstDocument
If doc.PStatus(0) = "Lock" Then
Msgbox "Complete PC Inspection first!"
Exit Sub
Else
'--set new batch info--'
dialogDoc.Form = "PCBatchInfo"
Call uidoc.FieldSetText("SaveOptions", "1")
Call uidoc.Save
answer% = Messagebox("Please confirm", 4,"Batch Number")
If answer% = 6 Then
While Not (doc Is Nothing)
If doc.PStatus(0) = "Active" Then
'--create new copy document--'
Set newdoc = doc.CopyToDatabase (db)
newdoc.DocumentId = doc.UniversalID
newdoc.PBatchNo = dialogDoc.BBatchNo(0)
Call newdoc.Save(True, False)
'-- set new acceptance form --'
Set repdoc = New NotesDocument (db)
repdoc.Form = "EmpPCSpec"
repdoc.ABatchNo = doc.PBatchNo(0)
repdoc.AStatus = doc.PStatus(0)
repdoc.ATagNo = doc.PTagNo(0)
repdoc.AFStatus = doc.PFStatus(0)
repdoc.AInspector = dialogDoc.BInspector(0)
repdoc.AStart = dialogDoc.BStart(0)
repdoc.AEnd = dialogDoc.Bend(0)
Call repdoc.ReplaceItemValue("AStatus", "Incomplete")
Call repdoc.ComputeWithForm(False,False)
Call repdoc.save(True,False)
doc.PStatus = "Lock"
Call doc.ComputeWithForm(False,False)
Call doc.save(True,False)
End If
Set doc = view.GetNextDocument(doc)
Wend
End If
End If
All this process I run on one button. So when I run this button, I have success to create new batch info, I can create copy of document, and I can create report document.
But the problem now are in copy document, it did not display BBatchNo. And in report document, it did not display BInspector, BStart, and BEnd that I want to get from PCBatchInfo form. The field left empty. I hope my explaination is clear about my problem. Any help from you guys I appreciated. Thanks!
Update Question
For all information save for new batch info using PCBatchInfo, the view is on (PCBatch). How can I get the value in this view? I only get value from "Computer" where it save Computer document.
I think your problem is right here
Set dialogDoc = New NotesDocument(db)
You carefully got the document object from the current UIDoc and then overwrote it with a new (blank) document.

Lock current document using lotusscript

I have a document and a copy of the document. I want to create a document lock for the document using LotusScript.
I have separately put the current document inside Computer view and copy document inside Draft view. Below here the action to create a copy.
Create copy
Sub Click(Source As Button)
Dim ns As New NotesSession
Dim db As NotesDatabase
Dim doc As NotesDocument
Dim newdoc As NotesDocument
Dim dc As NotesDocumentCollection
Set db= ns.CurrentDatabase
Set dc= db.UnprocessedDocuments
If dc.Count<>1 Then
Messagebox "No or too many documents selected"
Exit Sub
End If
Set doc= dc.GetFirstDocument
Set newdoc= doc.CopyToDatabase(db)
Call newdoc.ReplaceItemValue("PStatus", "Draft")
Call newdoc.Save(True, False)
End Sub
Save Button
Sub Click(Source As Button)
Dim session As New NotesSession
Dim workspace As New NotesUIWorkspace
Dim db As NotesDatabase
Dim uidoc As NotesUIDocument
Dim doc As NotesDocument
Dim view As NotesView
Set uidoc = workspace.CurrentDocument
Set db = session.CurrentDatabase
Set view = db.GetView("Draft")
Set doc = view.GetDocumentByKey("Draft", True)
vpswd = Inputbox$("Pls input code to save :")
If vpswd = "o" Then
uidoc.EditMode = True
Set doc = uidoc.Document
Set doc = view.GetFirstDocument
If doc.PStatus(0) = "Draft" Then
Set newdoc= doc.CopyToDatabase(db)
Call newdoc.ReplaceItemValue("PStatus", "Active")
Call newdoc.Save(True, False)
End If
Call uidoc.FieldSetText("SaveOptions" , "1")
Call uidoc.Save
Call uidoc.Close
End If
End Sub
How can I lock a current document every time I create a copy of the document? E.g current document will lock when the copy document created.
Another question is, for copy document, after I saved, I want to replace the current document as a copy document and a copy document will be a live document. While the current document will not be deleted from the database but deleted from Computer view and displayed in the "Archived" view.
And inside Draft view, copy document will be deleted from view. Any help will be appreciated. Thanks!
Locking a document should be implicit. Make sure that you use the Status field in all documents. E.g. when you create the copy, set the status of the copied document to "Copied" and the nw documof nt to "Draft". You have to cover all different status changes. Best is also to add one field that contains a unique document Id that can never be changed. Maybe also add a version number.
Examples of statuses:
Draft: document under construction (only one, cannot be copied)
Current: valid document (only one, can be copied)
Copied: Current document that has been copied (only one, cannot be copied)
Archived: document that has been replaced (more than one, cannot be copied)
It might help to create a STD, a State Transition Diagram.
I have done something similar. When a new version, as I call it, is created, it is the "draft" document. The previous document is an "approved" document. User get to see only the approved until the new version is approved, then the older approved document is archived out of the db. If you want all versions to stay in the db, but only the newer document brought up, you could use what I call a HistoryID field. Basically I have a field on every document that has up to three values in it:
TheUNID
ParentUNID:TheUNID:Parent
TheUNID:ChildUNID:Child
The "theUNID" field is computed when composed so it never changes. If a new version or draft is created, the HistoryID would now have two values:
TheUNID
TheUNID:ChildUNID:Parent
This let's you know you now have a new draft and the document you are on is actually a parent. The "ChildUNID" is actually "theUNID" of the draft document you just created.
On the child document or the new draft document you put in the HistoryID:
TheUNID
ParentUNID:TheUNID:Parent
This way your draft knows who it's parent is.
In your code in your db, you just have any document that gets opened check the HistoryID field first. If there is a child, you take the user to the child. It doesn't matter what parent gets opened or how far back the generations go, your code continues to iterate through the HistoryID until the current child document is found that doesn't have a parent. Sound good?
Let me know if you need clarification.

How can Lotus Notes detect whether a document is currently being opened?

As title.
How can Lotus Notes detect whether a document is currently being opened?
The solution should without "Document locking" because of User's User needs.
I have 1 maindoc and 1 subdoc, but subdoc and maindoc are not parents.
I use the "IsUIDocOpen" but it just worked at currentdocument.
Is there any other way to do this?
If you ask just for one client, then this is doable without document locking, but it needs some advanced techniques:
You can use NotesUIWorkspace to get a currently open document for any given backend document if you set parameter "newInstance" to false.
To get the currently open document (as uidocument, but of course you can use .Document property to get NotesDocument from it) you use the following code. If it returns nothing then the document is not open:
Dim ses as New NotesSession
Dim ws as New NotesUIWorkspace
Dim docToGetFrontendFor as NotesDocument
Dim uidoc as NotesDocument
Set docToGetFrontendFor = .... 'somehow get the document you wanna have the frontend for
Call ses.SetEnvironmentvar( "PreventOpen" , "TRUE" )
Set uidoc = ws.EditDocument( False, docToGetFrontendFor, False, "", True, False )
If not uidoc is Nothing then '-document was open already
'- do whatever with the frontend- document
Why the ses.SetEnvironmentvar( "PreventOpen" , "TRUE" )?
The EditDocument opens the document regardless of it being open already or not.
You need to prevent the document from opening, if it is not already open. Therefor you manipulate the "QueryOpen"- Event of the Form of the document:
Sub Queryopen(Source As Notesuidocument, Mode As Integer, Isnewdoc As Variant, Continue As Variant)
Dim ses as New NotesSession
Dim strPrevent as String
strPrevent = ses.GetEnvironmentstring( "PreventOpen" )
Call ses.SetEnvironmentVar( "PreventOpen" , "" )
If strPrevent = "TRUE" Then Continue = False
End Sub
So: The document does NOT open, if PreventOpen is set, so if it is not already open it will stay closed.
This approach has one big downside: The Notes Client has a "BUG": If you open a document and save it and then open it again with my code, then it will Open in a second window DESPITE the parameter "newInstance" set to false unless you closed and reopened that document.
Explained:
Create Document
Save document
Close document
Reopen document
Use my code
==> Works as the code just "reuses" the window
Create Document
Save document
Use my code
==> Will try to open a second instance for the document and then return NOTHING as this new instance does not open because of the code...

$Ref flag reappears even after deletion

We have an Xpage based Web mail-in application. Some emails are coming with $Ref field (response document). We wanted to convert them into normal document by removing $Ref field so that it will no longer a response one. We are able to delete the $ref field but it reappears again after saving the documents from web interface(xpage) and it makes all such documents again response document. This started happening recently and working well earlier. Can you please suggest what is the root cause? How to stop it?
Sub Initialize
On Error GoTo ErrorHandler
Dim s As New NotesSession
Dim db As NotesDatabase
Dim coll As NotesDocumentCollection
Dim doc As NotesDocument
Dim count As Long
Set db = s.Currentdatabase
Set coll = db.Unprocesseddocuments
MessageBox "Count : " & coll.Count
'Exit Sub
count = 1
Set doc = coll.Getfirstdocument()
While Not doc Is Nothing
If doc.Hasitem("$Ref") Then
Call doc.Removeitem("$Ref")
Call doc.Save(false, false)
End If
Print count
count = count + 1
Set doc = coll.Getnextdocument(doc)
Wend
Exit Sub
ErrorHandler:
MessageBox "Error " & Error & " at line " & Erl
Exit Sub
End Sub
Try changing your save method to Call doc.Save(true, false).
This will force the document save, and also prevent creating a response.
Also verify that you are running the agent on a server not accessable to active users. Also verify that you are only running your agent once, and that it isn't enabled on multible replicas.
Have you tried using If(doc.isResponse) Then instead of If doc.Hasitem("$Ref") Then
Note: I am looking in the java editor, but assume that the isResponse method is also in LS.
Wheather a document is a response is controlled by a property of the used form. As long as you do not assign another form that is a "Document" and not a "Response", you will most probably not be able to remove the "isresponse"- flag. As already told: most probably your xpage saves the "frontend" document after your backend manipulation and resets the state (form validation enabled in xpage properties). But without source code of the xpage one cannot tell.
Check the form name. Emails can use either the "Memo" form or the "Reply" form. Emails using the Reply form are response documents. You may also need to change the form to "Memo".

Getting values from profile document

I have some problem getting the value from the profile document. For creation, I followed these instructions:
Creating a profile form
1.Create a form with fields to hold the values you want to store in profile documents.
2.Choose Design - Form Properties and deselect "Include in Menu. and "Include in Search Builder"
3.Save the form.
4.Do not include the form in any view.
In the form I have only one field that is computed when composed (a number), with a computed value "0"
But with this code I can't retreive the field value:
Dim session as New NotesSession
Dim db as NotesDatabase
Dim doc as NotesDocument
Set db=session.CurrentDatabase
Set doc=db.GetProfileDocument("nameofprofiledoc")
dim number as integer
number=doc.fieldname(0)
Isprofile return true, but number is always "". For some reason it never gets the value
Perhaps it is because you haven't saved the document into the database yet. You can create an action button that let's you edit the document and then save it:
#Command( [EditProfile] ; formname );
Computed field formulas are not executed when you call GetProfileDocument. That's because GetProfileDocument is a "back-end" method. The form, with its various field definitions and formulas is used by the "front-end". (There's one exception: there's a ComputeWithForm method available in the back-end classes.) Anyhow. GetProfileDocument either loads a previously saved profile doc, or creates a new one that is essentially empty. #Ken's answer tells you how to manually create the profile document and save it so your code will find it. As an alternative, you can do the initialization in your code like this:
if ! doc.hasItem("fieldname") then
doc.replaceItemValue("fieldname",0)
end if
number=doc.fieldname(0)
That way you won't be dependent on someone manually creating the profile document. But if you are accessing the profile document from multiple places in code, and you can't predict which code might execute first, then you're probably going to want to create a script library with functions (or a class) and wrap GetProfileDocument in your own function (or method) to insure that all code paths will do the initialization properly.
As Richard mentions, when you call the method GetProfileDocument, the profile is created as a blank document, if not found in the database, (it will only have some initial fields that hold the profile name, conflict action, last editor)..
To initialize the profile, you might try to either:
1) Program the Form's QuerySave event to copy all items to the profile (then cancel the Save, to avoid storing the data in a regular document).
Sub Querysave(Source As Notesuidocument, Continue As Variant)
Dim db As NotesDatabase
Dim curdoc As NotesDocument
Dim profile As NotesDocument
Set curdoc = Source.Document
Set db = curodc.ParentDatabase
Set profile = db.GetProfileDocument(curdoc.Form(0))
Call curdoc.CopyAllItems(profile, True)
Call profile.Save(True, False)
Continue = False 'Don't allow the form to be saved to a regular document.
End Sub
Or:
2) Call GetProfileDocument to create a new profile or get an old one (you can tell the difference by checking the IsNewNote property. Then assign it a Form name, and compute it with this form.
In an Agent or an Action:
Sub InitializeProfile
Dim s As New NotesSession
Dim db As NotesDatabase
Dim profile As NotesDocument
Set db = s.CurrentDatabase
Set profile = db.GetProfileDocument("MyForm")
If profile.IsNewNote Then
Call profile.ReplaceItemValue("Form", "MyForm")
Call profile.ComputeWithForm(False, False) 'This will create the computed fields with their default values in the profile.
Call profile.Save(True, False)
End If
End Sub

Resources