Creating a Power Automate approval markdown table, but faster

A common requirement when creating Power Automate approvals, is to display a table of values. The approvals connector allows us to display tabular data in a markdown table format. Appending the line items to our table, however, is generally achieved by using an Apply to Each action which slows down our flow.

In this blog post, we’ll shortly familiarize ourselves with markdown tables within Power Automate. More importantly, we’ll explore how data operations and expressions can help us avoid the known Apply to Each approach. Resulting in less actions, less Power Automate requests and a faster flow run time.

Table of Contents

Approval markdown table

Power Automate approvals allow us to display dynamic tabular data by creating a markdown tableThe markdown table lay-out consists of:

  1. Header rows
				
					| Header 1 | Header 2 |
|----------|----------|

				
			

The pipe character ‘|’ is used to separate each header column. Make sure to add a space between your column values and the pipe characters. The second row consists of the same amount of columns, each column containing the number of hyphens equivalent to the header column length.*

*Note: Including only one hyphen per header column is enough to create the header structure but may result in a less readable markdown format within the flow.

  1. Item rows
				
					| Value 1 H1 | Value 1 H2 |
| Value 2 H1 | Value 2 H2 |
				
			

The item rows contain the same amount of columns as defined by the header, following the same pipe character structure. The table above results in the following approval request table:

The 'Apply to Each' approach

That, however, was a fully hard coded example. Let’s explore a scenario in which we want to visualize dynamic invoice line data.

The most frequent approach to displaying this dynamic markdown table consists out of the following 3 steps:

  1. Initialize a string variable containing the header structure
  1. Fetch your line item data (invoice lines in this example)

 

  1. Loop through the output and append the line item values prefixed by a line break

Optimized approach

Although the approach above certainly gets the job done, it could be improved upon by using expressions and data operations to avoid the redundant Apply to Each. We can leverage the Select data operation and Concat Power Automate expression to achieve the same output.

				
					concat(
    '| ', 
    item()?['lm_invoicelinenumber'], 
    ' | ', 
    item()?['lm_price'], 
    ' | ', 
    item()?['lm_description'], 
    ' |'
)

				
			

The Select will result in a single column array whilst the concat expression takes care of the expected pipe character structure. The action above results in the following output:

The output is very close, yet we still need to map it to our expected string structure with a line feed as a separator. In order to achieve this, we can use the join expression:

				
					join(
    body('Select_-_Map_Table_Body'), 
    decodeUriComponent('%0A')
)
				
			

You can choose to append this to an existing string variable containing the header structure (and a line break). However in a lot of cases this variable is not needed, allowing us to write out the header structure and use this function directly in the Approvals action:

The result

The optimized approach removes the need for a string variable and Apply to Each action, ultimately resulting in less actions, less Power Automate requests and a faster flow run time.

Scroll to Top