Download Word Document Template using JavaScript- Dynamics 365 CE

Requirement
We got one requirement where we wanted to download Word Document based on the word template after validating some conditions. I am going to share sample code which can be used to download word document based on the template name.

Solution
We create a flyout button similar to existing word template flyout and hide out of the box flyout button. While working code, I found similar code here which helped me for downloading file but the file was corrupted after download so I am sharing code which worked for me.

You can refer our earlier post for creating flyout button and passing parameters.

function DownloadWT(formContext, entityTypeCode)
{
    //display notification
    Xrm.Utility.showProgressIndicator("Exporting to Word");
    var filename= "Demo.docx"//replace file name here
    var templateType = 9940;
    var Query=  Query = "?$select=documenttemplateid&$filter=name eq 'WORD TEMPLATE NAME'";//replace it accordingly
    var id = formContext.data.entity.getId();
    var globalContext = Xrm.Utility.getGlobalContext();
    var path = globalContext.getClientUrl() + "/_grid/print/print_data.aspx";

    //query template record based name
Xrm.WebApi.online.retrieveMultipleRecords("documenttemplate", Query).then(
                function success(results) {
                    if (results.entities.length > 0) {
                        var wordTemplateId = results.entities[0]["documenttemplateid"];
                        var request = "exportType=MergeWordTemplate&selectedRecords=" + encodeURIComponent(JSON.stringify(id)) +
                            "&associatedentitytypecode=" + entityTypeCode + "&TemplateId=" + wordTemplateId + "&TemplateType=" + templateType;
                
                        var req = new XMLHttpRequest();
                        req.open("POST", path, true);
                        req.responseType = "arraybuffer";
                        req.setRequestHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
                        req.setRequestHeader("Accept-Language", "en-US,en;q=0.8");
                        req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
                        req.onreadystatechange = function () {
                            if (this.readyState == 4) {/* complete */
                                req.onreadystatechange = null;
                                if (this.status >= 200 && this.status <= 299) {
                                    var mimetype = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
                                    var blob = new Blob([req.response], { type: mimetype });
                                    var downloadurl = URL.createObjectURL(blob);
                                    if (navigator.msSaveOrOpenBlob) {
                                        navigator.msSaveOrOpenBlob(blob, filename);
                                        return;
                                    }
                                   
                                    //download file
                                    var a = document.createElement("a");
                                    document.body.appendChild(a);
                                    a.style = "display: none";
                                    a.href = downloadurl;
                                    a.download = filename;
                                    a.click();
                                    URL.revokeObjectURL(downloadurl);
                                    Xrm.Utility.closeProgressIndicator();
                                 }
                                else {
                                    Console.Write("An Error occurred generating the word document." + err.message);
                                }
                            }
                        };
                        req.send(request);
                    }
                },
                function (error) {
                   Console.Write(error.message);
                });
}

In above code I am passing two parameter from ribbon command bar:
1. formContext – This is get form contact to access form control, we can pass PrimaryControl as CrmParameter from button command.
2. entityTypeCode – This parameter is for the entity code, we can get it CrmParameter –PrimaryEntityTypeCode.

We can pass these parameter in the Java Script action for our button. After getting these parameter we can query template based on the name and download it using above code.

Hope it will help someone!
Keep learning, Keep sharing !!

7 thoughts on “Download Word Document Template using JavaScript- Dynamics 365 CE

  1. Satish Srinivas

    i still get the corrupted msg. i did add a query part for the template to get the one that is activated as mine had a few more in draft status. but not sure why this is happening post wave 2

    Reply
  2. Ingrid Andersson

    Hi! Is this code still actual and working? In our case when we try to reach the print_data.aspx file through that specified path in our Dynamics environment – we get an instant redirect to popuperror.aspx saying “An error has occured”. And instead of a downloaded Word file – we get an docx with HTML instead – with the content of the popuperror.aspx. Are we missing something in the CRM environment to be able to reach print_data.aspx file maybe? Thanks! Sincerely, Ingrid.

    Reply
  3. Krystian

    For everyone who wants to generate word documents from JS in Dyn365 Online;

    In the internet you can find ‘list of undocumented SDK messages’ for Dynamics (I don’t know if I can put the website url here). It is unsupported, but it works now. Thanks to that I prepare a sample code for downloading Word templates (you only need to put that in function, change parameters like EntityTypeCode, templateid, filename… etc.)

    fetch(Xrm.Utility.getGlobalContext().getClientUrl() + “/api/data/v9.0/ExportWordDocument”, {
    method: “POST”,
    body: JSON.stringify({
    EntityTypeCode: 1084, //change to valid code
    SelectedRecords: “[\”{6F7651A2-1AE4-ED11-A7C7-000D3ABE768E}\”]”, //array of records
    SelectedTemplate: {
    ‘@odata.type': “Microsoft.Dynamics.CRM.documenttemplate”,
    documenttemplateid: “296cb76d-0b59-e811-8126-5065f38bd3c1″ //change to valie templateId or retrieve id by template name earlier
    }
    }),
    headers: {
    “Content-Type”: “application/json”,
    “Accept”: “application/json”,
    “Accept-Language”: “*”
    }
    }).then((response) => response.json())
    .then((json) => {
    const binaryString = window.atob(json.WordFile);
    const bytes = new Uint8Array(binaryString.length);
    const arrayBuffer = bytes.map((byte, i) => binaryString.charCodeAt(i));

    const blob = new Blob([arrayBuffer]);
    const fileName = ‘TEST.docx';
    if (navigator.msSaveBlob) {
    // IE 10+
    navigator.msSaveBlob(blob, fileName);
    } else {
    const link = document.createElement(‘a’);
    // Browsers that support HTML5 download attribute
    if (link.download !== undefined) {
    const url = URL.createObjectURL(blob);
    link.setAttribute(‘href’, url);
    link.setAttribute(‘download’, fileName);
    link.style.visibility = ‘hidden';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    }
    }
    }
    );

    Reply

Leave a Reply