Wednesday, June 28, 2017

Dynamics CRM Word Document Templates that use FetchXML for Complex Data Retrieval


It is a little bit longer but informative post so please bare with me :)

Dynamics CRM now allows you to create and persist Document Templates using Microsoft Word. I discovered one shortcoming. The user interface in CRM forces you to select a single starting entity and only entities that have a direct relationship for the data. SO what if you want to pull in data from other entities that do not have a direct relationship in your data model? Or what if you want to retrieve data from another external system?

We have already created reports in SSRS that use FetchXML as the data source so what else can we do to leverage FetchXML as the data source for the new Word Document Templates?. This approach is possible and not at all difficult leveraging the Open XML SDK for Microsoft Office.

1. Retrieve your Data

Determine what data it to be be retrieves to display in the Word Template.

The easiest way to create your FetchXML query is to do an advanced find from within CRM and then export the FetchXML from there.

So, for our example, let’s just run a default Fetch for Accounts.

Click the Download Fetch XML button and Save the resulting Fetch statement. You should have a simple FetchXML query that looks like the following:

Now that we know what data and how to get it, let’s move onto creating a Word Template.

2. Create Word Template in CRM

From the Settings menu select Templates and then Document Templates. 

From this page see the Available OOTB Templates that come with CRM and either Create a New Template or Upload one you already have.

For our approach, we will select New.

On the next screen, l select Word Template and for our example use the Account entity. Keep in mind that the entity you select is irrelevant with this approach since we will be retrieving and binding the data on our own.

After clicking Select Entity you are presented with the Select Entity screen  - pick any other Entities that have a direct Relationship to the Account. This is limiting since there might be other entities that we would like to pull in (or you might have data from other systems as well you would like to retrieve and display in the report).

At this point select Download Template and do some design in Word.

3. Populate Word Template with Content Controls

At this point we have a not-so-exciting blank document Open in Word. The first thing we need to do is Show the Developer tab in the Word Ribbon.


 Now we can insert Plain Text Content Controls to display the data we would like in the document.

 click the 2nd Aa button in the Controls section of the Developer tab.

See the Content Control appear in your document at the position of your cursor that reads "Click or tap here to enter text".

The Content Control is basically just a placeholder that you can use to control the layout of your document.

We still have not specified what data this field should display. - select the Content Control and click Properties from the Controls section of the Developer tab.

Now here is a bit of the magic, you must be familiar with what data you will be retrieving which we already determined in Section 1 when defining our Fetch.

You will need the following function to execute your Fetch and to return the results as a DataTable:

The call for that will look like the following:

This gives you a resulting XML in accountDataAsXML:

Let’s say for this first control we want to display the Account Name. The XPath for that in XML will be: /ReportData/Account/name.

XPath is straight forward you just follow down the hierarchy of the XML.
With that information, populate the tag on our Content Control so it looks like the following:


To keep this extremely simple since save the template and upload it into CRM. Just like before, from the Settings menu select Templates and then Document Templates. From this page, you can select UPLOAD TEMPLATE and browse out to the Word Template on your local system.



4. Retrieve Word Template Contents

 When you get ready to run the report (how you choose to do this is entirely up to you and can be custom workflow activity, plugin, etc.) you will need to retrieve the Word Template Contents. Here is a function to get the Document Template ID which is a basic retrieve of the DocumentTemplate entity with a name filter.

Once you have that, you can get the Document Template contents as a byte array like this:

5. Merge the data into the Word Document Template



So now at this point we have our CRM data in an XML string and our Word Document contents in a byte array and we need to get the two to merge. Here is an example of how to do that:

that’s a large amount of code, what does it all do? While most of this understandable to a CRM developer, the main part to pay attention to is the using statement with the WordprocessingDocument. To understand that code, take a quick detour into the land of OpenXML.

All Microsoft Office documents are just a bunch of files zipped together? Take that Word Document Template we have been working with on your machine for this example and change the .docx extension to a .zip. Now extract that file.? You might see something like this:

We won’t examine all of these files, look at the document.xml in the word folder. If you open that file then you will see an XML representation of what is in your Document starting with a ton of namespaces for the different Office libraries. After that you get into the body of the document which will look something like this:

Notice anything familiar? - that XPath that we entered on the Content Control is there in the tag  - right where we put it.

The Open XML SDK for Microsoft Office is what allows you to manipulate this underlying XML. So let’s do a quick breakdown of that code above.

To save the generated document as a Note on an entity, you could do something like the following (which again is fairly common CRM coding):

that was a whirlwind tour of how to leverage FetchXML for data retrieval and use that data within a Word Document Template.  To recap the steps are:

1.     Retrieve your data

2.     Create Word Template in CRM

3.     Populate Word Template with content control placeholders

4.     Retrieve the Word Template contents

5.     Merge the data into the template using the Open XML sdk.

 Keep in mind, that FetchXML is obviously only one choice for data retrieval and we chose that since we were porting over existing SSRS reports. You could also leverage other means of gathering data such as web services to external systems. The only real requirement is that the data you retrieve eventually ends up in an XML string so you can leverage XPath to bind it to the Content Controls.

No comments:

Post a Comment

if you have any doubts, please tell me

More Than One Form Was Opened at Once for the Lookup Control

In Dynamics 365 for Finance and Operations, when subscribing to a lookup event to modify an existing lookup on a form control, you must...