Link to home
Start Free TrialLog in
Avatar of scribla
scriblaFlag for United Kingdom of Great Britain and Northern Ireland

asked on

Agent to update all documents in a view

I have implemented some LS provided by Bill Hanson https://www.experts-exchange.com/questions/23301283/View-formula-Attachment-names-only-possible-per-document-or-possible-per-field.html

I am now wondering how to get the LS to update the fields on the 8000+ docs already in the database, I've tried to do this with an agent but I can't seem to do it, is it at all possible?

If Bill is reading this, is it possible to put your PostSave code into a agent? I am hoping to perform this without editing and saving each document if possible?
Avatar of Bill-Hanson
Bill-Hanson
Flag of United States of America image

Sure.

The agent below will do the same thing to all documents in the "DocumentsToUpdate" view (you'll need to change the view name in the code below to the name of a view that contains your documents).

To create the agent...

1) From the designer, select New Agent.
2) Change the type to "LotusScript".
3) If you added the DocGetFileLocations to a script library, then add this line to the agent's "Options" module (replacing "common_functions" with the name of your library):

    Use "common_functions"

4) If you don't have a library, then paste all of the DocGetFileLocations code into the "Declarations" module.
5) Paste the code below into the "Declarations" module.
6) Set the agent's trigger to ""Action menu selection".
7) Set the agent's target to "None".
8) Save and run the agent.
Sub Initialize
	
	Dim sess As New NotesSession
	Dim db As NotesDatabase
	Dim view As NotesView
	Dim doc As NotesDocument
	Dim fileMap List As Variant
	Dim hasDoc As Boolean
	Dim hasXl As Boolean
	
	' Get the view that contains the documents to process
	Set db = sess.CurrentDatabase
	Set view = db.GetView("DocumentsToUpdate")
	Call view.Refresh
	If (view.AllEntries.Count = 0) Then Exit Sub
	
	' Loop through all documents in the view.
	Set doc = view.GetFirstDocument()
	Do While (Not doc Is Nothing)
		Call DocGetFileLocations(doc, fileMap)
		hasDoc = False
		hasXl = True
		If (Isempty(fileMap)) Then
			doc.FileDisplay = "4. No Attachments"
		Else
			Forall fileNames In fileMap
				Select Case Listtag(fileNames)
				Case "WordDocs"
					Forall fileName In fileNames
						If (Right(Lcase(fileName), 4) = ".doc") Then
							hasDoc = True
							Exit Forall
						End If
					End Forall
				Case "ExcelDocs"
					Forall fileName In fileNames
						If (Right(Lcase(fileName), 4) = ".xls") Then
							hasXl = True
							Exit Forall
						End If
					End Forall
				End Select
			End Forall
			If (hasDoc And hasXl) Then
				doc.FileDisplay = "1. DOC & XLS Attached"
			Elseif (hasDoc) Then
				doc.FileDisplay = "2. DOC Attached"
			Elseif (hasXl) Then
				doc.FileDisplay = "3. XLS Attached"
			Else
				doc.FileDisplay = "4. No Attachments"
			End If
		End If
		Call doc.Save(True, False)
		Set doc = view.GetNextDocument(doc)
	Loop
	
End Sub

Open in new window

Avatar of scribla

ASKER

Hi Bill,

A couple of questions:

1. Rather than use a "DocumentsToUpdate" view could I not just run the agent against selected documents? as I'd prefer this method if possible.

2. I did indeed add the DocGetFileLocations to the script library. However I have changed your original example slightly as follows below. Just to prevent complete disaster when I try and run the agent, could you apply what I have done to your example above? I guess it should just be a copy and paste job on the IF/Else/Elseif sections, but I'd like you to confirm that what I have done to your example wont misbehave inside the agent.
Sub Postsave(Source As Notesuidocument)
	
      ' Save file metadata.
	Dim doc As NotesDocument
	Dim fileMap List As Variant
	Dim hasQuote As Boolean
	Dim hasCSS As Boolean
	Dim hasOA As Boolean
	Set doc = Source.Document
	Call DocGetFileLocations(doc, fileMap)
	If (Isempty(fileMap)) Then
		doc.FileDisplay = "No Attachments"
	Else
		Forall fileNames In fileMap
			Select Case Listtag(fileNames)
			Case "QuotationDocument"
				Forall fileName In fileNames
					If (Right(Lcase(fileName), 4) = ".doc") Then
						hasQuote = True
						Exit Forall
					End If
				End Forall
			Case "CostingSheet"
				Forall fileName In fileNames
					If (Right(Lcase(fileName), 4) = ".xls") Then
						hasCSS = True
						Exit Forall
					End If
				End Forall
			Case "OrderAcknowledgement"
				Forall fileName In fileNames
					If (Right(Lcase(fileName), 4) = ".doc") Then
						hasOA = True
						Exit Forall
					End If
				End Forall
			End Select
		End Forall
		If (hasQuote) Then
			doc.QuoteAttached = "Yes"
		Else 
			doc.QuoteAttached = "No"
		End If			
		If (hasCSS) Then
			doc.CSSAttached = "Yes"
		Else 
			doc.CSSAttached = "No"
		End If			
		If (hasOA) Then
			doc.OrderAckAttached = "Yes"
		Else 
			doc.OrderAckAttached = "No"
			
		End If
	End If			
	
	Call doc.Save(True, False)
	
End Sub

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Bill-Hanson
Bill-Hanson
Flag of United States of America image

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
Avatar of scribla

ASKER

Very sorry for leaving this question, it has not been abandoned, I've just been busy with another project.
I'm having a play with your code examples now.
Avatar of scribla

ASKER

I didn't get very far I'm afraid. I created a new lotus script library and pasted your 'UpdateFileData' code in, when I save it says "Untitled: UpdateFileData: 7: Not a sub or function name: GETDOCFILELOCATIONS"

Line 7 = Call DocGetFileLocations(doc, fileMap)

I do have DocGetFileLocations saved in my script library already, so I don't understand what this problem is.
It's hard to say what the problem is without seeing your code.  Please post the entire library.
Avatar of scribla

ASKER

My bad, I was trying to create a new library.. Now pasted into the original library along side GetDocFileLocations and no error.
Avatar of scribla

ASKER

I have got as far as step 3. Creating the agent. When I try and save the agent I get the error "Not a sub or function name: UPDATEFILEDATA"

Not sure I've gone about this the right way. At the moment I have a single doc/object in my script library called 'DocGetFileLocations'

This contains:

GetDocFileLocations
ArrayAdd
ArrayAppendEx
ArrayElements
ArrayTrimArray
ArrayIsMember
ArrayCreate
UpdateFileData

The code for GetDocFileLocations is as follows in code snippet below. UpdateFileData is as you code snippet posted above.
Sub DocGetFileLocations(doc As NotesDocument, fileMap List As Variant)
	
	'/**
	' * Locates all file attachments in a document and returns the result in a hash table (list).
	' * @param doc The document that contains the attachments.
	' * @param fileList (Return) A hash table (list) used to store and return the results of this function.
	' */
	
	Dim allFiles As Variant ' all files embedded within the specified document regardless of which (if any) richtext field contains them.
	Dim rtFiles As Variant ' files found embedded within any rich text field.
	Erase fileMap ' clear the return param.
	
	' Get all attachment names.
	allFiles = ArrayTrimArray(Evaluate("@AttachmentNames", doc))
	If (Isempty(allFiles)) Then Exit Sub
	
	' Check all richtext items for embedded files.
	Forall item In doc.Items
		If (item.Type = RICHTEXT) Then
			If (Not Isempty(item.EmbeddedObjects)) Then
				Forall obj In item.EmbeddedObjects
					fileMap(item.Name) = ArrayAdd(fileMap(item.Name), obj.Name)
					rtFiles = ArrayAdd(rtFiles, obj.Name)
				End Forall
			End If
		End If
	End Forall
	
	' Get the files that are not embedded within an item.
	Forall file In allFiles
		If (Not ArrayIsMember(rtFiles, file, False)) Then
			fileMap("$DOCUMENT") = ArrayAdd(fileMap("$DOCUMENT"), file)
		End If
	End Forall
	
End Sub

Open in new window

Did you remember to include the library by adding a "Use" statement in the agent's "Options" module?

    Use "DocGetFileLocations"

If you already included the library, please post the agent code for me to evaluate.
Avatar of scribla

ASKER


Thats works great, thanks for bearing with me on this one.
I have some other functions I'd live to implement based on this code, I'll put questions up in due course.

Dan.
Avatar of scribla

ASKER

Many thanks once again Bill.
No problem.  Glad to help.