Export Sitecore Workflow History

Because of audit purposes, exporting the workflow history might be a useful tool. In this post I will show you how we can create a custom button to export the workflow history to a csv file.

First, we need to create a button in the Core Database. We are going to use a Small Button and the path I chose to create the item at is: /sitecore/content/Applications/Content Editor/Ribbons/Chunks/Workflow/Export History (You can place the button anywhere you like, I just decided to place it in the workflow chunk as shown below):


After creating the small button, we need to fill in some information like the header, icon, click and tooltip fields:


On the click field, we define the command we are going to trigger when the button is clicked. I created a new command called item:ExportWorkflowHistory. In order to register this new command we need to create a config patch like this:

 <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">  
  <sitecore>  
   <commands>  
    <command name="item:ExportWorkflowHistory" type="XXX.XXX.ExportWorkflowHistoryCommand, XXX.XXX"/>  
   </commands>  
  </sitecore>  
 </configuration>  

Now the only thing left is to create our XXX.XXX.ExportWorkflowHistoryCommand class which will have the logic to export the workflow history as csv. Let's create our ExportWorkflowHistoryCommand class that will inherit from Sitecore.Shell.Framework.Commands.Command. We will need to override two methods: the Execute which will have the export logic and the QueryState which will allow us to hide or show the button because we don't want this button to show up on every item (it should only appear on the items which have workflow history). Our command would end up looking something like this:


 using System;  
 using System.IO;  
 using System.Linq;  
 using System.Text;  
 using Sitecore.Data;  
 using Sitecore.Data.Items;  
 using Sitecore.Diagnostics;  
 using Sitecore.IO;  
 using Sitecore.Shell.Framework.Commands;  
 using Sitecore.Web.UI.Sheer;  
 using Sitecore.Workflows;  
 namespace XXX.XXX  
 {  
   public class ExportWorkflowHistoryCommand : Command  
   {  
     public override void Execute(CommandContext context)  
     {  
       Assert.ArgumentNotNull(context, "context");  
       Item currentItem = context.Items.FirstOrDefault();  
       if (currentItem == null)  
       {  
         SheerResponse.Alert("There was an issue trying to get the context item");  
         return;  
       }  
       Database db = currentItem.Database;  
       IWorkflow workflow = currentItem.State.GetWorkflow();  
       if (workflow == null)  
       {  
         SheerResponse.Alert("The context item has no workflow assigned to it");  
         return;  
       }  
       WorkflowEvent[] history = workflow.GetHistory(currentItem);  
       if (!history.Any())  
       {  
         SheerResponse.Alert("The context item has no history");  
         return;  
       }  
       var filename = $"WorkflowHistory_{currentItem.Name}_{DateTime.Now:yyyyMMdd_HHmm}.csv";  
       var filepath = FileUtil.MapPath(Path.Combine(TempFolder.Folder, filename));  
       var sb = new StringBuilder();  
       sb.AppendLine("Name, ID, Version, Language, Path");  
       sb.AppendLine($"{currentItem.Name},{currentItem.ID},{currentItem.Version},{currentItem.Language},{currentItem.Paths.FullPath}");  
       sb.AppendLine();  
       sb.AppendLine("Comments, Date, New State, Old State, User");  
       foreach (var workflowEvent in history)  
       {  
         sb.AppendLine($"{workflowEvent.CommentFields["Comments"]}, {workflowEvent.Date}, {db.GetItem(workflowEvent.NewState)?.Name}, {db.GetItem(workflowEvent.OldState)?.Name}, {workflowEvent.User}");  
       }  
       File.WriteAllText(filepath,sb.ToString());  
       SheerResponse.Download(filepath);  
     }  
     public override CommandState QueryState(CommandContext context)  
     {  
       Item contextItem = context.Items.FirstOrDefault();  
       var workflow = contextItem?.State.GetWorkflow();  
       var history = workflow?.GetHistory(contextItem);  
       if (history == null || !history.Any())  
         return CommandState.Hidden;  
       return CommandState.Enabled;  
     }  
   }  
 }  

Finally, after pressing the following button:


a download will start with the workflow history for the selected item!

TIP: In versions prior to Sitecore 8.3, there was a bug with the  SheerResponse.Download() method that injected html in the downloaded files:



For those of you on 8.2 or earlier, the link to the hotfix is here: https://github.com/SitecoreSupport/Sitecore.Support.90534/releases/

Comments