Skip to Content

As described in How to set up Generic Workflow Handling in Alloy, sometimes it might be necessary to add a bit more generic to the delivered Alloy workflow forms, in order to save implementation efforts.
One way of adding more generic to the Alloy forms is described in How to set up Generic Workflow Handling in Alloy.

In a summary:

  • Use one or two predefined fields to add the relevant business object data in those fields (do this by using a custom Alloy Outbound Handler (see How to set up Generic Workflow Handling in Alloy for an example)).
  • The data inside these fields is separated by some agreed separators. (here: colon and semicolon)
  • Add a simple Lotus Script to the delivered (ERPApprovalWorkflow) form that parses the content (of the predefined fields) and extracts it in order to display the data in a HTML table

Let’s see this in real life. After adding the custom Alloy Outbound Handler (here: Z_S_OSP_WF_PO1_CH_OB), the Alloy workflow note comes with two additional fields: WF_HEADER and WF_ITEMS.
Additional fields to Alloy workflow note

The content in these two fields is separated by colons and semicolons, as described by How to set up Generic Workflow Handling in Alloy.
The below given Lotus Script code parses these fields, extracts the data and creates a HTML table with that data.

|) Call HFstream.WriteText(||) Call HFstream.WriteText(||) Call HFstream.WriteText(||) ‘ The HTML table Call HFstream.WriteText(||) Forall headerIndex In header Call HFstream.WriteText(||) End Forall Call HFstream.WriteText(|

| & headerIndex.name & | | & headerIndex.value & |

|) Call HFstream.WriteText(||) Call HFmimeChild.SetContentFromText(HFstream,”text/html”,ENC_NONE) Call HFstream.Close() Call HFstream.Truncate ‘ —————————————————————————————————————————————————————- ‘ Print items to stream Dim IFmime As NotesMimeEntity Dim IFmimeChild As NotesMimeEntity Dim IFmimeHeader As NotesMimeHeader Dim IFstream As NotesStream Set IFmime = doc.GetMIMEEntity(“ItemField”) If( IFmime Is Nothing) Then Set IFmime = doc.CreateMIMEEntity(“ItemField”) End If Set IFmimeHeader = IFmime.CreateHeader(“Content-Type”) Call IFmimeHeader.SetHeaderVal(“multipart/mixed”) Set IFmimeChild = IFmime.CreateChildEntity Set IFstream = session.CreateStream ‘ HTML header for CSS Call IFstream.WriteText(“”) Call IFstream.WriteText(||) Call IFstream.WriteText(||) Call IFstream.WriteText(||) ‘ HTML table Call IFstream.WriteText(||) Dim hc As Integer Forall itemE In items If( hc = 0 ) Then Call IFstream.WriteText(||) Else Call IFstream.WriteText(||) End If For i = 1 To columns If( hc = 0 ) Then Call IFstream.WriteText(||) Else Call IFstream.WriteText(||) End If Next Call IFstream.WriteText(||) If( hc = 0 ) Then hc = hc +1 End If End Forall Call IFstream.WriteText(|

| & itemE(i) & | | & itemE(i) & |

|) Call IFstream.WriteText(||) Call IFmimeChild.SetContentFromText(IFstream,”text/html”,ENC_NONE) Call IFstream.Close() Call IFstream.Truncate Call doc.CloseMIMEEntities(True) Call doc.Save(True, False, False) End Sub Sub LoadHeaderData(doc As NotesDocument) Dim Token As String Dim s As String Dim TestHeaderString As String ‘TestHeaderString = “Key1;Value1:Key2;Value2:Key3;Value3:” ‘ Dim workspace As New NotesUIWorkspace ‘ Dim doc As NotesDocument ‘ Set doc = workspace.CurrentDocument.Document If( doc.HasItem(“WF_HEADER”) ) Then TestHeaderString = doc.GetItemValue(“WF_HEADER”)(0) Else TestHeaderString = doc.GetItemValue(“WorkflowContainer00WF_HEADER”)(0) End If ‘ TestHeaderString = doc.GetItemValue(“WF_HEADER”)(0) Token = “bla” Dim headerIndex As Integer headerIndex = 1 Do While Not Token = “” Token = Strtoken(TestHeaderString, “:”, headerIndex) If Not (Token = “”) Then s = Strtoken(Token, “;”,1) header(headerIndex).name=s s = Strtoken(Token, “;”,2) header(headerIndex).value=s headerIndex = headerIndex +1 End If Loop End Sub Sub LoadItemData(doc As NotesDocument) Dim Token As String Dim s As String Dim itemIndex As Integer Dim sIndex As Integer Dim TestItemString As String ‘TestItemString = “Header1;Header2;Header3:Key2;Value21;Value22:Key3;Value31;Value32:” If( doc.HasItem(“WF_ITEMS”) ) Then TestItemString = doc.GetItemValue(“WF_ITEMS”)(0) Else TestItemString = doc.GetItemValue(“WorkflowContainer00WF_ITEMS”)(0) End If ‘TestItemString = doc.GetItemValue(“WF_ITEMS”)(0) ‘ First data entry is table header ‘ Assumption is that no table header contains an empty string s = “bla” sIndex = 1 Token = Strtoken(TestItemString, “:”, 1) If Not (Token = “”) Then ‘ Get column number Do While Not s = “” s = Strtoken(Token, “;”, sIndex) If Not ( s = “”) Then columns = columns +1 sIndex = sIndex +1 End If Loop sIndex = 1 s = “bla” Redim itemEntry(1 To columns) As String ‘ Set size and clear array Do While Not s = “” s = Strtoken(Token, “;”, sIndex) If Not ( s = “”) Then itemEntry(sIndex) = s sIndex = sIndex +1 End If Loop items(1) = itemEntry Else ‘ Unable to parse table header…so we do not know how many columns we need Exit Sub End If itemIndex = 2 Dim i As Integer Do While Not Token = “” Token = Strtoken(TestItemString, “:”, itemIndex) If Not (Token = “”) Then Redim itemEntry(1 To columns) As String ‘ Set size and clear array For i = 1 To columns s = Strtoken(Token, “;”, i) If Not ( s = “”) Then itemEntry(i) = s End If Next items(itemIndex) = itemEntry itemIndex = itemIndex + 1 End If Loop End Sub

Place a call to the DisplayReport function in the QueryOpen part of your (ERPApprovalWorkflow) form (or better: make a copy of it and use the copy) to make sure the script is called, once the form is opened.

If the script is called the first time on a document, it reads out the WF_HEADER and WF_ITEMS data, and creates a HTML table out of it. The HTML data is stored in the Notes document, so that we don’t need to parse the data a second time in case the form is opened again.
Additional fields created by Lotus Script

In order to display the header and item HTML data, two rich text fields are added to (ERPApprovalWorkflow) that have the same name as the stored HTML data fields in the Notes document.
Additional fields to notes form

For sure this example can be enhanced. E.g. it should be ensured that the separator characters colon and semicolon are escaped properly, the Lotus Script coding could be moved to the CustomAgent section of the Domino Workflow configuration and so on and so forth.

The result

To report this post you need to login first.

4 Comments

You must be Logged on to comment or reply to a post.

  1. Theo Aemmer
    Hi Dirk
    The Lotusscript is not working, the global header and item definition are missing. They would descripe how those variables are composed. Could you please profide this information. This is the last pice of the puzzle and then our ALLOY work should work!

    Many thanks

    (0) 
    1. Dirk Lehmann Post author
      Hi Theo,

      you’re absolutly right.

      Here’s the missing part:

      <—snip—>

      Dim UpdateCheck As String

      Type t_headerRow
      name As String
      value As String
      End Type

      Dim header List As t_headerRow

      Dim items List As Variant
      Dim itemEntries() As String
      Dim columns As Integer

      Dim authorizedEntry As Integer

      <—snap—>

      Hope this helps

      Best regards

      Dirk

      (0) 
  2. Dirk Lehmann Post author
    Hi all,

    as you might notice the above listed solution works on the client side. So the HTML rendering is done on every notes client.
    If you wanna run the solution server-side, create a new agent in NDERPws.nsf. Here’s the agents listing:

    Declaration part:
    ———————————————
    Dim UpdateCheck As String

    Type t_headerRow
    name As String
    value As String
    End Type

    Dim header List As t_headerRow

    Dim items List As Variant
    Dim itemEntries() As String
    Dim columns As Integer

    Dim authorizedEntry As Integer
    ———————————————

    Initialize function:
    ———————————————
    Sub Initialize
    Dim tempdir$, h_filename$, i_filename$, h_fn%, i_fn%
    Dim preview As Integer
    Dim i As Integer

    Dim header List As t_headerRow
    Dim items List As Variant
    Dim itemEntries() As String
    Dim columns As Integer

    ‘ Create session
    Dim session As New NotesSession
    session.ConvertMime = False

    Dim agent As NotesAgent
    Set agent = session.CurrentAgent

    Dim db As NotesDatabase
    Set db = session.CurrentDatabase

    ‘ Get NotesDocument
    Dim doc As NotesDocument
    Set doc = db.GetDocumentByID(agent.ParameterDocID)

    doc.RemoveItem(“body”)


    ‘ —————————————————————————————————————————————————————-
    ‘ Load HeaderData

    Dim Token As String
    Dim s As String

    Dim TestHeaderString As String

    If( doc.HasItem(“WF_HEADER”) ) Then
    TestHeaderString = doc.GetItemValue(“WF_HEADER”)(0)
    Else
    TestHeaderString = doc.GetItemValue(“WorkflowContainer00WF_HEADER”)(0)
    End If


    Token = “bla”
    Dim headerI As Integer
    headerI = 1
    Do While Not Token = “”
    Token = Strtoken(TestHeaderString, “:”, headerI)
    If Not (Token = “”) Then
    s = Strtoken(Token, “;”,1)
    header(headerI).name=s
    s = Strtoken(Token, “;”,2)
    header(headerI).value=s
    headerI = headerI +1
    End If
    Loop

    ‘ —————————————————————————————————————————————————————-
    ‘ Load ItemData

    Dim itemIndex As Integer
    Dim sIndex As Integer

    Dim TestItemString As String

    If( doc.HasItem(“WF_ITEMS”) ) Then
    TestItemString = doc.GetItemValue(“WF_ITEMS”)(0)
    Else
    TestItemString = doc.GetItemValue(“WorkflowContainer00WF_ITEMS”)(0)
    End If

    s = “bla”
    sIndex = 1
    Token = Strtoken(TestItemString, “:”, 1)
    If Not (Token = “”) Then
    ‘ Get column number
    Do While Not s = “”
    s = Strtoken(Token, “;”, sIndex)
    If Not ( s = “”) Then
    columns = columns +1
    sIndex = sIndex +1
    End If
    Loop

    sIndex = 1
    s = “bla”
    Redim itemEntry(1 To columns) As String ‘ Set size and clear array
    Do While Not s = “”
    s = Strtoken(Token, “;”, sIndex)
    If Not ( s = “”) Then
    itemEntry(sIndex) = s
    sIndex = sIndex +1
    End If
    Loop
    items(1) = itemEntry
    Else
    ‘ Unable to parse table header…so we do not know how many columns we need
    Exit Sub
    End If

    itemIndex = 2
    Do While Not Token = “”
    Token = Strtoken(TestItemString, “:”, itemIndex)
    If Not (Token = “”) Then
    Redim itemEntry(1 To columns) As String ‘ Set size and clear array
    For i = 1 To columns
    s = Strtoken(Token, “;”, i)
    If Not ( s = “”) Then
    itemEntry(i) = s
    End If
    Next
    items(itemIndex) = itemEntry
    itemIndex = itemIndex + 1
    End If
    Loop

    ‘ —————————————————————————————————————————————————————-

    ‘ Print header into stream
    Dim body As NotesMimeEntity
    Dim HFmimeChild As NotesMimeEntity
    Dim HFmimeHeader As NotesMimeHeader
    Dim HFstream As NotesStream

    Set body = doc.CreateMIMEEntity(“body”)
    Set HFmimeHeader = body.CreateHeader(“Content-Type”)
    Call HFmimeHeader.SetHeaderVal(“text/html”)

    Set HFmimeChild = body.CreateChildEntity

    Set HFstream = session.CreateStream

    ‘ HTML Header for CSS
    Call HFstream.WriteText(||)
    Call HFstream.WriteText(||)
    Call HFstream.WriteText(||)

    Call HFstream.WriteText(||)

    ‘ The Header HTML table
    Call HFstream.WriteText(||)
    Forall headerIndex In header
    Call HFstream.WriteText(||)
    End Forall
    Call HFstream.WriteText(|

    | & headerIndex.name & | | & headerIndex.value & |

    |)

    ‘ Item HTML table
    Call HFstream.WriteText(||)
    Dim hc As Integer
    Forall itemE In items
    If( hc = 0 ) Then
    Call HFstream.WriteText(||)
    Else
    Call HFstream.WriteText(||)
    End If
    For i = 1 To columns
    If( hc = 0 ) Then
    Call HFstream.WriteText(||)
    Else
    Call HFstream.WriteText(||)
    End If
    Next
    Call HFstream.WriteText(||)
    If( hc = 0 ) Then
    hc = hc +1
    End If
    End Forall

    Call HFstream.WriteText(|

    | & itemE(i) & | | & itemE(i) & |

    |)

    Call HFstream.WriteText(||)

    Call HFmimeChild.SetContentFromText(HFstream,”text/html”,ENC_NONE)
    Call HFstream.Close()
    Call HFstream.Truncate

    ‘ —————————————————————————————————————————————————————-

    Call doc.CloseMIMEEntities(True)
    Call doc.Save(True, False, False)
    End Sub

    ———————————————

    Save the agent, and put it in the “Custom agent” field on Dominos’ workflow application configuration (where you set the BoundItem Type, etc. ).

    Doing it that way, the agent is executed on server side, while creating the end-users work item.

    Hope this helps…

    Best regards

    Dirk

    (0) 

Leave a Reply