I have a process called PC Inspection. When copy inspection, batch no will be change every time inspection is done. And there is pc inspection form called EmpPCSpec. It will copy data from computer document.
I can create batch but it only created for one document selected only.
Below are the lotusscript code to set new batch and create pc inspection form.
Sub Click(Source As Button)
Dim session As New NotesSession
Dim workspace As New NotesUIWorkspace
Dim db As NotesDatabase
Dim collection As NotesDocumentCollection
Set db = session.CurrentDatabase
Set collection = db.UnprocessedDocuments
Dim ws As New NotesUIWorkspace
Dim uiview As NotesUIView
Set uiview = ws.CurrentView
answer% = Messagebox("Do you want to set batch number?", 4,"Batch Number")
If answer% = 6 Then
InputBatchNo = Inputbox("Please insert the Batch Number. eg : 2014A")
If Not InputBatchNo="" Then
For ii = 1 To collection.count
Set doc = collection.GetNthDocument(ii)
currbatchno = doc.PBatchNo(0)
'--------------------------------------
Gosub SetNewBatchNo
'---------------------------------------
doc.PBatchNo =newbatchno
'------------ set new acceptance form ---------------------------
If doc.PStatus(0) = "Active" Then
Set comdoc = New NotesDocument (db)
comdoc.Form = "EmpPCSpec"
comdoc.ATagNo = doc.PTagNo(0)
comdoc.AYear= Left(InputBatchNo,4)
comdoc.ADept= doc.PDept(0)
comdoc.AUserName= doc.PUserName(0)
comdoc.AUserID= doc.PUserID(0)
comdoc.AUserGroup= doc.PUserGroup(0)
comdoc.ALocation= doc.PLocation(0)
comdoc.AStatus= doc.PStatus(0)
comdoc.ABatchNo=doc.PBatchNo(0)
comdoc.AProcessor= doc.PProcessor(0)
comdoc.ASerialNo= doc.PSerialNo(0)
comdoc.ABrand= doc.PBrand(0)
comdoc.AModel= doc.PModel(0)
comdoc.AType= doc.PType(0)
comdoc.ADisplayUnit= doc.PDisplayUnit(0)
comdoc.ADisplaySize= doc.PDisplaySize(0)
comdoc.ADisplayBrand= doc.PDisplayBrand(0)
comdoc.ARam= doc.PRam(0)
comdoc.AHDD= doc.PHDD(0)
comdoc.AIPAddress= doc.PIPAddress(0)
comdoc.AOperatingSys= doc.POperatingSys(0)
comdoc.ACalLicense= doc.PCalLicense(0)
Call comdoc.ComputeWithForm(False,False)
Call comdoc.save(True,True)
'----------------------------------------------------------------
Call doc.ComputeWithForm(False,False)
Call doc.save(True,True)
End If
Next
Messagebox("Process completed." & Chr(13) & "Press 'F9' to refresh the view.")
Else
Messagebox("Please insert Batch Number.")
End If
End If
Exit Sub
SetNewBatchNo:
currbatchno1 = Strtoken(currbatchno, "-", 1)
If InputBatchNo = currbatchno1 Then
seqno = Strtoken(currbatchno, "-", 2)
newseqno = Val(seqno) +1
newseqno1 = Format(newseqno, "0000")
newbatchno = InputBatchNo + "-" + newseqno1
Else
newbatchno = InputBatchNo + "-" + "0001"
End If
Return
End Sub
How can I get all document where if status is "Active" by looping it? Any help will be appreciated. Thanks!
There are a number of issues with this code: using getNthDocument should be avoided as it is a performance killer and bad practice - at least for larger collections as the code will recalculate the position of the document on every use of getNthDocument. Use getFirstDocument and getNextDocument instead. The same is true for the logic with goto. This is difficult to read, understand and especially to maintain. I suggest you create a logic like this:
Set collection = db.UnprocessedDocuments
set doc = collection.getFirstDocument()
while not doc is nothing
if doc.status(0) = "Active" then
<your logic goes here>
end if
//next doc for processing
set doc=collection.getnextdocument(doc)
wend
Besides the above mentioned issues I think the issue with your code is that you did not establish any sort of looping through all selected documents - getNthDocument() is executed only once, therefore only one document is being touched. But as I already said it is dificult to read and understand when and where the code jumps to during runtime due to the use of goto.
Related
Goal for my project:
I want to be able to copy the contents of one document and append that selection to the end of another document.
What it does... (this is just background info so you understand why I am trying to do this):
I am trying to dynamically produce a document which quotes a variety of information regarding different parts and materials involved for a product.
The document itself has a consistent format which I have broken down and separated into two documents. The first contains a bunch of data that needs to be entered manually, and is where I want to append all additional content. The second contains roughly a dozen custom fields which are updated from an excel spreadsheet in VBA. For a single part and as a single doc this works as I want it (my base case). However my issue is when there are multiple parts for a project.
The Problem:
For multiple parts I have to store information in an array which changes in size dynamically as each additional part is added. When someone has added all the necessary parts they can select a button called "Create Quote".
Create quote runs a procedure which creates/opens separate copies of the two template documents mentioned above (saved on my computer). It then iterates through the array of parts and updates all the custom field in the 2nd document (no problems). Now I just need the contents of the 2nd document appended to the end of the first which is my problem.
What I want:
Ideally, my procedure will continue to iterate through every part in the array - updating custom fields, copy then paste the updated text, repeat... Until every part is included in the newly generated quote.
What I Tried - this code can be found in my generate quote procedure
I have tried many of the examples and suggestions provided by people who had similar question, but I don't know if its because I am operating from an excel doc, but many of their solution have not worked for me.
This is my most recent attempt and occurs after each iteration of the for loop
wrdDoc2.Fields.Update 'Update all the fields in the format document
wrdDoc2.Activate
Selection.WholeStory ' I want to select the entire document
Selection.Copy ' Copy the doc
wrdDoc1.Activate ' Set focus to the target document
Selection.EndKey wdStory ' I want the selection to be pasted to the end of the document
Selection.PasteAndFormat wdPasteDefault
QUOTE PROCEDURE - I am only including a handful of the fields I am updating because its not necessary to show them all
Private Sub quote_button_Click()
On Error GoTo RunError
Dim wrdApp1, wrdApp2 As Word.Application
Dim wrdDoc1, wrdDoc2 As Word.Document
Set wrdApp1 = CreateObject("Word.Application")
Set wrdApp2 = CreateObject("Word.Application")
wrdApp1.Visible = True
wrdApp2.Visible = True
Set wrdDoc1 = wrdApp1.Documents.Add(Template:="C:\MWES\AQT_v1.1(start).docm", NewTemplate:=False, DocumentType:=0)
Set wrdDoc2 = wrdApp2.Documents.Add(Template:="C:\MWES\AQT_v2.1(format).docm", NewTemplate:=False, DocumentType:=0)
Dim propName As String
For i = LBound(part_array, 1) To UBound(part_array, 1)
For Each prop In wrdDoc2.CustomDocumentProperties
propName = prop.name
' Looks for and sets the property name to custom values of select properties
With wrdDoc2.CustomDocumentProperties(propName)
Select Case propName
Case "EST_Quantity"
.value = part_array(i, 0) ' "QTY" ' Sheet1.Cells(1, 3) 'NA
Case "EST_Metal_Number"
.value = part_array(i, 1) ' "METAL_#" ' Sheet1.Cells(2, 3) 'NA"
Case "EST_Metal_Name"
.value = part_array(i, 2) ' "METAL_N" ' Sheet1.Cells(5, 2)
End Select
End With
Next prop ' Iterates until all the custom properties are set
wrdDoc2.Fields.Update 'Update all the fields in the format document
wrdDoc2.Activate
Selection.WholeStory ' I want to select the entire document
Selection.Copy ' Copy the doc
wrdDoc1.Activate ' Set focus to the target document
Selection.EndKey wdStory ' I want the selection to be pasted to the end of the document
Selection.PasteAndFormat wdPasteDefault
Next i ' update the document for the next part
RunError: ' Reportd any errors that might occur in the system
If Err.Number = 0 Then
Debug.Print "IGNORE ERROR 0!"
Else
Dim strError As String
strError = "ERROR: " & Err.Number & vbCrLf & Err.Description & vbCrLf & Erl
MsgBox strError
Debug.Print strError & " LINE: " & Erl
End If
End Sub
I apologize this was so long winded. Let me know if there is anything confusing or you may want clarified. I think I included everything though.
I think you're close, so here are a couple of comments and an example.
First of all, you're opening two separate MS Word Application objects. You only need one. In fact, it's possible that the copy/paste is failing because you're trying to copy from one Word app to a document opened in the other. (Trust me, I've seen weird things like this.) My example below shows how to do this by only opening a single application instance.
Dim mswApp As Word.Application
Set mswApp = AttachToMSWordApplication() 'more on this function below...
Dim doc1 As Word.Document
Dim doc2 As Word.Document
Set doc1 = mswApp.Documents.Open("C:\Temp\combined.docx")
Set doc2 = mswApp.Documents.Open("C:\Temp\control.docx")
While I don't often write code for Word, I've found that there are so many different ways to get at the same content using different objects or properties. This is always a source of confusion.
Based on this answer, which has worked well for me in the past, I then set up the source and destination ranges to perform the "copy":
Dim destination As Word.Range
Dim source As Word.Range
Set source = doc1.Content
Set destination = doc2.Content
destination.Collapse Direction:=Word.wdCollapseEnd
destination.FormattedText = source
Here is the whole module for reference:
Option Explicit
Sub AddDocs()
Dim wordWasRunning As Boolean
wordWasRunning = IsMSWordRunning()
Dim mswApp As Word.Application
Set mswApp = AttachToMSWordApplication()
Dim doc1 As Word.Document
Dim doc2 As Word.Document
Set doc1 = mswApp.Documents.Open("C:\Temp\combined.docx")
Set doc2 = mswApp.Documents.Open("C:\Temp\control.docx")
Dim destination As Word.Range
Dim source As Word.Range
Set source = doc1.Content
Set destination = doc2.Content
destination.Collapse Direction:=Word.wdCollapseEnd
destination.FormattedText = source
doc2.Close SaveChanges:=True
doc1.Close
If Not wordWasRunning Then
mswApp.Quit
End If
End Sub
Here's the promised note on a couple functions I use in the sample. I've built up a set of library functions, several of which help me access other Office applications. I save these modules as .bas files (by using the Export function in the VBA Editor) and import them as needed. So if you'd like to use it, just save the code below in using a plain text editor (NOT in the VBA Editor!), then import that file into your project.
Suggested filename is Lib_MSWordSupport.bas:
Attribute VB_Name = "Lib_MSWordSupport"
Attribute VB_Description = "Variety of support functions operating on MS Word"
Option Explicit
Public Function IsMSWordRunning() As Boolean
Attribute IsMSWordRunning.VB_Description = "quick check to see if an instance of MS Word is running"
'--- quick check to see if an instance of MS Word is running
Dim msApp As Object
On Error Resume Next
Set msApp = GetObject(, "Word.Application")
If Err > 0 Then
'--- not running
IsMSWordRunning = False
Else
'--- running
IsMSWordRunning = True
End If
End Function
Public Function AttachToMSWordApplication() As Word.Application
Attribute AttachToMSWordApplication.VB_Description = "finds an existing and running instance of MS Word, or starts the application if one is not already running"
'--- finds an existing and running instance of MS Word, or starts
' the application if one is not already running
Dim msApp As Word.Application
On Error Resume Next
Set msApp = GetObject(, "Word.Application")
If Err > 0 Then
'--- we have to start one
' an exception will be raised if the application is not installed
Set msApp = CreateObject("Word.Application")
End If
Set AttachToMSWordApplication = msApp
End Function
Before this I ask this question and #Torsten Link suggest that I filter document to prevent user from select different document. Basically I have view, and in this view I have list of document sort by Faulty Status which I set as PFStatus. So I have three status which is Obsolete, Spoilt, and Not Found. So I want to filter so that user choose either these three status only and cannot be mixed up.
So I try to filter using below code but nothing happened.
Set doc = dc.GetFirstDocument()
If (doc.PFStatus(0) = "Obsolete" And doc.PFStatus(0) = "Spoilt" And doc.PFStatus(0) = "Not Found") Then
Messagebox"Please choose either one Write Off selection!"
Exit Sub
Elseif (doc.PFStatus(0) = "Obsolete" And doc.PFStatus(0) = "Spoilt") Then
Msgbox"Please choose only one Write Off selection!"
Exit Sub
Elseif (doc.PFStatus(0) = "Obsolete" And doc.PFStatus(0) = "Not Found") Then
Msgbox"Please choose only one Write Off selection!"
Exit Sub
Elseif (doc.PFStatus(0) = "Spoilt" And doc.PFStatus(0) = "Not Found") Then
Msgbox"Please choose only one Write Off selection!"
Exit Sub
Else
'Some code...
End If
So how can I filter selection of documents? Did I put the code in wrong way? Any help I really appreciate. Thank you. :)
Update question
Below are my view name "WriteOff". And I have a button to create new batch. So I want to try prevent user from create a batch with mixed up Faulty Status.
I created a sample on how to do this
Best is not to put your code in the button, but to create an agent to put your code in. Like this, you don't need to refresh your view while debugging your code.
Set 'Agent list selection' as trigger and Target = None.
Create a button in the view using the following formula (replace 'batch process' by your agent name):
#Command([ToolsRunMacro];"(batch process)")
Here's an example of the agent code on how you can check if pfstatus in selected docs is the same.
Option Public
Option Declare
Sub Initialize
Dim col As NotesDocumentCollection
Dim doc As NotesDocument
Dim vwUI As NotesUIView
Dim ws As New NotesUIWorkspace
Dim session As New NotesSession
Dim dbcurrent As NotesDatabase
Set dbCurrent = session.currentdatabase
'Use vwui.documents to keep documents selected if the agent runs.
'Like this, a user can deselect a faulty document.
'Don't forget to deselect all docs at the end of your code
Set vwui = ws.Currentview
Set col = vwui.Documents
'If a user did not 'select' a document (eg V marker before the docline), but merely positioned on a document,
'you need to create a single doc collection based on the caretnoteid (= id of selected document)
If col.count = 0 And vwui.caretnoteid <> "" Then
Set doc = dbCurrent.Getdocumentbyid(vwui.caretnoteid)
Set col = dbCurrent.createdocumentcollection()
Call col.Adddocument(doc)
End If
'Get status from first document to get status to compare against
Dim statusRef As String
Set doc = col.getfirstdocument
If doc Is Nothing Then Exit Sub 'avoid error when no doc is selected
statusRef = doc.pfStatus(0)
'loop other selected documents to compare status
Set doc = col.getNextDocument(doc)
While Not doc Is Nothing
If doc.pfStatus(0) <> statusRef Then
'A document with another status is selected, so do not continue
Msgbox"Please choose only one Write Off selection!"
Exit sub
End If
Set doc = col.getNextDocument(doc)
Wend
'If code gets here, you can loop all documents again to do you batch processing
'Reset doc to first doc in selected collection
Set doc = col.getfirstdocument()
While Not doc Is Nothing
'... some code to run on current doc in the loop ...
Set doc = col.getNextDocument(doc)
Wend
'Deselect documents at the end of your code
Call vwui.Deselectall()
End Sub
Is PFStatus a multi-value field? If it isn't, it can never have more than 1 value (unless you set more than one value programmatically). Or is it a checkbox field?
I think it would be the best if you simply disallow the selection of documents from multiple categories in the view. See https://www.ibm.com/support/knowledgecenter/en/SSVRGU_9.0.1/basic/H_ONSELECT_EVENT.html
IMHO a status field should never be directly input by the user. You should have buttons that guide the user to perform some functions AND change the status in the meantime.
I have around 50 lotus notes databases which I need to search through (including RTFs and attachments) based on a rather complicated query (for example: If customer = a or b or c or d or e ... or z & product = x or y) then == match; and a tag to (e.g. tag = found or not found)
However, I wasn't sure the best way to go about this and wanted to check three options.
Using Lotus' 'Search in View' should, after indexing, search all the databases - however I am unsure if it will accept a long, complicated search query
Coding an agent in Lotus SCRIPT to basically perform the search in 1. but this might be a way of getting it to accept a complicated query
Using external software (e.g. X1 Professional Search) to search outside of Lotus Notes (however I am not sure if I will be able to tag the files if I identify them in windows explorer).
Edit: My idea is:
Sub Initialise
Dim session as New NotesSession
Dim db as NotesDatabase
Dim dc as NotesDocumentCollection
Dim doc as NotesDocument
Dim searcy_query$
'On current database
Set db = session.CurrentDatabase
'Force index of database
Call db.UpdateFTIndex(True)
'Construct QUERY
search_query = "(Customer1|Customer2) & (Product1|Product2)"
'Search
Set dc = db.FTSearch(query, 0)
If dc.Count=0 Then
Msgbox "No matches!"
Exit Sub
End If
‘Tag the matched documents with “Flag”
Call dc.StampAll("Flag","Active)")
End Sub
However, I am not sure if this will return all matches and also regarding #TRIM and #UPPER (where to put them into the query as I will be searching all fields and RTFs rather than specific ones)
First of all: Searching more than one database at a time can of course be done "manually" by searching each individual database, collection the results and find a way to present the documents "somehow" (what will not be easy, as documents from different databases cannot be shown in "one" view - you would need to use "shadow- documents" or a web- approach (e.g. XPages))
BUT: Lotus Notes has a built-in function to do this, it is called "Domain Indexer". You can read more about how to setup "domain index" in this IBM Link or in your administration help.
Examples for using the domain- index for multi- database- searches can be found in catalog.nsf in the form "DomainQuery".
The search- string does not have a limit as far as I know, so that you can do very complex searches with this technique and it gives you all the matches.
If you search for a LotusScript- Solution, check the documentation for NotesDatabase.ftdomainsearch for example code like this (taken from developer help):
The following code, when placed in a button on a search form within a directory catalog database, searches the directory for the specified query string, and returns all results.
Sub Click(Source As Button)
Dim s As New NotesSession
Dim db As NotesDatabase
Dim w As New NotesUIWorkspace
Dim uidoc As NotesUIDocument
Dim doc as NotesDocument
Dim quer As String
Dim srdoc as NotesDocument
Set db=s.CurrentDatabase
Set uidoc = w.currentdocument
uidoc.refresh
Set doc=uidoc.Document
quer=doc.query(0)
On Error Resume Next
If db.isopen Then
If Err <> 0 Then
Messagebox STR_DBOPEN_ERROR, 0 , STR_ERROR
Err = 0
Exit Sub
End If
Set srdoc = db.ftdomainsearch(quer, 0)
If Err <> 0 Then
Messagebox STR_NDF , 0 , STR_LOTUS_NOTES
Err=0
Exit Sub
End If
srdoc.Form="SearchResults"
Call w.EditDocument(False, srdoc, True)
End If
End Sub
If you also intend to search Rich Text, the simplier way is Full Text Search, you got the point!
The syntax for your query is:
generic_text or ([_CreationDate]<07.10.2014 and ([CustomerFieldName]="Smith" or [CustomerFieldName]="Wesson"))
For formating the Result, I'ld suggest looking at:AppendDocLink for something like:
Dim session As New NotesSession
Dim db As New NotesDatabase("", "resu.nsf")
Dim newDoc As NotesDocument
Dim rtitem As NotesRichTextItem
Dim dc As NotesDocumentCollection
Dim doc As NotesDocument
Set newDoc = New NotesDocument( db )
Set rtitem = New NotesRichTextItem( newDoc, "Body" )
'you have to loop on your 50 DBs
'Search =>from your code
Set dc = db.FTSearch(query, 0)
while not doc is nothing
Call rtitem.AppendDocLink( doc, db.Title )
Call rtitem.AddTab( 1 )
Call rtitem.AppendText( doc.FieldImportantInResult( 0 ) )
Call rtitem.AddNewLine( 1 )
Set doc = dc.GetNextDocument( doc )
Wend
newDoc.save true, true
'this part is not to add it you plane to run your search in background
Dim w As New NotesUIWorkspace
Call w.EditDocument(False, newDoc, True)
I use the below script in querysave event of a form. The logic is when I save the form the sequence should get displayed in the view in two columns. like "115-" in one column and the sequence "00001", "00002", ... in the second column. The first two documents gets saved without any issue. When I save try to save 3rd and more documents, its displaying "00002" only every time after that. I am not able to identify what is the mistake. Can somebody help please.
Sub Querysave(Source As Notesuidocument, Continue As Variant)
Dim SESS As New NotesSession
Dim w As New NotesUIWorkspace
Dim uidoc As NotesUIdocument
Dim Doc As NotesDocument
Dim RefView As NotesView
Dim DB As NotesDatabase
Dim RefDoc As NotesDocument
Set DB = SESS.CurrentDatabase
Set uidoc = w.CurrentDocument
Set Doc = uidoc.Document
Set RefView = DB.GetView("System\AutoNo")
Dim approvedcnt As Integer
approvedcnt = Cint(source.fieldgettext("appcnt"))
If uidoc.EditMode = True Then
Financial_Year = Clng(Right$(Cstr(Year(Now)),3)) + 104
If Month(Now) >= 4 Then Financial_Year = Financial_Year + 1
DocKey = Cstr(Financial_Year)& "-"
New_No = 0
Set RefDoc = RefView.GetDocumentByKey(DocKey , True)
If Not(RefDoc Is Nothing) Then New_No = Clng(Right$(RefDoc.SETTLEMENT_NO(0),5))
New_No = New_No + 1
autono = DocKey & "-" & Right$("00000" & Cstr(New_No) ,5)
Application ="ST"
Latest_No = Application + autono
Doc.SETTLEMENT_NO = Latest_No
Doc.FinFlag="Finish"
Call SESS.SetEnvironmentVar("ENV_ST_NO",Right$("00000" & Cstr(DefNo&) ,5))
'Call uidoc.FieldSetText("SETTLEMENT_NO",Latest_No)
Call uidoc.Refresh
Else
Exit Sub
End If
get_ex_rate
get_cv_local
Call uidoc.FieldSetText("Flag1", "A")
If approvedcnt = 12 And uidoc.FieldGetText("STATUS") = "APPROVE" Then
Call uidoc.fieldsettext("Flag2", "B")
End If
Dim answer2 As Integer
answer2% = Msgbox("Do you want to save this document?", 1, "Save")
If answer2 = 1 Then
Print "Saving"
End If
If answer2 = 2 Then
continue=False
Exit Sub
End If
uidoc.Refresh
uidoc.close
End Sub
I imagine your call to GetDocumentByKey is getting the wrong document or not the next one in sequence. Make sure the view is sorted properly and perhaps call the refresh method on the view before calling GetDocumentByKey.
Our Domino developer told us that it is "technologically impossible" to move subdocuments between documents. Is this true?
Earlier this year he wrote for us a course registration system with the following database diagram:
Now we asked him how to move waitlisted registrants from the full training sessions to those sessions that are not. He said it is impossible. He said we need to re-enter (recreate, copy and paste manually) the waitlist records because Domino cannot move attendees from one session to another.
We have over 1000 attendees in our waitlists.
Is he correct? Is this for real? We hope for a solution.
How to do it depends on the way the documents are linked. But in any case it should be possible to relink the documents using code (formula/lotusscript/java).
The help of the Lotus designer contains a lot of information about application development. Another resource is IBM developerworks
There are numerous Lotus related blogs
From the Lotus Designer help:
MakeResponse: Makes one document a response to another document. The two documents must be in the same database.
Dim session As New NotesSession
Dim db As NotesDatabase
Dim view As NotesView
Dim docA As NotesDocument
Dim docB As NotesDocument
Set db = session.CurrentDatabase
Set view = db.GetView( "All documents" )
Set docA = view.GetFirstDocument
Set docB = view.GetNextDocument( docA )
Call docB.MakeResponse( docA )
docB.Form = "Response"
Call docB.Save( True, True )
There are 2 ways that documents can be linked:
- via keys, the soft way
- hierarchically, using a document-response link (i.e. parent-child)
If there is only the logical link, using keys, you only have to adapt the key fields. If there is a "physical", document-response link, you can easily break and recreate that link. In LotusScript there is the NotesDocument.MakeResponse method to attach any document to a new parent. If both methods are used, redundant of course but practical when you need to recover some links, you need to do both changes. Usually, some key fields are repeated from parent to child
Just for testing purposes, you could try this:
- select a response document that you want to hang elsewhere
- Ctrl-X
- select the new parent document
- Ctrl-V
Do this in a test database, for the key fields won't be updated automatically. By the way: code can be written to repair the keys after pasting such a response document.
If you want to keep existing documents you could programmatically copy/duplicate them.
It's quite easy using copyAllItems method.
Look Domino help (with example) here
You could iterate documents with notesView object (getFirstDocument() / getNextDocument() methods), iterate responses on notesdocument.responses method...
Trust us, it's possible, Domino is flexible :-)
There are basically 2 ways this data is linked in the data model you describe. If the data is linked through response document hierarchies it will be slightly different from key based document structures.
Show this to your developer and, he should literally be able to plug in the code to enable the "move attendees" requirements that you're talking about.
A few things to note.
I am assuming that all the data you need to manipulate is in one database.
I am taking your diagram you've provided literally.
For key based document structures, you'll need to check the view and key values used o find attendee documents. Specifically check these 2 lines in the "MoveAttendeesKeyBased" sub:
Set vwAttendeesByCourseID = db.GetView("(LkupAllAttendeesByCourseID)")
Set dcAttendees = vwAttendeesbyCourseID.GetAllDocumentsByKey(docCourseFrom.CourseID(0), True)
The code is designed to look at a field called "CourseID", "Status" and the value of "Wait Listed" for the status value of attendees to be moved.
It took about 20 minutes to write both versions of this function.
For response based document structures
Sub MoveAttendeesResponseBased(docCourseFrom As notesDocument, docCourseTo As NotesDocument)
%REM
A simple move attendees function if the relationship between courses and attendees is based on
response document hierarchies
%END REM
On Error Goto errHandle
Dim dcAttendees As notesDocumentCollection
Dim docAttendee As notesDocument
Dim iAvailablePlaces As Integer
Dim bMoved As Boolean
If Not (docCourseFrom Is Nothing Or docCourseTo Is Nothing) Then
iAvailablePlaces = docCourseTo.availablePlaces(0)
If 0 < iAvailablePlaces Then
bMoved = False
Set dcAttendees = docCourseFrom.Responses
Set docAttendee = dcAttendees.GetFirstDocument
While Not docAttendee Is Nothing And 0 < iAvailablePlaces
If Ucase(Trim(docAttendee.Status(0)))= "WAIT LISTED" Then
Call docAttendee.MakeResponse(docCourseTo)
If docAttendee.Save(True,True) Then
iAvailablePlaces = iAvailablePlaces - 1
bMoved = True
End If
End If
Set docAttendee = dcAttendees.GetNextDocument(docAttendee)
Wend
If bMoved Then
docCourseTo.availablePlaces = iAvailablePlaces
Call docCourseTo.Save(True,False)
End If
End If
End If
Exit Sub
errHandle:
Messagebox Lsi_info(2) + " - " + Str(Err) + " : " + Error(Err) + ", at line " + Str(Erl)
Exit Sub
End Sub
For key based document structures
Sub MoveAttendeesKeyBased(docCourseFrom As notesDocument, docCourseTo As notesDocument)
%REM
A simple move attendees function if the relationship between courses and attendees uses
(non-response) key based documents
%END REM
On Error Goto errHandle
Dim session As New notesSession
Dim dcAttendees As notesDocumentCollection
Dim docAttendee As notesDocument
Dim iAvailablePlaces As Integer
Dim bMoved As Boolean
' a view that lists attendees by Course ID
Dim vwAttendeesByCourseID As notesView
Dim db As notesDatabase
If Not (docCourseFrom Is Nothing Or docCourseTo Is Nothing) Then
iAvailablePlaces = docCourseTo.availablePlaces(0)
If 0 < iAvailablePlaces Then
Set db = session.CurrentDatabase
' do a lookup of all attendees based on the CourseFrom document course id
Set vwAttendeesByCourseID = db.GetView("(LkupAllAttendeesByCourseID)")
' this is the collection of all attendees under the CourseFrom document
Set dcAttendees = vwAttendeesbyCourseID.GetAllDocumentsByKey(docCourseFrom.CourseID(0), True)
bMoved = False
Set docAttendee = dcAttendees.GetFirstDocument
' While there are attendee documents to process and there are available places to goto
While Not docAttendee Is Nothing And 0 < iAvailablePlaces
' if the attendee's status is "Wait Listed" then move them
If Ucase(Trim(docAttendee.Status(0)))= "WAIT LISTED" Then
' Update the course ID for the Attendee
docAttendee.CourseID = docCourseTo.CourseID(0)
If docAttendee.Save(True,True) Then
' decrement the available places
iAvailablePlaces = iAvailablePlaces - 1
bMoved = True
End If
End If
Set docAttendee = dcAttendees.GetNextDocument(docAttendee)
Wend
If bMoved Then
' available places may be >= 0. Just update the available places so you don't over book the course
docCourseTo.availablePlaces = iAvailablePlaces
Call docCourseTo.Save(True,False)
End If
End If
End If
Exit Sub
errHandle:
Messagebox Lsi_info(2) + " - " + Str(Err) + " : " + Error(Err) + ", at line " + Str(Erl)
Exit Sub
End Sub
Key based documents are a little more work but I think are a better structure because you can easily move documents in databases and restore from backups, copy and paste. With response documents you may have issues restoring backups becasue response documents use parent document UNID's to associate themselves to, and also if you move an attendee by accident, it would be impossible to know which course to put the attendee back onto without the original course information, thus leading you back to a key based structure for documents.(But that's just my opinion).....