The other day I was poking around Sitecore.Forms.Core.dll — this is one of the assemblies that comes with Web Forms for Marketers (what, you don’t randomly look at code in the Sitecore assemblies? 😉 ) — and decided to check out how the export functionality of the Form Reports work.
Once I felt I understood how the export code functions, I decided to take a stab at building my own custom export: functionality to export to CSV, and built the following class to serve as a pipeline processor to wedge Form Reports data into CSV format:
using System;
using System.Collections.Generic;
using System.Linq;
using Sitecore.Diagnostics;
using Sitecore.Form.Core.Configuration;
using Sitecore.Form.Core.Pipelines.Export;
using Sitecore.Forms.Data;
using Sitecore.Jobs;
namespace Sitecore.Sandbox.Form.Core.Pipelines.Export.Csv
{
public class ExportToCsv
{
public void Process(ExportArgs args)
{
Assert.ArgumentNotNull(args, "args");
LogInfo();
args.Result = GenerateCsv(args.Packet.Entries);
}
protected virtual void LogInfo()
{
Job job = Context.Job;
if (job != null)
{
job.Status.LogInfo(ResourceManager.Localize("EXPORTING_DATA"));
}
}
private string GenerateCsv(IEnumerable<IForm> forms)
{
return string.Join(Environment.NewLine, GenerateAllCsvRows(forms));
}
protected virtual IEnumerable<string> GenerateAllCsvRows(IEnumerable<IForm> forms)
{
Assert.ArgumentNotNull(forms, "forms");
IList<string> rows = new List<string>();
rows.Add(GenerateCsvHeader(forms.FirstOrDefault()));
foreach (IForm form in forms)
{
string row = GenerateCsvRow(form);
if (!string.IsNullOrWhiteSpace(row))
{
rows.Add(row);
}
}
return rows;
}
protected virtual string GenerateCsvHeader(IForm form)
{
Assert.ArgumentNotNull(form, "form");
return string.Join(",", form.Field.Select(field => field.FieldName));
}
protected virtual string GenerateCsvRow(IForm form)
{
Assert.ArgumentNotNull(form, "form");
return string.Join(",", form.Field.Select(field => field.Value));
}
}
}
There really isn’t anything magical happening in the code above. The code creates a string of comma-separated values for each row of entries in args.Packet.Entries, and puts these plus a CSV header into a collection of strings.
Once all rows have been placed into a collection of strings, they are munged together on the newline character ultimately creating a multi-row CSV string. This CSV string is then set on the Result property of the ExportArgs instance.
Now we need a way to invoke a pipeline that contains the above class as a processor, and the following command does just that:
using System.Collections.Specialized;
using Sitecore.Diagnostics;
using Sitecore.Forms.Core.Commands.Export;
using Sitecore.Form.Core.Configuration;
using Sitecore.Shell.Framework.Commands;
namespace Sitecore.Sandbox.Forms.Core.Commands.Export
{
public class Export : ExportToXml
{
protected override void AddParameters(NameValueCollection parameters)
{
parameters["filename"] = FileName;
parameters["contentType"] = MimeType;
}
public override void Execute(CommandContext context)
{
SetProperties(context);
base.Execute(context);
}
private void SetProperties(CommandContext context)
{
Assert.ArgumentNotNull(context, "context");
Assert.ArgumentNotNull(context.Parameters, "context.Parameters");
Assert.ArgumentNotNullOrEmpty(context.Parameters["fileName"], "context.Parameters[\"fileName\"]");
Assert.ArgumentNotNullOrEmpty(context.Parameters["mimeType"], "context.Parameters[\"mimeType\"]");
Assert.ArgumentNotNullOrEmpty(context.Parameters["exportPipeline"], "context.Parameters[\"exportPipeline\"]");
Assert.ArgumentNotNullOrEmpty(context.Parameters["progressDialogTitle"], "context.Parameters[\"progressDialogTitle\"]");
FileName = context.Parameters["fileName"];
MimeType = context.Parameters["mimeType"];
ExportPipeline = context.Parameters["exportPipeline"];
ProgressDialogTitle = context.Parameters["progressDialogTitle"];
}
protected override string GetName()
{
return ProgressDialogTitle;
}
protected override string GetProcessorName()
{
return ExportPipeline;
}
private string FileName { get; set; }
private string MimeType { get; set; }
private string ExportPipeline { get; set; }
private string ProgressDialogTitle { get; set; }
}
}
I modeled the above command after Sitecore.Forms.Core.Commands.Export.ExportToExcel in Sitecore.Forms.Core.dll: this command inherits some useful logic of Sitecore.Forms.Core.Commands.Export.ExportToXml but differs along the pipeline being invoked, the name of the export file, and content type of the file being created.
I decided to make the above command be generic: the name of the file, pipeline, progress dialog title — this is a heading that is displayed in a modal dialog that is launched when the data is being exported from the Form Reports — and content type of the file are passed to it from Sitecore via Sheer UI buttons (see below).
I then registered all of the above in Sitecore via the following patch configuration file:
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<commands>
<command name="forms:export" type="Sitecore.Sandbox.Forms.Core.Commands.Export.Export, Sitecore.Sandbox" />
</commands>
<pipelines>
<exportToCsv>
<processor type="Sitecore.Sandbox.Form.Core.Pipelines.Export.Csv.ExportToCsv, Sitecore.Sandbox" />
<processor type="Sitecore.Form.Core.Pipelines.Export.SaveContent, Sitecore.Forms.Core" />
</exportToCsv>
</pipelines>
</sitecore>
</configuration>
Now we must wire the command to Sheer UI buttons. This is how I wired up the export ‘All’ button (this button is available in a dropdown of the main export button in the Form Reports):
I then created another export button which is used when exporting selected rows in the Form Reports:
Let’s see this in action!
I opened up the Form Reports for a test form I had built for a previous blog post, and selected some rows (notice the ‘To CSV’ button in the ribbon):
I clicked the ‘To CSV’ button — doing this launched a progress dialog (I wasn’t fast enough to grab a screenshot of it) — and was prompted to download the following file:
As you can see, the file looks beautiful in Excel 😉 :
If you have any thoughts on this, or ideas for other export data formats that could be incorporated into the Form Reports of Web Forms for Marketers, please share in a comment.
Until next time, have a Sitecoretastic day!









Hello My requirement is I want to export data on front end. I have created a button on sub-layout and now i want to export on click of this button. Is it possible?
Yes, this is possible.
You will have to get the form records using a Sitecore.Forms.Data.DataProviders.WFMDataProvider instance.
Can you please share some code if you have, so I can get idea how I can implement this.
Hello I have done it please see http://sitecoretweaks.wordpress.com/2014/07/02/sitecore-export-to-csvexcel-of-web-form-for-marketers-form-wffm-reports/
blog
Thanks Mike! This article was a very helpful reference point for my own customization of the WFFM export.
I am happy to hear that!
Thanks!
How would you deal with commas in the input fields? For instance, I have a ‘comments’ field, and when a user enters a comma in that field and submits the form it will cause the CSV export to skip a column. I’ve searched around and haven’t found a way to replace characters in wffm fields.