Friday, 14 April 2017

Nintex Workflow - How to Troubleshoot an Error

A - OBJECTIVE: 

Your Nintex workflows failed to run ? This article is going to share several methods to troubleshoot the issue.

B - PROBLEMS :

Typical Error Messages from Nintex Workflows: 
  • Workflow Name failed to start.
  • Workflow has ended unexpectedly for This Instance

C - SOLUTION:

Method 1 (item level): Run Now
  • At the workflow item, you can try running the individual action first to ensure your inputs or configuration are correct
  • In this example, Query List is tested with CAML editor, and you can click Run Now to test your CAML query

 

 Method 2 (item level): get workflow details (variables or interim results).
  • You can make use of either 
    • (a) Log in history list [to log the details into the instance history], or
    • (b) Send Notification [to send the details directly to your email]
  • You can view the details by following these steps:
    • Step 1: Workflow History page (e.g. https://anthonynhn.sharepoint.com/_layouts/15/NintexWorkflow/Preview.aspx?WorkflowId=f838195f-d50d-411c-94b2-3b1464372c3f&Category=List&ListId=3f30ef04-e84b-4f5b-a811-4273ea6c66a5  )
    • Step 2: click to a specific Workflow Instance, then click to view detailed logs
    • Step 3: read the details

 Method 3 (item level): Heavy-load workflow components (such as CAML query, For Each loop, or Run Parallel Actions), or form component (such as List Lookup).
  • Issue: workflow may fail while it is running halfway
  • Recommendation: additional actions (Commit Pending Changes, Pause for 1 min) should be added after every iteration in the loop or after the query to ensure the workflow has sufficient time and resource to complete it, such as

Method 4 (workflow level): Correlation ID error
  • A workflow runs halfway and throws a error with correlation ID
  • Recommendation: you can make use of SharePoint Powershell to get detailed logs from the server end as follows (with a specific error ID or timeframe): 
Merge-SPLogFile -Path "C:\ErrorLog.txt" -Correlation "0908cb9c-def6-605c-a8ef-9196988fb4a3"

or

Merge-SPLogFile -Path "C:\Logs\FarmMergedLog.log" -Overwrite -StartTime "10/14/2013 15:55" -EndTime "10/14/2013 16:05"

 Method 5 (workflow level): verbose log
  •  Worst-case scenario, you need to get the extremely detailed logs (verbose log) from Nintex, this feature can be activated at SharePoint Central Admin (reference link).
  • You can see the detailed logs for every workflow instances

  • You can scan through all details in the workflow instance as expected




D - CONFIGURATION:

Please contact me at anthonynhn@gmail.com for further advice.

Tuesday, 28 March 2017

AngularJS with SharePoint Online

A - OBJECTIVE: 

To retrieve items from SharePoint List or Library using AngularJS

B - REQUIREMENT:

Some expected use cases as follows:

  1. A fully customised page is expected with its own layout (i.e. no SharePoint default list view).
  2. Cross-site collection data aggregation: SharePoint default list view webpart only allows you to extract data from the same site collection, and the client expects you to show data across multiple site collections. AngularJS is one of the best options for you.

C - SOLUTION:

By adopting the AngularJS framework, together with SPServices, you can design your code as follows:
  1. Create an AngularJS app in a SharePoint page
  2. Create a SPServices function to get all data & pass it to AngularJS view
  3. Iterate all items in a list or library using ng-repeat within a particular scope (defined by ng-controller). You can create your own custom filter to display data.

D - SOURCE CODE:

At SharePoint Page: View in MVC
    <p> KEY MESSAGES </p>         <table ng-controller="ControllerKeyMessages"  class="ng-scope">         <tr><th>ID</th>         <th>TITLE</th>         <th>FEO CONTENT OWNER</th>         <th>PUBLISHED</th>         <th>SECTION</th>         <th>PUBLISH DATE</th>         <th>CREATED</th></tr>                 <tr ng-repeat="item in items">         <td align = "center" ng-cloak>{{item.ID}}</td>         <td class="digestLeft" ng-cloak>{{item.Title}}</td>         <td align = "center" ng-cloak>{{item | myTaxonomy}}</td>         <td align = "center" ng-cloak>{{item.Published}}</td>         <td align = "center" ng-cloak>Key Messages</td>         <td align = "center" ng-cloak>{{item.Publish_x0020_Date | date:'d MMM y'}}</td>         <td align = "center" ng-cloak>{{item.Created | date:'d MMM y'}}</td>         </tr>            </table>

At SPServices: Model in MVC

function funcNgGetListItems($scope, $http, webURL, listName, extraColumns){
 $http({
  method: 'GET',
  url: webURL + "/_api/web/lists/GetByTitle('"+listName+"')/Items?$filter=Created gt '2016-01-01T00:00:00.1374695Z'&$top=30&$select=ID,Title,Created,Modified,EncodedAbsUrl" + extraColumns +"&$orderby= Created desc",
  headers: { "Accept": "application/json;odata=verbose" }
 }).success(function(data, status, headers, config){  
  $scope.items = data.d.results;
 }).error(function(data, status, headers, config){
  alert("Error: " + JSON.stringify(data))
 });
}

At AngularJS script: Controller in MVC

var appVar = angular.module('myDigestList', []);

appVar.controller("ControllerKeyMessages", function($scope, $http){
    GetListItems($scope, $http, "https://anthonynhn.sharepoint.com/corpinfo/KM", "Posts", ",FEO_x0020_Content_x0020_Owner,Published,Publish_x0020_Date,Thumbnail1,Publication_x0020_Description");
});

Wednesday, 22 February 2017

SharePoint Online - Create Libraries automatically

A - OBJECTIVE: 

During data migration to move files from local drives to SharePoint Online, you may need to create a big number of libraries to anticipate the list (soft) threshold of 5,000 items.

B - PROBLEMS :

Creating libraries manually is tedious & a script to automate the process will be shared to ease your work.

C - SOLUTION:

Powershell script can be used at your own PC to create libraries automatically at any SharePoint Online site.

D - SOURCE CODE or BENCHMARK:

Pre-requisites:
  • SharePoint DLLs saved at your PC & loaded to the script session.
  • Source File which predefines all libraries in each row in the format of "Internal Name, External or Display Library Name".
  • SharePoint Online Management Shell must be installed at your PC.
What you need to do is:
  1. Load the neccessary components
  2. # Load DLLs
    Add-Type -Path "D:\SharePoint\PowerShell\SPO-DLL\Microsoft.SharePoint.Client.dll"
    Add-Type -Path "D:\SharePoint\PowerShell\SPO-DLL\Microsoft.SharePoint.Client.Runtime.dll"
    Add-Type -Path "D:\SharePoint\PowerShell\SPO-DLL\Microsoft.SharePoint.Client.UserProfiles.dll"
     
    # Source File to be synced from SharePoint On-Prem to Online
    $sourcefile = "D:\Projects\Libraries.txt"
    
  3. Load your SharePoint tenant
  4. #variables that needs to be set before starting the script
    $siteURL = "https://anthonynhn.sharepoint.com/sites/fat/cs"
    $adminUrl = "https://anthonynhn-admin.sharepoint.com"
    $userName = "admin@anthonynhn.onmicrosoft.com"
    # Let the user fill in their password in the PowerShell window
    $password = Read-Host "Please enter the password for $($userName)" -AsSecureString
    
  5. Initialize the creation task
  6. # set SharePoint Online credentials
    $SPOCredentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($userName, $password)  
    
    # Creating client context object
    $contextLocal = New-Object Microsoft.SharePoint.Client.ClientContext($siteURL)
    $contextLocal.credentials = $SPOCredentials
    $contextLocal.ExecuteQuery() 
    
    $listTemplate = 101 #doclib
    
    Foreach ($line in [System.IO.File]::ReadLines($sourcefile)) {
        $lib = New-Object Microsoft.SharePoint.Client.ListCreationInformation
     $libInput = $line -split ',';
     
     # set the Internal Name
        $lib.Url = $libInput[0]
     
     # set the Lib Title
     $lib.title = $libInput[1]
     
        $lib.TemplateType = $listTemplate
        $list = $contextLocal.web.lists.add($lib)
        $contextLocal.load($list)
        #send the request containing all operations to the server
        try{
            $contextLocal.executeQuery()
            write-host "info: Created $($listTitle)" -foregroundcolor green
        }
        catch{
            write-host "info: $($_.Exception.Message)" -foregroundcolor red
        }  
    }