• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar

Tachytelic.net

  • Get in Touch
  • About Me

Power Platform

Power Automate HTML Table Styling and Formatting

November 9, 2020 by Paulie 18 Comments

The Create HTML Table action in Power Automate is a useful tool, but lacks any formatting or styling options. In this post I am going to explain how to format the HTML table produced by Power Automate. Here is an example of the default output:

Image of the default unformatted output of the Create HTML Table action in Microsoft Power Automate

In my opinion:

  • The table is just ugly.
  • There are no column alignment options.
  • If you are using custom columns, it does not allow you to put spaces in the column headers.

The good news is that the Create HTML Table action produces basic HTML that can be easily modified or styled. The HTML source of the table generated above by Power Automate above is:

<table>
   <thead>
      <tr>
         <th>FirstName</th>
         <th>LastName</th>
         <th>JobDescription</th>
         <th>Furloughed</th>
         <th>FurlougedDate</th>
      </tr>
   </thead>
   <tbody>
      <tr>
         <td>Paul</td>
         <td>Murana</td>
         <td>Power Automate Developer</td>
         <td>No</td>
         <td></td>
      </tr>
      <tr>
         <td>Micheal</td>
         <td>Knight</td>
         <td>Lone Ranger</td>
         <td>Yes</td>
         <td>1986-04-04</td>
      </tr>
      <tr>
         <td>Peter</td>
         <td>Venkman</td>
         <td>Ghost Hunter</td>
         <td>No</td>
         <td></td>
      </tr>
      <tr>
         <td>John</td>
         <td>Rambo</td>
         <td>Mercenary</td>
         <td>No</td>
         <td></td>
      </tr>
   </tbody>
</table>

Use CSS to create a much more attractive table

By adding some CSS, you can make the table much more attractive very quickly:

Image of an HTML Table from Flow which has had styling applied.

The simple CSS I applied to the above is:

<style>
Table {
  font-family: Arial, Helvetica, sans-serif;
  background-color: #EEEEEE;
  border-collapse: collapse;
  width: 100%;
}

Table td, Table th {
  border: 1px solid #ddd;
  padding: 3px 3px;
}

Table th {
  font-size: 15px;
  font-weight: bold;
  padding-top: 12px;
  padding-bottom: 12px;
  text-align: left;
  background-color: #1C6EA4;
  color: white;
}
</style>

If you aren’t a CSS wizard you can use https://divtable.com/table-styler/ to get you started.

So now you have got the CSS, here is how to add it to the table:

  • Create a compose step called CSS Table Style.
  • Paste your CSS into that compose action.
  • In your Send an email action paste the CSS and then the HTML Table:
    Image showing how to insert CSS Into a HTML Table generated by Power Automate

You can put anything else you need in the body, but I would suggest that you put the CSS before anything else.

Add spaces to the column headings

In my example, I used custom columns and I was unable to add spaces to the column headings. So here is my workaround:

  • Use a carat ^ symbol wherever you want a space in the column header.
  • Create a compose action to replace the carat with a space.
  • Select the output of the compose in your email instead of your HTML Table output:
Image showing how to add spaces to column headers in the Power Automate Create HTML Table action.

The compose expression is:

replace(body('Create_HTML_table'), '^', ' ')

You could of course use any symbol, but make sure to use one that isn’t going to be in use elsewhere in the table. The carats are replaced with spaces:

Image of a HTML Table produced by Power Automate with CSS style applied.

You can take this much further by not using the Create HTML Table action at all, and constructing your own table directly in Power Automate and looping through an array of records. This is something I do sometimes, but it is a lot more work and I wanted to quickly cover how to improve the look of the standard action.

Filed Under: Power Platform Tagged With: Power Automate

Remove unwanted characters from a string in Power Automate

October 30, 2020 by Paulie 10 Comments

This blog post explains how to remove unwanted characters from a string in a Power Automate flow. These can be regular characters or unprintable characters, such as control codes.

My example string:


<note>
	<to>[email protected]</to>
	<from>Michael Knight</from>
	<heading>Reminder</heading>
	<body>Don't forget to clean KITT this weekend!!!
	</body>
</note>

The aim is to remove the apostrophes, exclamation marks and the two non-printable characters. The non-printable characters are visible in Notepad++ :

As you can see from the screenshot, the non-printable characters are the SOH (Start of heading) and BEL (Bell).

It is possible to replace all unwanted characters without any apply to each loops for maximum speed. If you just want implement this flow without understanding how it works, please just skip to the section Quick Paste Scope Code.

Table of contents

  • Flow Overview
  • Step by Step Explanation
    • Create a compose action to define the characters to remove
    • Create a compose action to define the string to have characters removed.
    • Create a Select action to remove any invalid characters from the string.
    • Reconstruct the String
    • Reconstruct the string
  • Non-printable characters
  • Quick Paste Scope Code

Flow Overview

Here is an image of the entire process:

Image of a Power Automate Flow Scope used to remove unwanted characters from a string.

Step by Step Explanation

Here is a step by step explanation of how the flow works.

Create a compose action to define the characters to remove

In the first step, a compose action is defined which contains a JSON array of characters to be removed from the string. If for example you wanted to remove the characters A, B and C, you would define it as:

[ "A", "B", "C" ]

Create a compose action to define the string to have characters removed.

This step is very simple, simply put the string you want to remove characters from in here (you could also use dynamic string content)

Create a Select action to remove any invalid characters from the string.

Most of the work is done within this select action. This is much faster than using an apply to each method as the execution time is near instant. But it does require some explanation. In the from field use the expression:

range(0, length(outputs('String_To_Modify')) )

The range function is useful for all sorts of things, but what we are using it for is to create an array of numbers. Each number represents one character of the string. If the string to have characters removed was:

I love Power Automate!

The range expression would produce the following array:

[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21 ]

The array contains an entry to represent each character in the string.

In the map section of the select action the expression used is:

if
(
  contains(outputs('Unwanted_Characters'), substring(outputs('String_To_Modify'), item(), 1)), 
  '', 
  substring(outputs('String_To_Modify'), item(), 1)
) 

This if expression checks through each character of the string and checks to see if that character is contained within the array of characters to be removed. If it is not in the array to be removed, then it is simply output as is, if it is found, then an empty string is output instead.

Reconstruct the String

The Select action expects it’s input to be an array, which we have provided using the range expression. It also outputs an array. If I wanted to remove the exclamation marks I would specify the Unwanted Characters compose action as:

[ "!" ]

And the select action would produce the following output:

[ "I", " ", "l", "o", "v", "e", " ", "P", "o", "w", "e", "r", " ", "A", "u", "t", "o", "m", "a", "t", "e", "" ]

Note how the final character which was an exclamation mark has become an empty string.

Reconstruct the string

Now that we have an array of characters with all of the unwanted characters removed. We can rebuild the string with a simply compose action containing the expression:

join(body('RemoveUnwanted'), '')

This will convert the array back into a string which we can then use in further actions within the Flow.

Brief overview of how the flow works:

  1. A variable called string is defined which contains the complete string including the invalid characters.
  2. A compose action called RemovalChars is created, which is an array of characters that you’d like to be removed.
  3. An apply to each loop is created using the array RemovalChars as it’s basis.
    1. Inside the loop, a compose action called “removeCharacter” uses the replace function to remove the character in the current iteration of the loop.
      replace(variables('string'), item(), '')
    2. The variable string is updated with the output from the compose action.
  4. Finally, the content of the string with the characters removed is placed inside a compose action, so that you can check if the output is as expected.

Non-printable characters

As I mentioned in the start of the post, it is also possible to remove special characters, that are non-printable. In my example I wanted to remove the SOH (Start of heading) and BEL. I represented these as:

[ "u0001", "u0007" ]

These numbers represent the Unicode values of these characters. Which you can lookup on unicode-table.com.

Quick Paste Scope Code

If you want to implement the above in one of your flows, then you can copy and paste the scope above into your flow. Simply do the following:

  • Copy the code block below into your clipboard.
  • Go into the flow editor and add a new action.
  • Click on My Clipboard.
  • Press CTRL-V.
  • Click on the newly Visible action Remove Unwanted Characters.
  • Edit the characters and string as per your requirements.
{
	"id": "09aad5c1-1777-4c50-91b6-0698-3fc31b57",
	"brandColor": "#8C3900",
	"connectionReferences": {},
	"connectorDisplayName": "Control",
	"icon": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDMyIDMyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPg0KIDxwYXRoIGQ9Im0wIDBoMzJ2MzJoLTMyeiIgZmlsbD0iIzhDMzkwMCIvPg0KIDxwYXRoIGQ9Im04IDEwaDE2djEyaC0xNnptMTUgMTF2LTEwaC0xNHYxMHptLTItOHY2aC0xMHYtNnptLTEgNXYtNGgtOHY0eiIgZmlsbD0iI2ZmZiIvPg0KPC9zdmc+DQo=",
	"isTrigger": false,
	"operationName": "Remove_Unwanted_Characters",
	"operationDefinition": {
		"type": "Scope",
		"actions": {
			"Unwanted_Characters": {
				"type": "Compose",
				"inputs": ["'", "!", "@", "£", "^", "=", ",", "%", "[", "]", ";", "~", "?", "<", ">", "|", "u0001", "u0007"],
				"runAfter": {},
				"description": "List of unwanted characters to remove (Compose Action)"
			},
			"String_To_Modify": {
				"type": "Compose",
				"inputs": "I love Power Automate!",
				"runAfter": {
					"Unwanted_Characters": ["Succeeded"]
				},
				"description": "String from which you want to remove characters (Compose Action)"
			},
			"RemoveUnwanted": {
				"type": "Select",
				"inputs": {
					"from": "@range(0, length(outputs('String_To_Modify')) )",
					"select": "@ifrn(rn  contains(outputs('Unwanted_Characters'), substring(outputs('String_To_Modify'), item(), 1)), rn  '', rn  substring(outputs('String_To_Modify'), item(), 1)rn) "
				},
				"runAfter": {
					"String_To_Modify": ["Succeeded"]
				},
				"description": "Select action to remove unwanted characters"
			},
			"Re-join_Original_String": {
				"type": "Compose",
				"inputs": "@join(body('RemoveUnwanted'), '')",
				"runAfter": {
					"RemoveUnwanted": ["Succeeded"]
				},
				"description": "Reconstruct the string"
			}
		},
		"runAfter": {},
		"description": "https://www.tachytelic.net/2020/10/remove-unwanted-characters-power-automate-flow/ "
	}
}

This is a really fast and efficient solution for removing characters from a string in Power Automate. I Hope it helps you out, and if it does, let me know in the comments!

Filed Under: Power Platform Tagged With: Power Automate

How to screenshot an entire Flow in Power Automate with Google Chrome

October 25, 2020 by Paulie Leave a Comment

If you have a flow in Power Automate flow which is bigger than you can display on screen capturing the complete process can be quite time consuming. Multiple images need to be manually stitched together and it is not an easy process.

Power Automate Screenshot using Google Chrome

This method requires no add-ins, is free and easy to do. It requires a little bit of configuration of Chrome.

Configure Google Chrome

  1. Press CTRL-SHIFT-I to bring up the developer tools pane.
  2. Now press CTRL-SHIFT-M to bring up the device toolbar.
  3. From the Device drop down menu, select edit:
    Image of Google Chrome Device Editor Drop Down
  4. Click Add Custom Device and then use the following settings:
    Image of Chrome Developer tools creating a new emulated device for capturing full screen images of Power Automate Flows
  5. Press Save and close the Emulated Devices Panel.
  6. Close the Chrome developer tools (Press CTRL-SHIFT-I again)

Use Chrome to take full page Screenshots

Now the setup of Chrome is complete. To take the full screenshot of Power Automate using Chrome do the following:

  1. Navigate to the flow you want to capture.
  2. Go back into Developer Tools again (CTRL-SHIFT-I)
  3. Bring up the Device Toolbar again (CTRL-SHIFT-M)
  4. From the drop down device list select the new “Power Automate” device:
    Image of Chrome Device Menu Showing Custom Power Automate Device
    You will now see Chrome Automatically adjust the zoom level to accommodate the new device resolution and your flow may be barely visible!
    Image of Google Chrome showing an entire Power Automate Flow in one screen ready for a screenshot
  5. Now Press CTRL-SHIFT-P and the command window will pop-up.
  6. In the command window type screenshot and select Capture Full Size Screenshot:

Chrome will take a couple of seconds and then download the screenshot to your default downloads folder. You will find a huge image ready for you to crop it down to just the content that you need.

Other Tips for Capturing Images of Flows

When using the process above to share a flow, I also do the following to make it easier for the person receiving the image to comprehend:

  • Include as many comments in the flow as possible.
  • Expand every element of the flow before you take your screenshot so that it is all visible.
  • If you are using expressions, add them to the comments so that others can copy them:
    Image of a Power Automate Expression as a comment on a flow step
  • Use something like Camtasia Snagit to add call-outs to explain certain parts of the flow:
    Image of a screenshot of a Power Automate Flow with an additional callout added from Camtasia SnagIT

Sharing your Power Automate Flow images

If you have used the method above, then you might find that the viewer has a hard time viewing such a large image.

When I post on the Power Automate Community Forums I upload my large flow image, but also upload it to imgbb.com because that has a viewer which makes it easy to view large images.

If you are publishing the images on your own WordPress blog, then the Magic Zoom Plus add-in provides a really good way for visitors to be able to view the entire flow easily. Here is an example of a large flow being displayed with Magic Zoom plus:

Image of an entire Power Automate Flow that uses Parallel Branches to get records from a SharePoint list

Filed Under: Power Platform Tagged With: Power Automate, PowerApps

Add multiple attachments to an approval email with Power Automate

September 25, 2020 by Paulie 40 Comments

Adding multiple attachments to an approval flow in Power Automate is a common requirement. The method is slightly different between the Create an Approval action and the Send an email(V2) action. I will demonstrate both methods in one flow, using a SharePoint list as an example:

First, create the trigger action and initialize two array variables. There are separate arrays for the email action and the approval action:

Image showing first steps of a flow in Power Automate.

Next, use the Get attachments action and provide the same site and list address as before. Use the ID from the trigger action.

Image of Get attachment action in Microsoft Power Automate to pull attachments from a SharePoint list.

Now use the Get attachment Content action and again supply the site and list name. For the ID field use the ID from When an Item is created. Finally, for the File identifier, use the Id from the Get attachments step:

Image of "Get attachment content" action in Power Automate.

This action will now change to be inside an Apply to Each action.

Fill the arrays with the attachment content

The next step is to populate the arrays with the contents of the attachments. Use the append to Append to array variable action. Here is how to build the approvals attachment array.

Image of Power Automate array containing multiple attachments for use in an approval flow.

The code for the approval attachment array is:

{
  "content": {
    "$content-type": "@{body('Get_attachment_content')['$content-type']}",
    "$content": "@{body('Get_attachment_content')['$content']}"
  },
  "Name": "@{items('Build_Attachment_array')?['DisplayName']}"
}

Now populate the email attachment array:

Image of Power Automate array containing multiple email attachments.

The code for the email attachment array is:

{
  "ContentBytes": {
    "$content-type": "@{body('Get_attachment_content')['$content-type']}",
    "$content": "@{body('Get_attachment_content')['$content']}"
  },
  "Name": "@{items('Build_attachment_array')?['DisplayName']}"
}

Notice how the required code is slightly different on line two.

Use the arrays as the attachment content

Now you can simply insert these arrays into the “Create an Approval” or “Send an email(V2)” actions.

Image of an approval flow having multiple attachments added

Here is an image of my entire flow that shows how to send multiple attachments in approvals in a flow from a SharePoint list (click to expand).

Image of a Power Automate Flow showing how to add multiple attachments to an approval

Corrupt attachments

Slightly different solutions to this problem have been discussed in the Power Automate forums but for me, they resulted in corrupted attachments. Adding the correct content type for each of the file attachments fixes the corruption.

I also found that sometimes the file size would increase dramatically.

I’d like to understand why the different array format works for some people and generates corrupt attachments for others.

Filed Under: Office 365, Power Platform Tagged With: Power Automate

Secure the HTTP Request Trigger in Microsoft Power Automate

September 21, 2020 by Paulie 4 Comments

Flows created with the “When a HTTP request is received” trigger can be executed by anyone that knows the URL. This post covers details how to secure the HTTP trigger by using a trigger condition.

I have created a simple two step flow that sends me an email when the flow is triggered:

Image of a simple flow in Power Automate that sends an email after the a HTTP request is received,

Using a condition within the flow to compare a value passed in the HTTP works, but will consume a flow run.

Secure the Trigger with a condition to evaluate if the flow should execute

A better method is to use the Trigger Conditions functionality to test if a flow should execute. Trigger conditions must evaluate to true or false, there is a good introduction to trigger conditions here. I will demonstrate the basic premise with an example.

First, access the trigger settings by clicking on the ellipses of the HTTP Trigger:

Image showing how to access the settings of the HTTP Request trigger in Power Automate

Set a condition for the trigger, if this condition does not evaluate to true, the flow will not run:

I am passing the header “runKey” to the HTTP Request and testing to see if it matches a random string. Here is the code:

equals(triggerOutputs()['headers']?['runKey'],'FSgWPsAEBDP6epQZ')

The advantages of trigger conditions are:

  • It does not execute at all if the condition is not met.
  • The flow executes faster as there is no condition within the flow.
  • Your run history is cleaner (it only shows if the condition was met).
  • The flow is less complicated.

Testing the security with PowerShell

I tested execution of the HTTP trigger in Powershell with the following code:

$flowURI = "https://prod-31.westeurope.logic.azure.com:443/workflows/..."
$messageSubject = "Testing HTTP Security Trigger"
$messageBody = "Execution test from Powershell"
$params = @{"messageSubject"="$messageSubject";"messageBody"="$messageBody"}
$headers = @{'runKey' = 'FSgWPsAEBDP6epQZ'}
Invoke-WebRequest -Uri $flowURI -Method POST -Headers $headers -ContentType "application/json" -Body ($params|ConvertTo-Json)

In my run history I can see all of the data that PowerShell transferred:

{
  "headers": {
    "Expect": "100-continue",
    "Host": "prod-31.westeurope.logic.azure.com",
    "User-Agent": "Mozilla/5.0,(Windows NT; Windows NT 10.0; en-GB),WindowsPowerShell/5.1.18362.752",
    "runKey": "FSgWPsAEBDP6epQZ",
    "Content-Length": "115",
    "Content-Type": "application/json"
  },
  "body": {
    "messageSubject": "Testing HTTP Security Trigger",
    "messageBody": "Execution test from Powershell"
  }
}

Important Note

Make sure your trigger condition includes a question mark for your key value, like this:

equals(triggerOutputs()['headers']?['runKey'],'FSgWPsAEBDP6epQZ')

Not like:
equals(triggerOutputs()['headers']['runKey'],'FSgWPsAEBDP6epQZ')

If you do not include the question mark then anyone that posts to the unique URL will receive the error message back from flow, which will be something like:

equals(triggerOutputs()['headers']['runKey'],'FSgWPsAEBDP6epQZ')' cannot be evaluated because property 'runKey' doesn't exist, available properties are 'Connection,Expect, Host, User-Agent, Content-Length, Content-Type'. 

Which as you can see, contains the key that secures the trigger! So be sure to include the question mark, which will simply make that property return null.

I hope this helps, if you have any clever ideas to add to this method, please let me know!

Filed Under: Power Platform Tagged With: Power Automate

  • « Go to Previous Page
  • Go to page 1
  • Interim pages omitted …
  • Go to page 5
  • Go to page 6
  • Go to page 7
  • Go to page 8
  • Go to page 9
  • Go to page 10
  • Go to Next Page »

Primary Sidebar

Link to my LinkedIn Profile
Buy me a coffee

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 245 other subscribers.

Go to mobile version