SharePoint Experts Blog

How to Start SharePoint 2013 Workflows on Selected Items

This blog post appeared as an email response to one of our clients, he described very common use case where you have two libraries of documents, the first library where the users works with draft documents and the other library which is stored the final versions of documents. In this case, users want to be able to select finished documents and move it in one click.
Oblivious solution for this is to use a workflow that will move documents to the final document library. But there is one question how we can start the workflow on selected list items? When I was thinking about the answer to that question – I realized that is not as trivial as it seems, because list level workflow can be started only on singl document. How to start multiple workflows on selected documents? In the article, I will describe how you can implement such solution.

I divided this article into three main parts:

  • Get selected items via JavaScript;
  • Start SharePoint 2013 workflow from JavaScript;
  • Add custom button to the list ribbon

Before we start, I want to show what we will get in result. On the figure below you can see the custom button on the ribbon, which will launch a workflows on selected documents.


How to get selected elements via JavaScript

Firstly I will describe how you can get selected List items from SharePoint list. To do this, you can use special JavaScript function getSelectedItems. Please see example below:

var ctx = SP.ClientContext.get_current();
var selectedItems = SP.ListOperation.Selection.getSelectedItems(ctx);

for(var i=0; i < selectedItems.length;i++)
{
    var itemId = selectedItems[i].id;

	console.log(itemId);
}

As result of execution, this snippet of code you should see the IDs of selected list items in the console log.

How to start workflow

Since SharePoint 2013 Microsoft has added a new workflow engine. The new JavaScript API for manipulation with workflows also became available. In this article, I will not describe it, but if you are interested, you can find more information from the Andrei Markeev’s blog post. I will show you ready to use JavaScript snippet, which can run workflow on a single list item.

function startWorkflow(itemID, subID) {
    var context = SP.ClientContext.get_current();
    var web = context.get_web();
    var wfServiceManager = SP.WorkflowServices.WorkflowServicesManager.newObject(context, web);
    var subscription = wfServiceManager.getWorkflowSubscriptionService().getSubscription(subID);

    context.load(subscription);
    context.executeQueryAsync(
        function(sender, args){
            console.log("Subscription load success. Attempting to start workflow.");        
            var inputParameters = {};
            wfServiceManager.getWorkflowInstanceService().startWorkflowOnListItem(subscription, itemID, inputParameters);

            context.executeQueryAsync(
                function(sender, args){ console.log("Successfully starting workflow."); },
                function(sender, args){ 
                    console.log("Failed to start workflow.");
                    console.log("Error: " + args.get_message() + "\n" + args.get_stackTrace());
                }
            );
        },
        function(sender,args){
            console.log("Failed to load subscription.");
            console.log("Error: " + args.get_message() + "\n" + args.get_stackTrace());
        }
    );
}

This simple JavaScript function launches a workflow on a list item. The workflow subscription is specified by SubID argument. To identify the subscription ID of your workflow you can navigate to the workflows start page and see the URL in your browser, it should look like this (the bold GUID it is workflow subscription ID): “javascript:StartWorkflow4('6eb43e78-6e6c-486a-9147-3e3870f3a44e', '19', '{FA41C64B-42CD-4A3F-A1AF-CF674AB35C57}')”

How to Add a Button to the SharePoint Ribbon

Very important part is how a user will interact with our system, I believe that the user experience is very important for any system. In our case we plan that the user will select the documents and click on the ribbon button which will move them to another document library.

There are various ways to add a button on the ribbon, but in this article, I want to describe the simplest. We will use SharePoint Designer to do this. When we use SharePoint Designer we have some limitation for example we cannot add new ribbon tab or hide any existing button, but from other point of view if we need just to add button to the ribbon it will take five minutes of our time and it doesn't require programming skills.

Please open the SharePoint Designer, navigate to “List and Libraries” and choose your document library.

To add a ribbon button please click inside the “Custom Actions” area and choose on the ribbon “Custom Actions” – “View Ribbon”.

When you fill in the all fields, you should see something like on the figure below in your list.

Please pay attention at the property “Navigate URL”, I filled it with following text: javascript:PlumsailDemo.WFPack.API.StartListWorkflowOnSelectedItems("{6eb43e78-6e6c-486a-9147-3e3870f3a44e}");

This is a call of our function with argument “Subscription ID” of our workflow.

Join all of it together

OK, we almost did it. All we need to do it is combine and place the JavaScript in SharePoint. To add our JavaScript on the page we will use the ScriptEditor Web part. To do this you need to enter to edit page mode, click on “Add a Web Part” and select “Script Editor” in “Media and Content” group.

I changed the JavaScript file little bit to simplify using

<script type="text/javascript">// <![CDATA[
var PlumsailDemo = PlumsailDemo || {};
PlumsailDemo.WFPack = PlumsailDemo.WFPack || {};

PlumsailDemo.WFPack.API = (function() {
    var self = this; 
    self.Context = null, 
    self.WFManager = null;

    SP.SOD.executeFunc('sp.js', 'SP.ClientContext' , function(){
        SP.SOD.registerSod("sp.workflowservices.js", SP.Utilities.Utility.getLayoutsPageUrl("sp.workflowservices.js"));
        SP.SOD.executeFunc("sp.workflowservices.js", 'SP.WorkflowServices.WorkflowServicesManager', 
            function() { 
                self.Context = SP.ClientContext.get_current();
                var web = self.Context.get_web();
                self.WFManager = SP.WorkflowServices.WorkflowServicesManager.newObject(self.Context, web);
            });
    });

    StartListWorkflowOnSelectedItems = function(subID) {
        var selectedItems = SP.ListOperation.Selection.getSelectedItems(self.Context);

        for(var i=0; i < selectedItems.length;i++)
        {
            var itemId = selectedItems[i].id;
            self.StartListWorkflow(itemId, subID);
        }
    };

    StartListWorkflow = function(itemID, subID) {
        var subscription = self.WFManager.getWorkflowSubscriptionService().getSubscription(subID);

        self.Context.load(subscription);
        self.Context.executeQueryAsync(
            function(sender, args){
                var inputParameters = {};

                self.WFManager.getWorkflowInstanceService().startWorkflowOnListItem(subscription, itemID, inputParameters);

                self.Context.executeQueryAsync(
                    function(sender, args){ 
                        var message = 'The workflow ' + subscription.get_name() + ' was started on item with ID ' + itemID;
                        SP.UI.Notify.addNotification(message, false); 
                    },
                    function(sender, args){ 
                        var message = 'Failed to start workflow ' + subscription.get_name() + ' on item with ID ' + itemID;
                        SP.UI.Notify.addNotification(message, false);                 
                        console.log('Failed to start workflow.');
                        console.log('Error: ' + args.get_message() + '\n' + args.get_stackTrace());
                    }
                );
            },
            function(sender,args){
                var message = 'Failed to load subscription ' + subID;
                SP.UI.Notify.addNotification(message, false); 
                console.log('Failed to load subscription.');
                console.log('Error: ' + args.get_message() + '\n' + args.get_stackTrace());
            }
        );

    };

    return {
        StartListWorkflow: StartListWorkflow
        , StartListWorkflowOnSelectedItems: StartListWorkflowOnSelectedItems
    };
})();
// ]]>

Conclusion

In the article, we reviewed the way how you can start multiple workflows on the selected list items. As conclusion, I want to mention about one little detail, in such approach very difficult to monitor the status and errors of the workflows because it works on multiple list items. But you can extend my simple JavaScript with some workflow tracking logic if you have enough JavaScript/SharePoint skills.

You have to understand what will be the load for the system, for small systems this is an acceptable approach, but for highly loaded systems this is not so good. You can consider other approaches for moving documents like single site level workflow or custom coded solution.

As alternative of this approach, you can start a site level workflow and pass to it the selected IDs, but this is the theme of another article.

Please feel free to comment, I will be happy to answer to your questions.

Posted in: Products, Workflow Actions Pack

  • Guest
    Hi Roman,Its really wonderful one.I was looking for this kind of solution. Could you please provide me the workflow part as well or it would be grateful if you can share me the entire solution.
    • Roman Rylov
      Hello,The core idea of the article is in JavaScript function that you can find in last part of the article. You can use it with conjunction with any of your workflows it is not principal.
  • Mohd
    HI Roman1. Where are we supposed to add the Script Editor webpart. If I am adding the “Script Editor” webpart just above document library by editing the page. The workflow is not triggering. Please explain us where to place the webpart.2. Do we need to add Jquery and SPServices reference file in the script. if yes where to add and how to trigger them.
    • Roman Rylov
      Hello Mohd,1. It doesn’t matter where is located web part. Please ensure that javascript was inserted correctly, to do this you could open source of the page and find the script.2. No, it doesn’t require any additional 3rd party libraries.
  • tomidix
    Thank you sir! This works flawlessly..
  • Marian Thijssen
    Hello Roman, the solution described is exactly what we were looking for. And it works as long as I select 1 item in my document library and use the option “Initiate workflow” for my custom Action. As soon as I use ‘Navigate to URL’, it does’t work. Even for 1 item it doesn’t work.I want to workflow to run when more items are selected. Why does the URL not work? I copied the URL to my browser and got errors. not sure what I do wrong.How can I get this to work and how do I get this to run on more selected items?
    • Roman Rylov
      Hello Marian,Why you need to use ‘Navigate to URL’ action? Could you please describe your business case?
  • Nick
    A problem that might arise and I encountered is the disappearing of the Office 365 ribbon or other strange behavior when adding the script to the home page without having a list on the page. To fix this: 1. Add the script as in the tutorial 2. Check-In your changes 3. Add ?contents=1 at the end of the URL 4. On the page select your script and press Close. This will stop the script from running when the page loads
    • Nick
      Please delete this comment. It was because of some script syntax i was getting an error