Emailing an SSRS Report using ReportViewer

Introduction

SQL Server Reporting Services (SSRS) is Microsoft’s offering in the reporting space, if you install SSRS as part of a SQL Server install you get a nice web front end through which users can navigate and view reports. But SSRS is not restricted to this online portal style access, reports can be embedded into you application using the ReportViewer component shipped with Visual Studio.

Through the ReportViewer component users can view, export and print reports in exactly the same manner as the web based version but we also get some nice hooks into the ReportViewer control, I’m going to demo how we can use these to extract the report to a pdf and attach it to a new outlook message ready for the user to view and send. I’m using the inbuilt Outlook interoperability to achieve this but you could just as easily apply the same principles to another method of email delivery.

I’m doing this demo using VS2008 but it will work in exactly the same manner in VS2005.

Adding a ReportViewer

For this demo I’m starting with a blank form, first we need to drag a ReportViewer control onto the design surface. I’m using the a report stored on an SSRS server in this demo but you can also include reports locally in your solution, whichever option you choose does not affect the following steps.

Configure the report viewer to point to your report, I’m using a server based report so I have expanded the “ServerReport” property and specified a report server and a report path, I have also changed the “ProcessingMode” property to “Remote” to specify that I am using a remote report.

Now when we run the application we are able to interact with the report.

Exporting the Report

To attach our report to an email the first step is to get the pdf file out to disk, I’m going to write a utility type function to achieve this which will return a filepath to the saved PDF file;

//You will need to import these namespaces
using Microsoft.Reporting.WinForms;
using System.IO;
/// <summary>
/// Exports the current report out to a pdf file
/// </summary>
/// <returns>
/// Path to the file that was generated
/// </returns>
private string ExportReport()
{
    Warning[] warnings;
    string[] streamids;
    string mimeType;
    string encoding;
    string filenameExtension;

    //Render the report to a byte array
    byte[] bytes;
    if (reportViewer1.ProcessingMode == ProcessingMode.Local)
    {
       bytes = reportViewer1.LocalReport.Render("PDF", null, out mimeType,
           out encoding, out filenameExtension, out streamids, out warnings);
    }
    else
    {
       bytes = reportViewer1.ServerReport.Render("PDF", null, out mimeType,
          out encoding, out filenameExtension, out streamids, out warnings);
    }

    //Write report out to temporary PDF file
    string filename = Path.Combine(Path.GetTempPath(), "ReportToAttach.pdf");
    using (FileStream fs = new FileStream(filename, FileMode.Create))
    {
        fs.Write(bytes, 0, bytes.Length);
    }

    //return path to saved file
    return filename;
}

Sending the Email

The last step is to attach the report to a new email and load it up for the user, I’m using the Outlook interoperability assemblies. If you want to use the same method you will need to add a reference to Microsoft.Office.Interop.Outlook to your project.

Let’s add a button to our form to kick of the process and in the event handler we will create an email and attach our report.

//You will need to import this namespaces
using Microsoft.Office.Interop.Outlook;
private void emailButton_Click(object sender, EventArgs e)
{
    //Write report out to temporary PDF file
    string reportFilename = ExportReport();

    // Create a new email using outlook
    ApplicationClass outlookApp = new ApplicationClass();
    MailItem mailItem = (MailItem)outlookApp.CreateItem(OlItemType.olMailItem);
    mailItem.To = "mail@yourdomain.com";
    mailItem.Subject = "Your Report";
    mailItem.Body = "Please find your report attached";
    mailItem.Attachments.Add(reportFilename, (int)OlAttachmentType.olByValue, 1, reportFilename); 

    //Remove the temp file once attached
    File.Delete(reportFilename);

    // Display the window
    mailItem.Display(false);
}

Now when we click the button we should get a new outlook message with the PDF attached;