Friday, October 28, 2011

How To: Programmatically generate a report and save the results as a PDF to SharePoint.

I had a requirement this week to run a report from within one of our WCF services, get it as a PDF file and then save it to a SharePoint library. To do this you have to use the reporting services ReportExecutionService to run the report and get the file, then use the SharePoint Copy service to store it in the library. Here's how:

1. Add a web reference to the service 
1.1 Right click on your project and click on Add Service Reference
 1.2 Click on the Advanced button in the bottom left
 1.3 Click on Add Web Reference
 1.4 In the URL box add the reference to
http://yourReportServer/reportserver/reportexecution2005.asmx?wsdl
 1.5 Give your service a name and click on Add Reference

2. Create the service call method

// create the service
ReportExecutionService rs = new ReportExecutionService();
rs.Credentials = EcmServices.CreateNetworkCredential();
rs.Url = ConfigurationSettings.AppSettings["ReportServerUrl"];


// Prepare report parameter.
ParameterValue[] parameters = new ParameterValue[1];
parameters[0] = new ParameterValue();
parameters[0].Name = "ID";
parameters[0].Value = id;  // this is a value I pass to the method


// render arguments
byte[] result = null;
string reportPath = "/My Reports/Report";
string format = "PDF";
string historyID = null;
string devInfo = @"<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>";
string encoding;
string mimeType;
string extension;
Warning[] warnings = null;
string[] streamIDs = null;


// create execution info
ExecutionInfo execInfo = new ExecutionInfo();
ExecutionHeader execHeader = new ExecutionHeader();
rs.ExecutionHeaderValue = execHeader;
execInfo = rs.LoadReport(reportPath, historyID);
rs.SetExecutionParameters(parameters, "en-us");
String SessionId = rs.ExecutionHeaderValue.ExecutionID;


// execute the report and get the rendered file as a byte array
result = rs.Render(format, devInfo, out extension, out encoding, out mimeType, out warnings, out streamIDs);
execInfo = rs.GetExecutionInfo();


if(result != null)
{
 SubmitFileToSharePoint(result, id);
}


As above, the results return as a byte[] and this can be used in the SharePoint Copy service to store the file.

3. Store the file using the SharePoint Copy service
You need to add a web reference to the SharePoint Copy service in the same way as you did for the ReportExecutionService. The URL for this service is: http://yourSharepointServer/_vti_bin/Copy.asmx
public static void SubmitFileToSharePoint(byte[] fileBytes, int id){
 // create the copy service
 Copy copyWS = new Copy();
 copyWS.Url = "
http://yourSharepointServer/_vti_bin/Copy.asmx";
 copyWS.Credentials = System.Net.NetworkCredential("username", "password", "domain");


 // create the file url
 string documentLibraryUrl = "
http://yourSharepointServer/Documents/Report_" + id + ".pdf";
 string[] destinationUrls = { documentLibraryUrl };


 // set metadata values on the file
 FieldInformation info1 = new FieldInformation();
 info1.DisplayName = "Report ID";
 info1.Value = id.ToString();
 FieldInformation[] info = { info1 };


 // create the result variable
 var copyResult = new CopyResult();
 CopyResult[] copyResults = { copyResult };


 // copy the file
 copyWS.CopyIntoItems(documentLibraryUrl, destinationUrls, info, fileBytes, out copyResults);
 copyWS.Dispose();

 if (copyResults[0].ErrorCode != CopyErrorCode.Success)
 {
  throw new SPException(string.Format("Error copying file to {0}. {1}", copyResults[0].DestinationUrl, copyResults[0].ErrorMessage));
 }
}

No comments:

Post a Comment