Tuesday, July 25, 2017

SharePoint Workflows: Going Against the Flow #1

My latest project has me working with SharePoint workflows. In this case, I have some JavaScript that I wrote that uses PDF.js to see if a PDF document has been signed, how many signatures are present, and which names are associated with those signatures. (My thanks to PKJIS for a working example that gave me a good launching point.) The JavaScript uses the SharePoint API to retrieve the list of people that are supposed to sign the document and the list of people that are supposed to be notified when a signature is affixed to the document before storing this information as metadata for the document.

These modifications to the metadata then fire off a SharePoint workflow. If you've worked with SharePoint workflows, you know that they have some serious shortcomings, especially if you can't use Visual Studio to build workflow functionality in C#.

The JavaScript stores the names of the people who signed the document in a "Multiple Lines of Text" field; each name is on its own line. The metadata for the document includes a field called "Last Count" that is only updated by the SharePoint workflow. When the document is changed, the SharePoint workflow counts the number of lines in the Signatures field and compares that count with "Last Count". If the two values are different, an email is sent out to the person who should sign the document next and the people that are monitoring the signatures.

Here is what the workhorse portion of the workflow looks like:

  1. Set Variable: CountSignatures to 0.
  2. then Set Variable: CountCompleted to No.
  3. then Set Variable: IndexNextSignature to 0.
  4. Loop: through Signatures
    The contents of this loop will run repeatedly while Variable: CountCompleted equals No
    1. Copy from Current Item:Signatures, starting at Variable: IndexNextSignature (Output to Variable: TempSignatures)
    2. If Variable: TempSignatures is not empty
      1. Replace \n in Variable: TempSignatures (Output to Variable: TempSignatures)
      2. Find <br> in Variable: TempSignatures (Output to Variable: FindTag)
      3. then Calculate Variable: CountSignatures plus 1 (Output to Variable: CountIncremented)
      4. then Set Variable: CountSignatures to Variable: CountIncremented
      5. If Variable: FindTag is greater than or equal to 0
        1. Set Variable: LengthNextSignature to Variable: FindTag
        2. then Calculate Variable: LengthNextSignature plus 4 (Output to Variable: LengthIncremented)
        1. Set Variable: CountCompleted to Yes
      1. Set Variable: CountCompleted to Yes
    3. If Variable: CountCompleted equals No
      1. Calculate Variable: IndexNextSignature plus Variable: LengthIncremented (Output to Variable: IndexIncremented)
      2. then Set Variable: IndexNextSignature to Variable: IndexIncremented

I can do all of this in one line of JavaScript code:

var countSignatures = signatures.replace(/\n+/g, "<br>").split("<br>").length;

What's more, I don't have to worry about whether the signatures variable is empty or not. SharePoint throws an exception if you try to use the "Find Substring in String" action and either string is empty. If Substring is empty, you get a "Divide-by-Zero" error message; if String is empty, you get a "Value cannot be null" message.