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

Since I've had to answer this question three times recently, I thought I would blog about it both because it seems to be something people are needing to do, and because that way I have something to send a link to, in future.

There are basically three ways to programatically make changes to design elements in LotusScript:

  • Use the methods and properties that are provided, e.g. NotesForm.FormUsers.
  • If the change you want to make is not supported that way, you can use DXL to export the design element, manipulate the DXL, then re-import it. As yet, this does not work with 100% reliability for all design elements, however, and still not all options are represented.
  • For some properties, you can access the design note with a NotesDocument object and change or delete items that store those properties.
It's the third technique I'm focusing on here.

The first step is to obtain the NotesDocument object representing the design element. If it's a folder or a view, this is how:

Dim db As NotesDatabase
Dim vu As NotesView
Set vu = db.GetView("viewname")
Dim docDesElem As NotesDocument

Set docDesElem = db.GetDocumentByUNID(vu.UniversalID)

If the design element isn't a Notes view, use a NotesNoteCollection to get the note ID. For instance, to locate the design note for an outline you might write:

Function GetOutlineNote(db As NotesDatabase, Byval outlineName$) As NotesDocument
        Dim nnc As NotesNoteCollection
      Set nnc = db.CreateNoteCollection(False)
      nnc.SelectOutlines = True
      nnc.SelectionFormula = {@lowercase($TITLE) = "} & Lcase(Replace(outlineName, Split({\,"}, {,}), Split({\\,\"}, {,}))) & {"}

      If nnc.Count <> 1 Then
              Error 31203, "Outline name " & outlineName & " matched " & nnc.Count & " outlines."

              Set GetOutlineNote db.GetDocumentByID(nnc.GetFirstNoteId)

      End If

End Function

Obviously, similar functions could be written for other types of design elements.

Once you have the NotesDocument representing the design element, you can mess with its items. For instance, the setting for whether a design element is protected from design refresh is the character "P" in the item $Flags. So if you wanted to unprotect design elements from refresh, you could do something like this:

flags = docDesElem.GetItemValue("$Flags")(0)
If Instr(flags, "P") Then
    docDesElem.ReplaceItemValue("$Flags", Replace(flags, "P", ""))
    docDesElem.Save True, False, True
End If

"How do we know to do that?" you might be wondering. One way is to download the C API toolkit from this website -- it includes a file stdnames.h, important parts of which are also copied here. This describes the purposes of all the $Flags values and some $FlagsExt values.

design element properties showing item valuesAnother way is to make the change you want manually, and compare the item values before and after to see what changed. From a view of design elements in Domino Designer press Alt+Enter or use menu File / Properties. Click the second tab to see a list of items in the design note.

Some items are of simple types -- number or text -- and you can replace their values as we did with $Flags above. Others, such as $AssistQuery in an agent, contain binary data which you'll be unable to decode from LotusScript -- but you can still delete the item, or replace it with a copy of an item from another design element of the same type (using CopyItemToDocument).

The other thing you must pay attention to, is whether the item you're modifying is signed. If it is, your modification will invalidate the signature of the design element, and you should re-sign it using the NotesDocument.Sign method before you save it. Otherwise Notes/Domino will refuse to use it. If you're not sure whether you're modifying a signed item, you can use the IsSigned property to check, or you can just sign the document anyway just in case (provided you're running your code with an ID that your users' ECL lists and so on will recognize).

In many cases, the design changes you make aren't noticed by the client until you exit and re-enter the application. The exception is outlines in version 8.0 and later -- there's a method to tell the client to reload these.

Have fun!

Andre Guirard | 7 May 2008 04:35:00 PM ET | | Comments (5)


1) The basics of messing around with design elements
Kevin Pettitt | 5/7/2008 10:16:08 PM

I've made heavy use of this technique in the upcoming SuperNTF release. Did we talk about this already? Anyway, one example is applying header/footer "skins" to a form by creating a bunch of sample forms with nothing to them beyond the bits for defining a header and footer. This is a case where the form items involved are not of simple types, but I simply copyitemtodocument as you discuss and put those items on the target form element. In this case, choosing a header/footer is controlled from the "form configuration" document.

Almost there :-)

2) There is a forth method
Rob Goudvis | 5/8/2008 12:05:20 AM

Andre, you start this blog-entry by stating that there are 3 methods to make changes to a design element. I disagree with you (but I suspect that you were waiting for this, since it is not the first time I mention it) there is a forth method: the C API (and with less possibilities the C++ API). And, you might know already, this is my favorite way of working.

Of course it is not easy this way, but it is very powerful. During my testing I often see the dreaded red box appearing. and sometimes it takes a lot of digging before I am clear what the actual cause was.

A final remark: you mention the possibility to look at the attributes of a design element to see what the result of certain changes will be. I used this technique to find out how to compose the $ViewFormat attribute of a view. This attribute is build based on the view selection formula, the column formulae and some other details. The reason to do so, is that the supplied sample of MakeView in the C SDK is not valid for the newest releases of Notes. Not all parts of the $ViewFormat attribute are defined there. It took me some time, but I am now able to generate a view from scratch, that can be used in Notes 6, 7 and 8.

3) The basics of messing around with design elements
Jaime Bisgrove | 5/8/2008 11:09:13 AM


Thanks for the tip and the link to the Design Pattern flags. Its always better to know than to guess. Any idea when the DXL manipulation will be bolstered or is this really an unsupported benefit of its use?

4) The basics of messing around with design elements
Keith Smillie | 5/8/2008 12:12:48 PM

Hi Andre,

One thing I could never get working when programatically modifying agents was setting the "Run on behalf of" property of an agent.

The item associated with this property appears to be a Text item called $OnBehalfOf.

If the value is initially set via the Agent Security UI then it's easy to update the value, this code does the trick:

call doc.replaceItemValue( "$OnBehalfOf", "CN=Joe Doe/O=Acme" )

call doc.sign()

call true, false )

The agent will now run on behalf of Joe Doe as verified by printing out session.effectiveUserName.

If on the other hand, if the value has never been set via the UI the $OnBehalfOf item doesn't exist. I thought the following piece of code would do the trick:

call doc.replaceItemValue( "$OnBehalfOf", "CN=Joe Doe/O=Acme" )

set item = doc.getFirstItem( "$OnBehalfOf" )

item.isSigned = true

call doc.sign()

call true, false )

However, when I try to run the agent I get the following error:

AMgr: Task initialization failure; loading agent in 'Test.nsf' (Note ID 1B2A): This agent contains an illegally added 'On behalf' attribute. To make the agent valid, please remove it.

Any idea what I'm doing wrong? Is this even possible?


5) The basics of messing around with design elements
Kevin Pettitt | 5/8/2008 3:17:12 PM

Rob Goudvis posted some very cool agent schedule modifying code on this same topic over in the LDD forum ({ Link } ) which might help Keith as well. I'm hoping Rob will post a followup with more usage examples for that code.

6) The basics of messing around with design elements
Andre Guirard | 5/8/2008 5:09:18 PM

Keith, I will answer your question on Monday -- please check back then.

7) The basics of messing around with design elements
Joe Dinda | 5/8/2008 5:32:20 PM

Hi Andre,

I'm having a similar problem to that which Keith is having above. In my case, the C++ API errors out when it tries to open an agent with the "on behalf of" setting set. When I remove the "on behalf of" setting (via the Agent properties dialog box), I can open the agent with C++. Do you have any solutions or workarounds for this? Or do you know if this is a confirmed bug?



 Add a Comment
Comment:  (No HTML - Links will be converted if prefixed http://)
Remember Me?     Cancel

Search this blog 


    About IBM Privacy Contact