Anytime I’m working on any sort of coding project Google is really my savior – there is absolutely no way I can know how all of the different libraries and functions available inside of all the .net components, nor do I really care to. Sometimes I’ll get lucky and find exactly what I’m looking for but in reality it’s a fury of Google searches opened up in multiple tabs that end up getting pieced together into what I call “Production Code”. Anytime I have to piece together solutions from various sites I try and post the finished product here – mainly so I don’t have to go and find it all again the next time I do it but also I’m sure it helps the odd stranger during his Google-Fu – so with that said, and with #vDM30in30 looming over me here’s a solution to help with connecting to a SharePoint integrated reporting services instance, passing parameters to a report, and exporting the report to pdf through code-behind.
I chose to do this as a c# Windows Forms app but you could technically try and reproduce the code with some slight changes if you were to use asp. Either way we only need two controls on the form to make it work; a ReportViewer and a Button – go ahead and drag those onto the form.
So for the setup of the ReportViewer control there are only a few properties we need to setup in order to get our connection to the SharePoint SSRS instance which are listed below
- ProcessingMode – Set this to Remote. This simply states that the report we will be running is located remotely
- Then under ServerReport we need to specify a couple of options
- ReportServerUrl – This is the URL to the SSRS Report Server. Usually, in SharePoint integrated mode it will be the same as your site URL, with ‘_vti_bin/reportserver/’ tagged on the end. IE, https://mysharepoint.url/sitename/_vti_bin/reportserver/
- ReportPath – This is the path to the report you would like to process, relative to your ReportServerUrl. So if you browse to your Report Server and keep track of the directories you click on to get to the desired rdl – this is what goes into this property – IE Reports/MyReports/ReportName.rdl
And some code…
First up we are going to be accessing a few methods and objects outside of the normal c# includes. In order to gain access to these you will need to import the following references into your project and declare them at the top of your cs file – Use nuget it’s much easier 🙂
1 2 3 4 |
using Microsoft.Reporting.WinForms.Internal.Soap.ReportingServices2005.Execution; using Microsoft.Reporting.WinForms; using System.Web.Services.Protocols; using System.IO; |
And the code for the main click event on our button….
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
private void Button1_Click(object sender, EventArgs e) { string FilePath = "C:\\Desired\\Path\\"; // define and add parameteres Microsoft.Reporting.WinForms.ReportParameter[] reportParameterCollection = new Microsoft.Reporting.WinForms.ReportParameter[3]; reportParameterCollection[0] = new Microsoft.Reporting.WinForms.ReportParameter(); reportParameterCollection[0].Name = "Parameter1"; reportParameterCollection[0].Values.Add("Param1Value"); reportParameterCollection[1] = new Microsoft.Reporting.WinForms.ReportParameter(); reportParameterCollection[1].Name = "Parameter2"; reportParameterCollection[1].Values.Add("Param2Value"); reportParameterCollection[2] = new Microsoft.Reporting.WinForms.ReportParameter(); reportParameterCollection[2].Name = "Parameter3"; reportParameterCollection[2].Values.Add("Param3Value"); reportViewer1.ServerReport.SetParameters(reportParameterCollection); //render report string[] streamids; string mimeType, encoding, extension; string deviceInf = "8.5in11in"; Microsoft.Reporting.WinForms.Warning[] warnings; byte[] bytes = reportViewer1.ServerReport.Render("PDF", deviceInf, out mimeType, out encoding, out extension, out streamids, out warnings); //write file and refresh reportviewer control string completefilename = FilePath + "Report.pdf"; FileStream fs = new FileStream(completefilename, FileMode.Create, FileAccess.Write); fs.Write(bytes, 0, bytes.Length); fs.Close(); reportViewer1.RefreshReport(); } |
So lets break this down into manageable chunks of code…
Line 3 simply defines the path to the folder where we would like to export the report
Lines 5 through 15 define and set three parameters for our report. Obviously if your has more/less you can adjust accordingly. Line 16 simply calls the setParameters function of our ReportViewer component and passes our newly generated parameters.
Lines 18 through 22 define and set a few variables that we need setup in order to render our report but the real magic happens on line 23 where we call the render function of our ReportViewer and store the PDF result in an array of bytes.
Lines 26 through 29 take our bytes array and utilize a FileStream object in order to write the information to a pdf file.
I’ve included a refresh command on Line 30 even though it isn’t needed for just rendering one report. I wanted to place this in here just in case someone may be copying the code to achieve the same thing I was trying to achieve. Basically I had all of this code within a loop – I was looping through various strings and running my target report multiple times, each time with different parameters – in order to do this you need to call the RefreshReport() method at the end of every run in order to allow the object to completely initialize. I even went as far as to set the visibility of the ReportViewer object false as I simply just wanted to click a button and be left with a folder full of pdfs. So, not needed for 1 run, but if you place the code into a loop its needed.
So in essence this is the code I’ve used. It certainly is a time saver – we used to have someone manually changing parameters and dumping these reports to PDF which as you can imagine can take quite a long time if you need to do it a few hundred times – now, it’s simply an application that they run…
Happy coding.