Blog

You are browsing the archive for SharePoint Designer.

Use Multiple Selection Columns in Calculated Fields

February 22, 2010

I recently had a need to create a hyperlink in a custom list and the hyperlink needed to contain parameters that came from a Choice type column that allowed multiple selections. I’m very comfortable using Excel’s string functions (LEFT, RIGHT, MID, LEN, and FIND) to parse strings and I’ve done so many times. However, when I tried to write a formula using the Multiple Selection field, I got an error that said, “One or more column references are not allowed, because the columns are defined as a data type that is not supported in formulas.” Rats! I thought that we might need to write an event receiver with Visual Studio to accomplish my task, but I really wanted to find a way to do it without writing any code. Here is what I did to solve the problem.

The Problem

In this particular scenario, a department stores information about events in a custom list. There may be one or two people from the department who attend the event. The names of these employees are stored in a column of type Choice that has been set to display as Checkboxes (allow multiple selections).

They use a web based program as part of managing the event. Information about the event is passed to web application as variables in the URL. Two of those parameters are the employees who are attending the event. They want SharePoint to automatically create the URL and modify it if the item changes.

Here is a simplified example of what they want to see in their SharePoint list:
image

The Solution

This customer is using our Workflow Essentials product that adds 24 more activities to SharePoint Designer workflows. I decided to make use of two of the Text Capture activity to extract the parts of the string I needed (if you are interested, you can watch a short video on how the Text Capture, Text Replace, and Text Validate actions work).

The Text actions in Workflow Essentials use Regular Expressions to look for values within text (a great place to learn more about Regular Expressions is: http://www.regular-expressions.info/).

When a column is set to allow multiple items to be selected, SharePoint stores them in a plain text format with the items separated by semicolons; you can see this in the example above.

The first Regular Expression I wrote extracted the first word in the My Persons string. The That regular expression is: ^\b[A-Za-z]+\b
The second Regular Expression I wrote extracted the second word in the My Persons string. That regular expression is: \b[A-Za-z]+\b$

Note that regular expressions don’t actually extract anything, but rather returns the part of the original string that matches the given regular expression. These two expressions worked in my case because my strings consisted of single words that consisted only of singe letters and there was a maximum of two words total. If my string had different qualities, I would have to have written totally different regular expressions to match my particular criteria. Writing Regular Expressions is a very valuable, and often under valued, job skill. I’m not an expert at it so I won’t likely be a good source for writing a regular expression for your particular case. Sorry.

Once I had written my Regular Expressions, I was ready to create my solution. I launched SharePoint Designer and created a new workflow on my list that would run when a new item was added or when an item changed.

I added the Text Capture activity first, used my first Regular Expression as pattern and output the captured text to a variable named FirstChoice. Then I added another Text Capture activity where I used my second Regular Expression and captured the matched text to a variable named SecondChoice. Next I added a Build Dynamic String activity where I composed the URL and inserted the two variables in the appropriate place for the URL parameters. Finally, I added a Set Field in Current Item activity where I set the My URL field to the string I had just created. Here is the entire workflow.
image

As you can tell, Workflow Essentials is a powerful product that can greatly increase the power of your SharePoint Designer workflows. Check it out!

InfoPath Form with Multiple, Dynamic Approvers

February 19, 2010

A question came in to the MOSS Help and How To forum about creating a form that allowed multiple approvers to be specified at the time the form is being filled out.

I went ahead and created a form in InfoPath and a simple workflow in SharePoint Designer to allow the selection of the approvers and assign tasks for the approvers. It is a simple form and workflow both. For production you would want a more robust solution. If you have ideas for a better solution, please let me know in the comments.

Instead of writing out all of the steps I created this short video to demonstrate how the form, workflow, and SharePoint library work.

MOSSHelpPlay

Changes in SharePoint DesignerTypes for workflow activity parameters

October 23, 2009

Creating a workflow in SharePoint Designer consists of selecting Conditions and Activities to build the logic and determine what actions the workflow performs. When you select an activity or condition a sentence appears in the WorkFlow Designer screen with underlined phrases that allow you click on them to set the workflow’s parameters. These parameters can be selecting a column on a list item and a value to give it, or they can be a user’s account name, a url to a site or something more complex like an email definition that includes a To address, CC address, a subject and a body.

When creating custom workflow activities and conditions for SharePoint in Visual Studio, you create a code class to build its functionality as well as a .actions file, both of which define the parameters. SharePoint Designer uses the .actions to be able to add the activity or condition to a workflow. You must specify the type for each parameter within both the class and the .actions file as well as the DesignerType in the .actions file. When a user clicks on a parameter, different windows open to allow the user to input the values according to the DesignerType given to the parameter. The DesignerType is simply an enumeration that SharePoint Designer uses to determine what type of form to display to gather information on each parameter. For example, a DesignerType of DropDown will present a drop down menu at the location of the parameter phrase in the sentence, whereas a DesignerType of Email will open a pop up window with fields for the To address, CC address, Subject and Body where each of these fields is defined as a parameter of different types in code and returned from the Designer form as an object of that type.

For an activity to send an email, the simple class definition may look something like this:


public partial class SendAnEmail : SequenceActivity
{
   #region Dependency Properties

   public static DependencyProperty __ContextProperty = DependencyProperty.Register("__Context", typeof(WorkflowContext), typeof(SendAnEmail));
   public static DependencyProperty RecipientCCProperty = DependencyProperty.Register("RecipientCC", typeof(ArrayList), typeof(SendAnEmail));
   public static DependencyProperty RecipientFromProperty = DependencyProperty.Register("RecipientFrom", typeof(string), typeof(SendAnEmail));
   public static DependencyProperty RecipientTOProperty = DependencyProperty.Register("RecipientTO", typeof(ArrayList), typeof(SendAnEmail));
   public static DependencyProperty SubjectProperty = DependencyProperty.Register("Subject", typeof (string), typeof (SendAnEmail));
   public static DependencyProperty BodyProperty = DependencyProperty.Register("Body", typeof(string), typeof(SendAnEmail));

   #endregion

   public SendAnEmail()
   {
      InitializeComponent();
   }

   #region Activity Parameters

   [Description("Recipient address")]
   [Browsable(true)]
   [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
   public ArrayList RecipientTO
   {
      get { return ((ArrayList) (base.GetValue(RecipientTOProperty))); }
      set { base.SetValue(RecipientTOProperty, value); }
   }

   [Description("Carbon copy recipient")]
   [Browsable(true)]
   [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
   public ArrayList RecipientCC
   {
      get { return ((ArrayList) (base.GetValue(RecipientCCProperty))); }
      set { base.SetValue(RecipientCCProperty, value); }
   }

   [Description("Subject")]
   [Browsable(true)]
   [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
   public string Subject
   {
      get { return ((string) (base.GetValue(SubjectProperty))); }
      set { base.SetValue(SubjectProperty, value); }
   }

   [Description("HTML Body")]
   [Browsable(true)]
   [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
   public string Body
   {
      get { return ((string) (base.GetValue(BodyProperty))); }
      set { base.SetValue(BodyProperty, value); }
   }

   [Browsable(true)]
   [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
   public WorkflowContext __Context
   {
      get { return ((WorkflowContext) (base.GetValue(__ContextProperty))); }
      set { base.SetValue(__ContextProperty, value); }
   }

   [Description("Sender address. If this value is not specified, default sharepoint sender address will be used")]
   [Browsable(true)]
   [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
   public string RecipientFrom
   {
      get { return ((string) (base.GetValue(RecipientFromProperty))); }
      set { base.SetValue(RecipientFromProperty, value); }
   }

   #endregion

   protected override ActivityExecutionStatus OnExecute(ActivityExecutionContext executionContext, Microsoft.SharePoint.Workflow.ISharePointService service)
   {
   }
}

The .actions file would look like:


<?xml version="1.0" encoding="utf-8"?>
<WorkflowInfo Language="en-us">
   <Actions Sequential="then" Parallel="and">
      <Action Name="Send E-mail Extended" ClassName="SPSolutions.SharePoint.WorkflowEssentials.Activities.SendEmailExtended" Assembly="SPSolutions.SharePoint.WorkflowEssentials, Version=1.0.0.0, Culture=neutral, PublicKeyToken=08a33cc09f006379" AppliesTo="all" Category="SharePoint Solutions' WorkFlow Essentials">
         <RuleDesigner Sentence="Send a %1 e-mail to %2 and display %3 as the sender">
            <FieldBind Field="IsMessageUrgent" DesignerType="Dropdown" Text="choose" Id="1">
               <Option Name="urgent" Value="true"/>
               <Option Name="non urgent" Value="false"/>
            </FieldBind>
            <FieldBind Field="RecipientTO,RecipientCC,Subject,Body" Text="this address" DesignerType="Email" Id="2"/>
            <FieldBind Field="RecipientFrom" Text="this address" Id="3" DesignerType="stringbuilder" />
         </RuleDesigner>
         <Parameters>
            <Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext, Microsoft.SharePoint.WorkflowActions" Direction="In"/>
            <Parameter Name="IsMessageUrgent" Type="System.String, mscorlib" Direction="In" InitialValue="false" />
            <Parameter Name="RecipientTO" Type="System.Collections.ArrayList, mscorlib" Direction="In" />
            <Parameter Name="RecipientCC" Type="System.Collections.ArrayList, mscorlib" Direction="Optional" />
            <Parameter Name="RecipientFrom" Type="System.String, mscorlib" Direction="In" />
            <Parameter Name="Subject" Type="System.String, mscorlib" Direction="In" />
            <Parameter Name="Body" Type="System.String, mscorlib" Direction="In" />
         </Parameters>
      </Action>
   </Actions>
</WorkflowInfo>

In terms of SharePoint 2010, there are several new DesignerTypes and some of the existing ones have changed slightly in the types of parameters that they return. Below is an overview of most, if not all, of the DesignerTypes included in 2010.

 Designer Type 
   
 New to 2010 
   
 Parameter(s) returned
(example parameter name) 
   
 Parameter type 
   
 Description 
 Assignment       Yes       AssignedTo       System.String       
             CC       System.Collections.ArrayList       
             Comments       System.String       
             Subject       System.String       
             Duration       System.Double       
             DurationUnit       Microsoft.Office.Workflow.Actions.DurationUnit       
             DueDate       System.DateTime       
 Boolean       No       Yes/No       System.Boolean       
 ChooseDocLibItem       No       DocumentLibrary
ItemName 
     System.String       Selects list item from a Document Library based on a field value. 
 ChooseListItem       Changed       ListId       System.String       Selects List Item from list based on a field value. 
             ListItem       Microsoft.SharePoint.Workflow.SPItemKey       
 ContentType       Yes       ContentTypeID       System.String       
 CreateListItem       No                   
 DataSourceDropDown       Yes       DataSourceName       System.String       Drop Down list of DataSources for list associated with workflow. 
 Date       No       Date       System.DateTime       Date Time Selector 
 Dependent       Yes            S ystem.String       Based on TextArea DesignerType 
 DropDown       No             System.String       
 Email       No       To       System.Collection.ArrayList       
             CC       System.Collection.ArrayList       
             Subject       System.String       
             Body       System.String       
 Hide       No                   Used to hide parameter from users in Designer 
 FieldNames       No       FieldName       System.String       Select field column from list associated with workflow. 
 Float       No             System.Float       
 HyperLink       No       Link       System.String       
 Integer       No             System.Int32       
 ListItems       Yes             System.String       
 ListNames       No       ListTitle       System.String       Drop Down with list of list names from current site 
 Operator       No                   Drop-down list box control that includes operators used to evaluate each side of the RuleDesigner sentence. Operators are static and must be added in Options elements. 
 ParameterNames       No             System.String       Allows the creation of a new variable for the workflow. 
 Person       No       Users       System.Collections.ArrayList       Allows selection of multiple users 
 SinglePerson       Changed             System.Object       Allows selection of a single user 
 StringBuilder       No             System.String       
 Survey       No                   Creates a task in the workflow to gather data from users. 
 TaskSummary       Yes       TaskProcessName       System.String       
 Text       No             System.Object       
 TextArea       No             System.String       
 UpdateListItem       No       ListItemToUpdate             
 WritableFieldNames       No             System.String       Drop down including list of fields on list that are writable 

So far, the main changes appear in the return types of the ChooseListItem and SinglePerson DesignerTypes. In SharePoint 2010, the SinglePerson form returns a generic System.Object rather than a string, and the ChooseListItem’s ListItem parameter returns a new type of SPItemKey instead of a string.

To accommodate the return of an Object from the SinglePerson DesignerType form, simple define the parameter as System.Object in the .actions file and the DependencyProperty in code, then define the activities property as a String and explicitly convert it from object to string in the get statement.

The new .actions file section would now look like:

<Action Name="myNewActivity"
 ClassName="SPSolutions.SharePoint.WorkflowEssentials.Activities. myNewActivity "
 Assembly="SPSolutions.SharePoint.WorkflowEssentials, Version=1.0.0.0, Culture=neutral,
 PublicKeyToken=08a33cc09f006379"
 AppliesTo="all" Category="SharePoint Solutions' WorkFlow Essentials">
   <RuleDesigner Sentence="Get %1">
     <FieldBind Field="SharePointUser" DesignerType="SinglePerson" Text="this person" Id="1" />
   </RuleDesigner>
   <Parameters>
     <Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext,
      Microsoft.SharePoint.WorkflowActions" Direction="In"/>
     <Parameter Name="ListId" Type="System.String, mscorlib" Direction="In" />
     <Parameter Name="SharePointUser" Type="System.Object, mscorlib" Direction="In" />
   </Parameters>
 </Action>

The new declaration in the class for parameters returned from the ChooseListItem DesignerType would now look like:

public static DependencyProperty SharePointUserProperty =
DependencyProperty.Register("SharePointUser", typeof(object), typeof(myNewActivity));
[Description("SharePoint User")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public string SharePointUser
{
   get { return ((string) (base.GetValue(SharePointUserProperty))); }
   set { base.SetValue(SharePointUserProperty, value); }
}

The SPItemKey type appears to be a wrapper for returning an instance of the list item. It has two public properties: Id as Int32 and Key as String where the Id is the selected ListItem’s Id and Key is the name. You can programmatically get an instance of the SPListItem by passing the SPList object as a parameter to SPItemKey.GetItemByIdFromList(SPList).

Public Members for Microsoft.SharePoint.Workflow.SPItemKey

Constructors
 SPItemKey()       Returns object with Key = string.Empty, Id = -1 
 SPItemKey(Int32 id)       Returns object with Key = id.ToString(), Id = id 
 SPItemKey(string key)       Returns object with Key = key, Id =Int32.Parse(key) 
Methods
 Equals(object rhs)       Boolean       Determines if current object equals object passed in 
 Equals(object objA, object objB)       Boolean       Determines if two objects are equal 
 Finalize()       Void       Empty override of base System.Object.Finalize() 
 FromItem(SPListItem listItem)       SPItemKey       Returns SPItemKey object given SPListItem 
 GetHashCode()       Int32       Generated from Exclusive OR operation between Id and Key.GetHashCode() 
 GetItemByIdFromList(SPList)       SPItemKey       Returns SPListItem from given list from Key or Id property 
 GetType()       Type       Returns Type for current SPItemKey 
 IsEmpty(SPItemKey)       Boolean       Static. Returns true if both Id and Key properties are null or if Id = -1 and Key is null or string.Empty 
 MemberwiseClone()       Object       Creates a shallow copy of the current SPItemKey 
 op_Equality(SPItemKey lhs, object rhs)       Boolean       Static. Determines if SPItemKey and Object are both null or equal 
 op_Equality(SPItemKey lhs, SPItemKey rhs)       Boolean       Static. Determines if two SPItemKey objects are both null or equal 
 op_Inequality(SPItemKey lhs, object rhs)       Boolean       Static. Determines if SPItemKey and Object are both not null or not equal 
 op_Inequality(SPItemKey lhs, SPItemKey rhs)       Boolean       Static. Determines if two SPItemKey objects are both not null or not equal 
 ReferenceEquals(object objA, object objB)       Boolean       Static. Determines if two objects are references to the same object 
 ToString()       String       Comma separated string: Key, Id 
Properties
 Empty       SPItemKey       Static. Returns empty object using empty constructor 
 Id       Int32       Read/Write. Id of SPItemKey 
 Key       String       Read/Write. Key of SPItemKey 

To access the new type in your class, be sure to reference the new assemblies for SharePoint 14 including C:\Program Files\Common Files\Microsoft Shared\web server extensions\14\ISAPI\Microsoft.SharePoint.dll and C:\Program Files\Common Files\Microsoft Shared\web server extensions\14\ISAPI\Microsoft.SharePoint.WorkflowActions.dll.

The new .actions file section would now look like:

<Action Name="myNewActivity"
 ClassName="SPSolutions.SharePoint.WorkflowEssentials.Activities. myNewActivity"
 Assembly="SPSolutions.SharePoint.WorkflowEssentials, Version=1.0.0.0, Culture=neutral,
 PublicKeyToken=08a33cc09f006379"
 AppliesTo="all" Category="SharePoint Solutions' WorkFlow Essentials">
   <RuleDesigner Sentence="Get %1">
     <FieldBind Field="ListId, ListItem" DesignerType="ChooseListItem" Text="List Item" Id="1" />
   </RuleDesigner>
   <Parameters>
     <Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext,
      Microsoft.SharePoint.WorkflowActions" Direction="In"/>
     <Parameter Name="ListId" Type="System.String, mscorlib" Direction="In" />
     <Parameter Name="ListItem" Type="Microsoft.SharePoint.Workflow.SPItemKey, Microsoft.SharePoint" Direction="In" />
   </Parameters>
</Action>


The new declaration in the class for parameters returned from the ChooseListItem DesignerType would now look like:

public static DependencyProperty ListIdProperty = DependencyProperty.Register("ListId", typeof(string), typeof(myNewActivity));
[Description("List Id")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public string ListId
{
   get { return ((string) (base.GetValue(ListIdProperty))); }
   set { base.SetValue(ListIdProperty, value); }
}

public static DependencyProperty ListItemProperty = DependencyProperty.Register("ListItem", typeof(SPItemKey), typeof(myNewActivity));
[Description("List Item")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public SPItemKey ListItem
{
   get { return ((SPItemKey) (base.GetValue(ListItemProperty))); }
   set { base.SetValue(ListItemProperty, value); }
}

Looking at the SharePoint 14 codebase, there are several new activities included in the namespace Microsoft.SharePoint.WorkflowActions.WithKey that use the SPItemKey object includng the same ListItem property as well as additional properties such as TaskId. It appears that the workflow activities in the new version of SharePoint uses this object extensively for List Items, probably as a smaller object to pass around instead of the full SPListItem object. It will be interesting to see how, if at all, this object changes in the beta release.

The New Approval Actions in SharePoint Designer 2010 Workflows

October 18, 2009

SharePoint 2007 came with 23 out-of-the-box actions to fit many of the most common tasks needed in workflows. SharePoint 2010 comes with 44 out-of-the-box actions. All the original actions are still there, but you now have 21 more! Note: This post and all screenshots are from the Technical Preview and things may change before SharePoint 2010 is released to the public.

 

In SharePoint 2007, if you wanted to get approval from a user for something, you usually had to use the Collect Data from a User action, store a reference to the task ID for the task that was created, and then lookup the user’s input later in your workflow as needed. Microsoft has streamlined this process in SharePoint Designer 2010 with the actions for Assign Item for Approval, Assign Item for Feedback, and General Task Process. In this article, we’ll take a look at how these three actions work.

 

The first thing you will notice when you add any of these three actions to your workflow is that in the Editor, they all look identical. In the following screenshot I have added an Assign Item for Approval action to Step 1, and Assign Item for Feedback action to Step 2, and a General Task Process action to Step 3.

 

So, how can you tell them apart? You have to click on the Approval Process link for the action. When you do this, you will see a new page where you can define and customize that overall task process.

 

Let’s work our way around this page to explain what each section does.

 

Task Information

In the Task Information section there are only two options, you can change the name of the Approval Process and the Owner of the task.

Both of these can be changed by clicking on the information you want to change. The Name is a meaningful name to you for this particular process. I recommend changing this to a descriptive name that will help you remember later what this particular process is for and to keep the various approval processes in your workflow distinct. The Owner is the owner or this process; you’ll see where this comes into play when we get to the Settings section.

 

When you change the Name here it also changes the name in the workflow editor.

 

Task Outcomes

The Task Outcomes section, you can define the various outcomes for this particular process. If you selected the Assign Item for Approval action, you will already have the options of Approved and Rejected listed here.

If you want to add other options, you can click the New button to add a new option. In the example here, I have added a Skipped option.

The items you list here will be listed as separate buttons on the task form and will be displayed in the Sequence order you select.

 

Task Form Fields

The Task Form Fields section allows you to collect other information in the task form. For example, if something is approved or rejected, you probably want the person who is doing the approving or rejecting to enter some notes about why the chose to approve or reject it.

 

By clicking the New button, you can add your custom data fields to the form. There is a short wizard that will walk you through the process.


 

If you click the Choose existing field button, you will get a dialog box where you can choose from any of the Site Columns that are already available on your site. This can be incredibly handy since you can define the column one time and then reuse it as needed.

 

Settings

There are only three options in the Settings section.

If you check the box for Only allow task recipients and process owners to read and edit workflow tasks then those are the only people who can do those activities. Do you remember when you could set the process owner in the Task Information box? Well, this is where that process owner is used.

 

There are also boxes to allow users to reassign the tasks and to change requests.

 

Customization

I’ve saved this section for last because it is probably the most complex of the five configuration sections.

 

Clicking on the Return to Workflow link simply closes the Approval Process editing window and returns you to the workflow Editor.

 

If you click on Change the completion conditions for this task process you will be taken to the Check Exit Conditions section where you can see the underlying conditions that are part of this activity. This is probably where you begin to see how powerful these new Approval Actions really are. Here is a screenshot of the default page without making any changes:

You can add more conditions here if needed, add steps and generally modify the process as you need.

 

If you click on Change the behavior of a single task you will be taken to a place where you can see and change the behaviors for On Task Assigning, On Task Pending, On Task Expired, On Task Deleted, and On Task Completed. Within each of these, you can add your own conditions, actions, and steps. Here is a screenshot of the default page:

 

If you click on Change the behavior of the overall task process you will be taken to a place where you can see and change the behaviors for On Approval Started, On Approval Running, On Approval Canceled, and On Approval Completed. Once again, within each of these, you can add your own conditions, actions, and steps. Here are screenshots of the various sections of the default page:

Whew! That’s a lot of options and configurations that you can do! But were not yet finished! Remember that these were just he settings for the process. If you return to the workflow editor you’ll see that there are still two more options we haven’t looked at yet.

 

Item to Be Approved

You probably expect that the only item on which you can perform the Approval action is the current item. However, if you click on Current Item, you can change that to any list or library item you want.

 

Assigned to Users

Another thing that I found frustrating in SharePoint 2007 was that I couldn’t customize the task and emails that they sent. When you click on the link in SharePoint 2010 to add users, you get a dialog box where you can customize task request, including the title and body that can include lookups. You can even add serial and parallel recipients and have multiple assignment stages.

 

Well, there you have it. You’ve gotten a general overview of the options for the new Approval Actions in SharePoint Designer 2010. If you are overwhelmed, I’m not surprised. In this post, we’ve only just barely scratched the surface of the great things you can do with SharePoint Designer Workflows in SharePoint 2010. You’ll probably need to take a class to learn it all. J