Did you ever want to build a report in Dynamics CRM and download it in PDF format without having to manually rename the file? This is one of those things that makes a difference from the end user perspective since it streamlines the process – there is no need, anymore, to go back to the underlying record and copy-paste information from some of the fields to the file name.
Unfortunately, even though it seems reasonable, this feature is not supported out of the box. Moreover, Dynamics CRM uses SSRS for reporting, and, to the best of my knowledge, SSRS does not support this feature either. This is not to mention that we have limited control over SSRS functionality when working with Dynamics CRM in general and with the online version of Dynamics CRM in particular.
We can make it work, though, and you will find step-by-step instructions below. Please keep in mind that this solution uses some of the undocumented java script SSRS-related objects which may or may not exist in the newer versions of Dynamics CRM. As of now it works, though, and, I believe, all those undocumented features (there are really just one or two) will be available in the future.
So, here is what we have out of the box:
It is the last step that we want to eliminate:
We want to be able to name the file automatically as part of the “Export to PDF” step.
Here is how we are going to do it:
- We will do it using “salesorder” entity as an example, but it is easy to do the same for other entities as well.
- We will create a java script that will be loaded as a web resource to the order form.
- In that java script, we will define a single function that will be called in form “onload”.
- That function will re-define window.open so that we can run additional code whenever user decides to build a report.
- Our additional code will use java script setTimeout in order to wait until the report is loaded, and, then, modify report file name.
We will be using undocumented features of Dynamics CRM only once: in order to modify the file name, we will have to access java script instance of the reporting component. I believe this part of Dynamics CRM functionality is not really documented, but one can always use Internet Explorer developer tools (F12) to do some research.
Let’s take a look at the details:
- Create a new web resource (jscript)
- Give it a name (let’s use “new_reporting”)
- Using web resource “text editor” button, add the following java script:
function setHandlers()
{
var newFileName = Xrm.Page.getAttribute(“ordernumber”).getValue();//Change attribute name for other entities
window.open = function (open) {
return function (url, name, features) {
var timeout = 2000;
var newWindow = null;
if(features != null) newWindow = open(url, name, features);
else if(name != null) newWindow = open(url, name);
else newWindow = open(url);
function timeoutFunc()
{
var rv = null;
var r = null;
try
{
rv = newWindow.frames[ “resultFrame” ].$find(“reportViewer”);
r =rv._getInternalViewer();
}
catch(err)
{
setTimeout(timeoutFunc, timeout);
return;
}
if(r == null)
{
setTimeout(timeoutFunc, timeout);
return;
}
else
{
var url = r.ExportUrlBase;
var i = url.indexOf(“FileName=”);
var j = url.indexOf(“&”, i+1);
var oldFileName = url.substring(i+9, j);
r.ExportUrlBase = url.substring(0,i) + “FileName=”+ newFileName + oldFileName + url.substring(j);//Use this line to assign new file name
}
};
if(url.indexOf(“viewer.aspx”) > 0)
{
setTimeout(timeoutFunc, timeout);
}
return newWindow;
};
}(window.open);
}
This function does the following:
- It overrides window.open with a new function
- Whenever another java script makes a call to window.open, our overridden version will be called instead
- First, we will forward that request to the original window.open. After that, we will verify if requested url contains “viewer.aspx” substring. If it does not contain such a substring, we don’t need to do anything.
- If it does contain the substring, we will use setTimeout using internal “timeoutFunc” as a parameter
- The purpose of the internal “timeoutFunc” function is simple:
- It will verify if the report is loaded. If not, it will call another setTimeout, and it will keep doing it until the report is finally loaded (yes, there could be potential problem here)
- If the report has been loaded, finally, it will update “ExportUrlBase “ property of the reporting control
And that’s, pretty much, it.
What’s left is:
- Save this web resource and publish it
- Add this web resource to the order form
- Add “onload” event and specify setHandlers java script function for that event
- Save order form and publish it
Finally, verify the results:
Hope this helps.