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 !!
Thanks for sharing!
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
We have recently updated our environments for wave 2 but we are not experiencing this issue, please recheck/debug your code.
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.
Yes, we have this code in different environments and it’s working fine.
Hi
When we are downloading it is showing corrupt file , using on Dynamics online .
can you please help.
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);
}
}
}
);