Sunday, 14 June 2026

Reliably embed an image from SharePoint into a Power Automate email


If you're sending out emails using Power Automate and you want to embed an image from SharePoint, you need a clean link.

The basic HTML to embed the image is nice and simple:

<img src="image-url">

But getting a link from SharePoint can be tricky. You can't just copy the URL or click Copy Link because that comes with a whole bunch of possible tokens which can make the URL very long and unwieldy. 

More than that though, the tokens can include permissions and that can prevent your workflow from accessing the file. What you want is a simple URL that points directly to the file so that Power Automate can use it. 

It turns out there is a simple way to get that URL, it's just slightly hidden away. 

Select your image file in the library and click ... > Details to open up the Details side bar on the right hand side. Scroll all the way down to the bottom to find the Path information.

Click the Copy icon to get a clean URL directly to the file::


Use that URL in your HTML. Remember the basic HTML from earlier?

<img src="image-url">

That was taken from the Microsoft Learn page on this subject and they have forgotten something very important: Adding ALT text.

Making your emails accessible for people with sight issues should be something you do as standard. It's a tiny tweak that looks like this:

<img src="image-url" alt="ALT TEXT">

It's also worth adding in sizing if you need to make sure that an an image always renders as you want it to, and that is equally simple:

<img src="image-url" width="x" height="y" alt="ALT TEXT">

And there you go: a simple method for getting a simple URL for embedding images in emails. 

Sunday, 7 June 2026

Round Up Numbers from Power Automate to SharePoint

 


This problem came up for me when I was using Power Automate to calculate an average of 3 numbers that had been entered into an MS Form.

The requirement was for the average to be shown as a whole number in a SharePoint list column, but with rounding down for decimals less than 0.5 and rounding up for decimals of 0.5 or higher as per normal mathematical conventions. 

This seems simple enough but when you set a Number column in SharePoint to show 0 decimal places it doesn't round numbers or down. Instead it just truncates the decimal values. So whether you have 3.1 or 3.7, if you show those figures to 0 decimal places SharePoint will show both of them as 3. That's fine for decimals of .4 or lower but what about decimals of 0.5 or above you need to round up?


Here's how to do it in Power Automate:

  1. (I was calculating my number so I'll show that step but you can skip this if you've already got your number through some other means.) Calculate your average using an expression, for example:

    div(add(add(outputs('First Number'), outputs('Second Number')), outputs('Third Number')), 3)

  2. Convert it to a decimal number with 1 decimal place using Format Number with a custom value of 0.0 for the Format:


    (if you have a whole number like 3, this will convert it to 3.0 and the below technique will still work perfectly)

  3. This is where the magic happens: Use an expression to add 0.5 to the output of the Format step, if required:

if(greaterOrEquals(int(substring(body('Format'), add(length(body('Format')), -1), 1)), 5), add(float(body('Format')), 0.5), body('Format')) 

What is this expression doing? This part of the expression:

 int(substring(body('Format'), add(length(body('Format')), -1), 1)

is getting the last digit of your number.  Let's assume your number is 3.7, which means this part of the expression will return the number 7.

If we swap in the number 7, we get this expression: 

if(greaterOrEquals(7, 5), add(float(body('Format')), 0.5), body('Format'))

greaterOrEquals takes 2 arguments: The number to check, and the number to check against. 7 is greater than 5 so this will return true

If we swap in true we get this expression: 

if(true, add(float(body('Format')), 0.5), body('Format'))

If takes 3 inputs: A logical argument, the thing to do if the argument is true, and the thing to do if the argument is false. In this case if the argument is true we add 0.5 to the average and return that value, and if it false we just return the average. 

Because 7 is greater than 5 the If statement returns true, so it adds 0.5 to the average and returns 3.7 + 0.5 = 4.2.  If the decimal was less than 5 , such as 3.1, then the If statement would return false and just return the average.

Remember, SharePoint doesn't round up so when SharePoint formats your number to 0 decimal places both 3.1 and 3.7 will be shown as 3. 

So by adding 0.5 to any number where the last digit is 5 or greater we'll end up with the next whole number. In this case, that will be 4.2, so when SharePoint truncates it to 0 decimal places, you get 4. 

This meets the mathematical convention of "rounding up" 0.5 and above to the next integer even if we're not technical rounding up, we're just amending the number to fool SharePoint into looking like its rounded up.

Wednesday, 15 March 2023

Power Automate: Use FIRST Instead of "Apply to each" When Pulling Out a Single Value


Credit: Patrick Tomasso

If you're returning rows from a spreadsheet or a SharePoint list, you normally use an "Apply to each" action to pull out the data.

But when you use "Apply to each" the entire row is pulled into memory and this can be slow, especially if you've got a lot of columns. 

If there is only one row this isn't necessary; instead you can use the "First" expression, which is much quicker as it just loads a specific column value rather than the whole row.

Let's say you're filtering on a unique refeerence number column called "URN" to return a specific row using an OData Filter Query, such as urn eq 'example', and you want to get the value of a column from that row called "Start Date".

A screenshot of a "List rows present in a table" action showing a filter query

Rather than using "Apply to each" to pull the value out, use the following expression in a Compose or Set Variable action:

First(outputs('List_rows_present_in_a_table')?['body']?['value'])?['Start Date']

An "Initialize variable" action showing the FIRST expression

And now you've got the value you need without having to load all the rows - it's quicker, uses one less step, and is easy to implement.