How to: add a ribbon button that calls a Power Automate flow (and downloads generated document as a result)

By | November 20, 2021

If you ever wanted to add a ribbon button that would be calling a flow (one usage scenario for this is to start sing Power BI Paginated Reports and/or Power Automat Word Templates to generate documents/reports), there is a sample script below which you could use to achieve just that.

Here is how the user experience would look like with this script in place:

flowribbon

Here is what’s happening in the script:

  • The script will start by querying the value of the environment variable (which is called ita_documentgenerationflow – you’ll need to change the name of that variable to match your environment). That variable stores HTTP trigger link for the flow to be executed
  • The purpose of this variable is to support DEV->TEST->PROD process, since, once the variable is set properly in those environments, the script will use it to execute the flow
  • Once the script has that url, it will add record id as a parameter, and it will use “fetch” function to call the flow
  • In the success callback it will, then, download generated document

Anyways, here is the script:

function callHTTPFlow(primaryControl) {
	"use strict";
	debugger;
	Xrm.Utility.showProgressIndicator("Generating document...");
	getEnvironmentVariable("ita_documentgenerationflow", 
	    function(url){
			callHTTPFlowInternal(url, primaryControl);
	    },
		function(error){
			handleError(error);
		}
	);
}

function handleError(error)
{
	Xrm.Utility.closeProgressIndicator();
	showMessageDialog("Error", error);
}

function callHTTPFlowInternal(url, primaryControl) {
	"use strict";
	var fileName = "Summary.docx";
	var documentId = primaryControl.data.entity.getId();
	primaryControl.data.save().then(function() {
		
		documentId = documentId.replace("{", "").replace("}", "");
		url = url + "&id=" + documentId;

		fetch(url, {
			method: 'GET',
			headers: {
				'Content-Type': 'application/json'
			},
			body: null //JSON.stringify(data) 
		}).then(response => {
			Xrm.Utility.closeProgressIndicator();
			if (response.status == 200) {
				response.blob().then(blob => {
					downloadFile(blob, fileName);
					closePopups(primaryControl);
				});
			} else {
				response.text().then(body => {
					handleError(body);
				});
			}
		}).then(data => console.log(data))
		.catch(function(error) {
			handleError(error);
		});
	},
	function(error) {
		Xrm.Utility.closeProgressIndicator();
		showMessageDialog("Error", error.message);
	});
}

function closePopups(formContext) {
	formContext.data.refresh(false); 
	Xrm.Utility.closeProgressIndicator();
}
	
function downloadFile(blob, fileName) {
	if (navigator.msSaveBlob) { // IE 10+
		navigator.msSaveBlob(blob, fileName);
	} else {
		var link = document.createElement("a");
		if (link.download !== undefined) {
			var 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);
		}
	}
}

function showMessageDialog(messageTitle, message) {
	var alertStrings = {
		confirmButtonLabel: "OK",
		text: message,
		title: messageTitle
	};
	var alertOptions = {
		height: 120,
		width: 260
	};
	Xrm.Navigation.openAlertDialog(alertStrings, alertOptions);
}


function getEnvironmentVariable(varName, onSuccess, onError){
  "use strict";
   Xrm.WebApi.retrieveMultipleRecords("environmentvariabledefinition", "?$select=defaultvalue,displayname&$expand=environmentvariabledefinition_environmentvariablevalue($select=value)&$filter=schemaname eq '"+varName+"'").then(
		function success(result) {
			var varValue = null;
			for (var i = 0; i < result.entities.length; i++) {
			    
				if(typeof(result.entities[i]["environmentvariabledefinition_environmentvariablevalue"]) != "undefined"
				   && result.entities[i]["environmentvariabledefinition_environmentvariablevalue"].length > 0)
				{
				   varValue = result.entities[i]["environmentvariabledefinition_environmentvariablevalue"][0].value;
				}
				else if(typeof(result.entities[i].defaultvalue) != "undefined")
				{
				   varValue = result.entities[i].defaultvalue;
				}
				else{
				   varValue = null;
				}
			}    
			onSuccess(varValue);	
		},
		function (error) {
			console.log(error.message);
			onError(error);			
		}
	);
}

And here is how the button is configured in the ribbon workbench:

image

And here is one more screenshot just for completeness – this is how you could configure response action of your flow to work with the script above:

image

Nov 23: if you wanted to see a more detailed example of the flow, have a look at this post

2 thoughts on “How to: add a ribbon button that calls a Power Automate flow (and downloads generated document as a result)

Leave a Reply to Alex Shlega Cancel reply

Your email address will not be published. Required fields are marked *