Skip to main content
    Country/region select      Terms of use
     Home      Products      Services & solutions      Support & downloads      My account     

developerWorks  >  Lotus  >  Forums & community  >  Best Practice Makes Perfect

Best Practice Makes Perfect

A collaboration with Domino developers about how to do it and how to get it right in Domino

A recent question in the Notes 6 & 7 forum on dW, got me thinking that I should document the process for attaching a file to a document that's being edited, in cases where the file is produced by LotusScript code.

The challenge is that LotusScript doesn't provide a way to attach a file to a document that's in edit mode (if it existed, it would be a method of the NotesUIDocument class).

There are two ways that you can create a file attachment automatically:

  • NotesRichTextItem.EmbedObject: the problem is that since rich text doesn't update on screen when you update it in the back end, using this method requires that you also engage in some gymnastics to cause the new attachment to appear on screen, as described in the Update rich text tip. This is certainly one way to get the job done, but there are drawbacks to this method also, including that it causes Queryclose, Queryopen, Postopen form events to update and loses the values of any global variables you may be holding in LotusScript.
  • In macro language, @Command([EditInsertFileAttachment]; filename) works, but macro language often isn't powerful enough to come up with the filename automatically; you might have to search on disk for the file, or maybe the file doesn't exist yet and you have to create it , then attach it. For instance, it might be a report in a spreadsheet that you create through OLE automation, then want to attach to the document where you specified the report parameters.
My preferred solution uses the macro @Command in combination with LotusScript. To make this work, you need three pieces of code:
  • The LotusScript agent, which produces the file and records its location in an environment variable, a secret field of the document, a profile field, or anywhere else that macro language can get the information.
  • A macro language agent, which looks for the filepath and, if one has been supplied, uses it to create the attachment.
  • A two-line formula to call the two agents.
So for instance, the LotusScript agent would be:

   Dim wksp As New NotesUIWorkspace
   Dim uidoc As NotesUIDocument
   Set uidoc = wksp.CurrentDocument
Dim strFilepath$
' at this point, create your file and store the path in strFilepath (or exit early to abort creating the attachment).
   uidoc.Document.ReplaceItemValue "PathToAttach", strFilepath
End Sub

Of course I have left out the complicated part, creating the file, because there are so many different ways you might do this.The formula agent is:

@If(PathToAttach != "";
      @Command([EditBottom]); { or EditGotoField, or whatever you need to do to position the insertion point if it's not already where you wanted it.};
      @Command([EditInsertFileAttachment]; PathToAttach; "1");
      FIELD PathToAttach := @Unavailable

And the code to call them (which might be in an action button) is:

@Command([ToolsRunMacro]; "(ImportFile)")

I've experimented around with this a little, and I've found that you really have to do it just this way. There are a couple of things you might think to try that don't work, so I'll save you time and list them.
  • Having the first agent call the second agent directly, fails with the message, "Notes error: @Function is not valid in this context". The agent called by "Run" method is not supposed to interact with the user, and all @Commands are presumed to have UI interaction so they are prohibited when the agent is called with Run.
  • Having the first agent use NotesUIDocument methods to position the insertion point, makes the EditInsertFileAttachment command fail without an error message. Apparently, if you touch the rich text in any way with NotesUIDocument, it's left in an "pending" state until all code stops running, at which point the pending updates to rich text content and cursor are displayed. Putting up a dialog to the user will also finish up the rich text changes and let the attach operation proceed, but of course opening a dialog is what we usually wanted to avoid by doing all this! Just let the macro code position the cursor.
  • Don't forget to erase the filepath from wherever it's stored after the attachment is created, so that if the first agent fails (and fails to erase the value), the second agent doesn't attempt to attach a file anyway. Also, of course, there's usually no need to store this filepath in the document, so save space and increase performance by removing it.
  • You might think to check PathToAttach in the agent-calling macro and just don't call the second agent if there's no file to attach. The problem is that this formula has cached the field values that were current at the time the agent started running -- it doesn't see the change that the first agent makes to the PathToAttach field. This might work if you used an environment variable, but I tend to think a form field is neater, less code, etcetera, even though it does mean that you sometimes call the second agent unnecessarily.
  • The PathToAttach field shouldn't appear on the form. This works without doing that, and why make your form more complex unnecessarily? With the field not on the form, the second agent can delete it (@Unavailable) without it coming back when you save (available, but value is "")

Andre Guirard | 9 November 2007 03:04:03 PM ET | Plymouth, MN, USA | Comments (8)

Search this blog 


    About IBM Privacy Contact