Skip navigation
All Places > Getting Started > Blog > 2018 > June
2018

For a long time, we have been plagued by times in InfoPath forms jumping forward by an hour during daylight saving time after amending the metadata fields.

Investigation shows that the datetime value written back to the form contains a modifier telling SharePoint that the time is recorded as being GMT (and thus an hour needs to be added to make it ‘correct’ again).

Date field in InfoPath form

<my:StartDate>2018-05-23T00:00:00Z</my:StartDate>

The solution was to use Nintex to create a workflow that rewrites the date fields after change to remove the ‘Z’ character.

The workflow could either run on any change – or fine tune it to run only when one of the affected fields change value

The action is to

  • Retrieve the field value from the xml document
  • Test if it contains a ‘Z’
    • If it does, write it back without the ‘Z’

As it runs immediately after a change, it is worth starting the workflow with a ‘Commit pending changes’

The first step is to read the xml document associated with the current item, so insert a Query XML task – ensure the source is the Current Item; return the result as Text, to a temporary string variable

In the Output, set ‘Process using’ to XPath and click the XPath Builder button and navigate through your form’s xml to the field

When you reach it, select it and click the Apply button and something like this will be returned

 

Now test strTest in a Run If

Within the Run If, add an Update XML task

You can copy/paste the field reference from the Query XML task

You then replace the node content with the item value for the field, replacing the ‘Z’ with a blank

Note that the FormatDate function returns the date/time in the same format as that stored within the xml.

Now repeat this for each affected field.

graham

Nintex Workflow – Fast Loops

Posted by graham Jun 12, 2018

Recently I needed to create a schedule of dates, one week apart. I created a loop and added 7 days in each iteration. I noticed it took a very long time, so I added a Log in History task in the loop and saw that each iteration was taking 5 minutes. I realized that this was down to ‘Safe Looping’.

This protective feature places some safety measures against the hazards of an infinite loop by adding a hidden delay..

I didn’t want to disable this option, mainly because of the maintenance overhead involved, so I looked for another option.

I realised that the Collection iteration (For Each) didn’t have any such restriction, so all I needed was to create a collection with the number of entries that I wanted to loop for.

The Regular Expression task with the Split operator is the easiest way to create a collection; it simply splits text based on a character. All I had to do was to create a string with the right number of delimiters.

This is where I got the idea for this article https://community.nintex.com/community/build-your-own/blog/2018/06/08/nintex-string-repeat.

Now, as n delimiters will create n+ 1 entries, we need to reduce the number of delimiters by 1

Initialising the string to a non-delimiter will ensure that the string is padded to length ‘Iterations’ containing n-1 delimiters.

Regular Expression

For each

 

We place the retrieved value in TempStr variable and ignore it.

Calculate date:

Here’s where we add the recurrent +7 days added on each loop

The final workflow

 

 

I set the Iterations variable to be a startup parameter and set it to 10

Here are the results from the history - as you can see, it all executed immediately

 

Time

Event

Message

11/05/2018 10:49

Workflow Comment

MyDate=18/05/2018 10:49

11/05/2018 10:49

Workflow Comment

MyDate=25/05/2018 10:49

11/05/2018 10:49

Workflow Comment

MyDate=01/06/2018 10:49

11/05/2018 10:49

Workflow Comment

MyDate=08/06/2018 10:49

11/05/2018 10:49

Workflow Comment

MyDate=15/06/2018 10:49

11/05/2018 10:49

Workflow Comment

MyDate=22/06/2018 10:49

11/05/2018 10:49

Workflow Comment

MyDate=29/06/2018 10:49

11/05/2018 10:49

Workflow Comment

MyDate=06/07/2018 10:49

11/05/2018 10:49

Workflow Comment

MyDate=13/07/2018 10:49

11/05/2018 10:49

Workflow Comment

MyDate=20/07/2018 10:49

 

 

graham

Nintex String-Repeat

Posted by graham Jun 8, 2018

I recently needed a String-Repeat function in a workflow. But it doesn’t exist.

Or does it?

Looking at the inline function specifications, I saw that the PadLeft function (and PadRight) adds a number of characters to a string, until the string length is the desired number of characters long.

If you needed just a specific number of characters (lets say ‘-‘ chars), then the following

fn-PadLeft(-,15,-)

 

Will result in a string of 15 ‘-‘ characters

Now, you cannot tell it to pad out with a string of more than 1 character (it actually returns the text of the function definition when you try), so you need to be a little more clever to give a string of 15 repetitions of ‘Graham’ for example

We create a string of 15 ‘-‘ characters then replace each ‘-‘ with the longer text that we want to repeat in a RegEx task.

graham

Workflow Approvals Dashboard

Posted by graham Jun 5, 2018

This article is not strictly Nintex, as it could apply to any workflow engine.

We manage our Change Control process using InfoPath forms and Nintex workflow.

For a management overview and reminder for when approval request emails are missed, we needed a dashboard page that would show all outstanding approvals and those assigned to the current user.

Two methods were identified to provide this functionality – the Nintex webparts and custom list views of the WorkflowTasks list.

This is a summary of our requirements

Requirement

Nintex Webpart

Custom Listview

Display the ID of the item being approved

N

N

Link the item being approved to open in the browser

Y

N

Group all approvals for each item

N

Y

Ability to Approve from the page

Y

Y

Ability to Delegate from the page

N

Y

 

Whilst the Nintex webpart allows the current user to respond to a task if s/he is the one to whom the task was assigned, the Terminate Workflow option is visible and could cause problems - and the Delegate user was not available at al.

Our first attempt to solve this was to add a column to the WorkflowTask list and have a workflow paste in the relevant information each time a task was created. Big mistake – we had no end of ‘Task is locked by a workflow’ errors and resulted in delays of hours before an approval could be given.

Returning to the List Views, because the views are grouped, we did not want the name of the grouping field to be repeated in each group, so we used the JScript found here -> http://bistesh.blogspot.co.uk/2014/04/sharepoint-20132010-remove-columns-name.html and added it to a CEWP. We used this code as a basis to edit the url of the Related Content to use the InfoPath form server.

It also amends the standard message:

'There are no items to show in this view of the "Workflow Tasks" list. To add a new item, click "New".'

To show

'You have no outstanding approvals'

 

We wanted to be able to show the ID of the related content.

Research indicated that SP 2013 held a field called WorkflowItemId – a Content Query webpart (CQWP) was created using the debugging style to retrieve a field of this name and found it existed in SharePoint 2010 and was populated with the ID value.

Debugging XSLT

<xsl:template name="debugCustomStyle" match="Row[@Style='dCustomStyle']" mode="itemstyle">

<!-- shows all the fields supplied and their names  -->

<xsl:for-each select="@*">

F:

<xsl:value-of select="name()" />

=

<xsl:value-of select="." />

+

<br />

</xsl:for-each>

<xsl:call-template name="repeatstr">

<xsl:with-param name="num" select="20" />

<xsl:with-param name="str" select="'-'" />

</xsl:call-template>

<br />

<!-- shows all the nodes supplied and their names  -->

<xsl:for-each select="//*">

F:

<xsl:value-of select="name()" />

=

<xsl:value-of select="." />

+

<br />

</xsl:for-each>

<xsl:call-template name="repeatstr">

<xsl:with-param name="num" select="50" />

<xsl:with-param name="str" select="'='" />

</xsl:call-template>

<br />

</xsl:template>

 

The Property CommonViewFields of the webpart source was set to include all the wanted fields (it is imperative that the case matches the definition, otherwise it will not be recognised).

<property name="CommonViewFields" type="string">Title;WorkflowName;WorkflowLink;AssignedTo;Related Content;WorkflowListId;WorkflowItemId</property>

The next thing was to show it in the view – this field is not selectable as it is hidden. The answer was to export the ListView webpart (see Export a List Webpart at the end) and edit the embedded view

<property name="XmlDefinition" type="string">&lt;View Name="{CE1736B1-205B-42D4-99B6-AE5D5F723D18}" MobileView="TRUE" Type="HTML" Hidden="TRUE" TabularView="FALSE" DisplayName="" Url="[redacted]" Level="255" BaseViewID="1" ContentTypeID="0x" ImageUrl="/_layouts/images/issues.png"&gt;&lt;Query&gt;&lt;GroupBy Collapse="FALSE" GroupLimit="30"&gt;&lt;FieldRef Name="WorkflowItemId"/&gt;&lt;/GroupBy&gt;&lt;OrderBy&gt;&lt;FieldRef Name="WorkflowItemId" Ascending="FALSE"/&gt;&lt;FieldRef Name="AssignedTo"/&gt;&lt;/OrderBy&gt;&lt;Where&gt;&lt;Eq&gt;&lt;FieldRef Name="WorkflowOutcome"/&gt;&lt;Value Type="Text"&gt;Pending&lt;/Value&gt;&lt;/Eq&gt;&lt;/Where&gt;&lt;/Query&gt;&lt;ViewFields&gt;&lt;FieldRef Name="WorkflowItemId"/&gt;&lt;FieldRef Name="WorkflowLink"/&gt;&lt;FieldRef Name="WorkflowName"/&gt;&lt;FieldRef Name="Created"/&gt;&lt;FieldRef Name="AssignedTo"/&gt;&lt;FieldRef Name="LinkTitle"/&gt;&lt;/ViewFields&gt;&lt;RowLimit Paged="TRUE"&gt;30&lt;/RowLimit&gt;&lt;Aggregations Value="Off"/&gt;&lt;ViewStyle ID="17"/&gt;&lt;Toolbar Type="None"/&gt;&lt;/View&gt;</property>

 

When html un-encoded and reformatted, it looks like this

<View Name="{CE1736B1-205B-42D4-99B6-AE5D5F723D18}" MobileView="TRUE" Type="HTML" Hidden="TRUE" TabularView="FALSE" DisplayName="" Url="[redacted]" Level="255" BaseViewID="1" ContentTypeID="0x" ImageUrl="/_layouts/images/issues.png">

   <Query>

     <GroupBy Collapse="FALSE" GroupLimit="30">

         <FieldRef Name="WorkflowItemId" />

     </GroupBy>

     <OrderBy>

         <FieldRef Name="WorkflowItemId" Ascending="FALSE" />

         <FieldRef Name="AssignedTo" />

     </OrderBy>

     <Where>

         <Eq>

           <FieldRef Name="WorkflowOutcome" />

           <Value Type="Text">Pending</Value>

         </Eq>

     </Where>

   </Query>

   <ViewFields>

     <FieldRef Name="WorkflowItemId" />

     <FieldRef Name="WorkflowLink" />

     <FieldRef Name="WorkflowName" />

     <FieldRef Name="Created" />

     <FieldRef Name="AssignedTo" />

     <FieldRef Name="LinkTitle" />

   </ViewFields>

   <RowLimit Paged="TRUE">30</RowLimit>

   <Aggregations Value="Off" />

   <ViewStyle ID="17" />

   <Toolbar Type="None" />

</View>

 

This makes it a lot easier to read, understand and amend – this will need to be re-edited to remove unnecessary whitespace and carriage returns, then html encoded (or the tag can be set up to be a CDATA entry).

I recommend that you use the field Status as a substitute field, then find/replace it with WorkflowItemId – this should prevent errors when editing the encoded xml.

So the new field WorkflowItemId is added to the view fields and used as the Group By value.

After the webpart(s) have been re-uploaded, if you Edit Webpart and Edit current view, the fields will appear in their correct locations.

The My Approvals – with no assigned approvals

All Approvals

The full jscript is shown here

_spBodyOnLoadFunctionNames.push("HideHeaders");

 function HideHeaders() {   

    var elem;   

    var elements = getElementsByClassName(document, "td", "ms-gb");

    for (var i = 0; i &lt; elements.length; i++) {

        elem = elements[i];

        elem.childNodes[0].childNodes[1].nodeValue = "";

        elem.childNodes[1].nodeValue = elem.childNodes[1].nodeValue.replace(':', '');

        elem.childNodes[2].href="/_layouts/formserver.aspx?xmllocation=" + elem.childNodes[2].href + "&openin=browser";

        elem.childNodes[2].target="_blank";

   }

   

    elements = getElementsByClassName(document, "td", "ms-vb2");

    for (var i = 0; i &lt; elements.length; i++) {

        elem = elements[i];

        if (elem.childNodes[0].nodeName == 'A') {

            elem.childNodes[0].href="/_layouts/formserver.aspx?xmllocation=" + elem.childNodes[0].href + "&openin=browser";

            elem.childNodes[0].target="_blank";

       }

   }

   

    elements = getElementsByClassName(document, "td", "ms-vb");

    for (var i = 0; i &lt; elements.length; i++) {

        elem = elements[i];

         if (elem.childNodes[0].nodeValue == 'There are no items to show in this view of the "Workflow Tasks" list. To add a new item, click "New".') {

            elem.childNodes[0].nodeValue='You have no outstanding approvals';

       }

   }

}

 

/*

Written by Jonathan Snook, http://www.snook.ca/jonathan

Add-ons by Robert Nyman, http://www.robertnyman.com

*/

function getElementsByClassName(oElm, strTagName, strClassName) {

    var arrElements = (strTagName == "*" && oElm.all) ? oElm.all : oElm.getElementsByTagName(strTagName);

    var arrReturnElements = new Array();

    strClassName = strClassName.replace(/\-/g, "\\-");

    var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");

    var oElement;

    for (var i = 0; i &lt; arrElements.length; i++) {

        oElement = arrElements[i];

        if (oRegExp.test(oElement.className)) {

            arrReturnElements.push(oElement);

       }

   }

    return (arrReturnElements)

}

 

 

Export a List Webpart

You want to export the list webpart to your pc, to upload on a different site/page or edit it, but the export webpart option is not available.

 

This is where we get funky …. Still in edit page mode, in the browser toolbar, click Tools | F12 Developer tools. Now select the area on the page holding the webpart

 

Search for the text allowExport within the html

See the =false after it, double-click on it and change that to true

Now the Export option is available on the webpart

 

Save it to the pc, then you can edit it and Add webpart and upload the saved one

Filter Blog

By date: By tag: