HowTo: Read Workflow Status Text

Ever wanted to be read the Status text displayed on WrkStat.aspx programmatically so that you can make use of it elsewhere? No? Can’t blame you!

image

However, let’s say that you do fancy a bit of masochism. Here’s how it works:

The status value is stored in a field of type SPFieldWorkflowStatus. Generally this field has the same display name as your workflow although it’s internal name will be different. Getting the internal name is a pain, for some bizarre reason Microsoft decided to expose this as an internal property rather than public. (See SPWorkflowAssociation.InternalNameStatusField). After tracing this back to source via Reflector, it transpires that this comes from the database and is never exposed as a public property. The best way I’ve found to locate the correct field is to iterate through them and find one with a title that matches the workflow name. (Why? Surely there’s an easier way?)

Note: Strictly speaking you don’t need to iterate, you could just do SPList[WorkflowName] then check the field was of type SPFieldWorkflowStatus but I’m kinda hoping I’ll find a better way to verify the workflow that the field is attached to and an iterator makes it easier to add in additional checks.

An SPFieldWorkflowStatus field stores an Int32 value. This is probably useless to you and you’ll want to map it to your text value. Thankfully, you can do this using SPFieldWorkflowStatus.GetFieldValueAsHtml(int32), this code will iterate through the states attached to the workflow and return the correct value. You could achieve the same result by looking at SPWorkflowAssociation[“ExtendedStatusColumnValues”] but that’s a bit more involved and pointless unless you’ve extended the metadata.

Anyways, enough with the explanations. Here’s a some code that you could use:

      protected override void Render(HtmlTextWriter writer)
        {
            //Is the workflow attached to this list item?
            SPListItem current = SPContext.Current.ListItem;
            SPWorkflowManager manager = current.Web.Site.WorkflowManager;
            SPWorkflowFilter filter = new SPWorkflowFilter()
            {
                ExclusiveFilterStates = SPWorkflowState.Completed | SPWorkflowState.Cancelled
            };
 
            //Get a list of the workflows that are running
            foreach (SPWorkflow instance in manager.GetItemWorkflows(current, filter))
            {
                if (instance.ParentAssociation.Name==WorkFlowName)
                {
                    //loop through the fields
                    foreach (SPField field in instance.ParentList.Fields)
                    {
                        //If field is a workflow status column
                        if (field is SPFieldWorkflowStatus)
                        {
                            SPFieldWorkflowStatus statusField = (SPFieldWorkflowStatus) field;
                            //This may not always be true although I've never found a situation where it isn't!
                            if (statusField.Title == WorkFlowName)
                            {
                                //The field stores an int32
                                int statusValue = int.Parse(current[statusField.StaticName].ToString());
                                //Get the text value
                                string statusText = statusField.GetFieldValueAsHtml(statusValue);
                                //Do what you need to do with it
                                writer.Write(statusText);
                                break;
                            }
 
                        }
                    }                    
                }
            }
        }