Wednesday, February 20, 2008

Start a SharePoint workflow using code

Imagine you already have a SharePoint list with thousands of items and now want to associate a custom workflow with the list.
How will you go and run Workflow on all the existing items as Microsoft SharePoint don't provide any option to run workflow on existing items.
The solution: Run the workflow against each list item via the code

First Get the Workflow Guid and then Create a workflow association object. Start the workflow from the site passing the list item and the workflow association object.

To get a workflow Guid:
Go to List Settings- Workflow Setting and click on the workflow. From URL get the targetId value.

Create a Visual Studio 2005 Console project
Add Reference to SharePoint Library
Replace content of program.cs with the following code--


using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow;

using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow;

class Program
{
static void Main(string[] args)
{
try
{
Console.WriteLine("Started...");
Console.WriteLine("Read value from config list");
// Read from App.Config file
// Site URL
string SiteName = ConfigurationManager.AppSettings["SiteName"];
// Workflow Guid
string WorkFlowGuid = ConfigurationManager.AppSettings["WorkflowGuid"];
// List Name
string ListName = ConfigurationManager.AppSettings["ListName"];
// Query used to filter the items on which WorkFlow needs to be run
string Query = ConfigurationManager.AppSettings["Query"];
// Get Html Decoded Guid
string decode = ConfigurationManager.AppSettings["DecodeGuid"];
if (decode == "1")
WorkFlowGuid = DecodeString(WorkFlowGuid);


Console.WriteLine("Read site details");
SPSite site = new SPSite(SiteName);
SPWeb web = site.OpenWeb();
SPList list = web.Lists[ListName];

Console.WriteLine("Read workflow details");
SPWorkflowAssociation workflowAssociation = list.WorkflowAssociations[new Guid(WorkFlowGuid)];

Console.WriteLine("Get items");
SPListItemCollection items = null;
if(Query.Length > 0) // filtered
{
SPQuery query = new SPQuery();
query.Query = Query;
items = list.GetItems(query);
}
else
items = list.Items; // all items

Console.WriteLine("Looping items");

foreach (SPListItem item in items)
{
if(item.Workflows.Count == 0)
{
// Start if already not started
site.WorkflowManager.StartWorkflow(item, workflowAssociation,
workflowAssociation.AssociationData, true);
}
}
Console.WriteLine("Done");
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
finally
{
Console.WriteLine("Press any key to exit...");
Console.ReadLine();
}
}

static string DecodeString(string sStr)
{
string sChars = " ,',!,#,$,%,&,(,),/,:,;,[,\\,],^,`,{,|,},+,<,=,>,-";
string sANSICodes = "+,%27,%21,%23,%24,%25,%26,%28,%29,%2F,%3A,%3B,%5B,%5C,%5D,%5E,%60,%7B,%7C,%7D,%2B,%3C,%3D,%3E,%2D";
string[] aChars = sChars.Split(",".ToCharArray());
string[] aANSICodes = sANSICodes.Split(",".ToCharArray());
for (int i = 0; i <= aChars.GetUpperBound(0); i++)
{
if (sStr.IndexOf(aANSICodes[i]) > -1)
sStr = sStr.Replace(aANSICodes[i], aChars[i]);
}
return sStr;
}
}

********************Config File*********************


*****************************************

The code logic-

Read values from the app.config file
If WorkflowGuid is encoded as in the config file, decode the Guid
Get workflowassociated with this WorkFlowGuid
Based on SharePoint Query, get the items
Loop through the items and if no workflow started for that item. Start the workflow

1 comments:

Althea said...

You write very well.