<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Matthew Collinge</title>
    <description>The latest articles on DEV Community by Matthew Collinge (@mcombp).</description>
    <link>https://dev.to/mcombp</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1039590%2Fe69df5d8-ef04-4a6f-bf52-299d36350c0f.jpg</url>
      <title>DEV Community: Matthew Collinge</title>
      <link>https://dev.to/mcombp</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mcombp"/>
    <language>en</language>
    <item>
      <title>Cloning Power Automate Flows using a Power Automate Flow</title>
      <dc:creator>Matthew Collinge</dc:creator>
      <pubDate>Wed, 15 Apr 2026 09:25:54 +0000</pubDate>
      <link>https://dev.to/mcombp/cloning-power-automate-flows-using-a-power-automate-flow-5f1g</link>
      <guid>https://dev.to/mcombp/cloning-power-automate-flows-using-a-power-automate-flow-5f1g</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When you build a document trigger on top of SharePoint, you quickly run into a fundamental constraint: &lt;strong&gt;a SharePoint trigger Flow is hardwired to a single Site and Library&lt;/strong&gt;. There is no native way to point one Flow at a dynamic or configurable location — the Site URL and Library GUID are baked into the trigger definition at creation time.&lt;/p&gt;

&lt;p&gt;For a one-off deployment that's fine. But when you're setting up a standardised *&lt;em&gt;Processes &amp;amp; Procedures *&lt;/em&gt; programme across an organisation — where every Team or Business unit gets its own SharePoint Site — you need an approval trigger Flow for &lt;em&gt;each&lt;/em&gt; one. Creating and maintaining these by hand rapidly becomes a maintenance problem: if you fix a bug in one, you have to fix it in all of them.&lt;/p&gt;

&lt;p&gt;This post walks through the solution we built to address that: a &lt;strong&gt;Site-specific Provisioning Flow&lt;/strong&gt; that clones a template approval trigger into a new, Site-specific Flow automatically, using nothing more than Dataverse, Power Automate, and a clean separation between configuration data and Flow logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  The SPO P&amp;amp;P System at a Glance
&lt;/h2&gt;

&lt;p&gt;Before diving into the provisioning Flow, it's worth establishing the wider architecture of the solution.&lt;/p&gt;

&lt;p&gt;Each Processes and &amp;amp; Procedures Library is in a SharePoint Site. Authors upload documents to the Library. When a document is submitted for approval (its approval status set to &lt;em&gt;Pending Approval&lt;/em&gt;), a Power Automate Flow fires, routes the approval through a standard and centralised process via Microsoft Teams, and on Approval publishes the document to its major version and updates the approval metadata. This process can be maintained and changed whenever required and is all done in one place. &lt;/p&gt;

&lt;p&gt;That last Flow, the one watching the Library for changes, is the one we need to clone. It is specific to a Site and Library. The goal of this project was to make provisioning a new P&amp;amp;P Site a self-service operation: an admin fills in a record, runs a Flow from the Model Driven app, and everything wires itself up automatically 😀.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9z5yln8nfnf5a014lwjf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9z5yln8nfnf5a014lwjf.png" alt="Screenshot: SPO P&amp;amp;P Admin Model Driven App — Site Registries list view" width="800" height="635"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Three Flows
&lt;/h2&gt;

&lt;p&gt;The solution contains three Power Automate Flows that work together:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Flow&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SPO PP - Provision Site Flow&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Orchestrator — clones the template and provisions a new Site-specific Flow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SPO PP - Approval Trigger - TEMPLATE&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Template — the Flow definition that gets cloned for each new Site&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Child: PP Approval Standard Process&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Worker — handles the actual approval logic, called by every cloned trigger Flow&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The template and child Flows are permanent, shared fixtures. The cloned approval trigger Flows are ephemeral — one per Site, generated at provisioning time. We can have as many as we want of these, but point them all to the same child Power Automate Flow so we can control the centralised process in one place.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fug16ax4y3wxsmthetufk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fug16ax4y3wxsmthetufk.png" alt="Diagram: Relationship between the three Flows" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Site Registry Table
&lt;/h2&gt;

&lt;p&gt;The hub of the whole system is a custom Dataverse table: &lt;strong&gt;&lt;code&gt;Site_Registry&lt;/code&gt;&lt;/strong&gt; . It stores one row per P&amp;amp;P Site and acts as the source of truth for both provisioning and ongoing operations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom Columns
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Display Name&lt;/th&gt;
&lt;th&gt;Logical Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Required&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Site Name&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Sitename&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Human-readable name; also used as the Primary Name field and in the provisioned Flow's display name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Site URL&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Siteurl&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Full URL of the SharePoint Site (e.g. &lt;code&gt;https://companySite.sharepoint.com/Sites/Finance&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Library GUID&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Libraryguid&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;GUID of the Document Library within the Site — required by the SharePoint trigger&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Flow ID&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Flowid&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Written back by the provision Flow after cloning; links this registry entry to its live approval trigger Flow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Site Registry ID&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Site_Registryid&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;GUID (Primary Key)&lt;/td&gt;
&lt;td&gt;System&lt;/td&gt;
&lt;td&gt;Auto-generated unique identifier for the row&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;Flowid&lt;/code&gt; column starts empty. It is the only field the provisioning process writes — everything else is entered by the admin before triggering provisioning.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Library GUID, Not Library Name?
&lt;/h3&gt;

&lt;p&gt;The SharePoint &lt;code&gt;When a file is created or modified (properties only)&lt;/code&gt; trigger requires a list/Library GUID rather than its display name. GUIDs are stable across renames and don't break if someone tidies up the Library name. Recording the GUID in the Site Registry means provisioning is reliable regardless of what the Library is called. For our template, we can just use a development SharePoint site and a placeholder document Library to keep things simple and standard. I had tried inserting &lt;code&gt;placeholderName&lt;/code&gt; and &lt;code&gt;Library-guid-name&lt;/code&gt; as placeholders, but the Flow struggled to save. &lt;br&gt;
As a possible improvement in the Model Driven App, we could make selection easier by showing them a list of possible document libraries for the selected sites, so the user does not have to go and find the GUID. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9kkprsra65gimikc4ovl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9kkprsra65gimikc4ovl.png" alt="Screenshot: Site Registry form in the Model Driven App — showing all custom columns" width="800" height="250"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  The Approval Trigger Template
&lt;/h2&gt;

&lt;p&gt;The template Flow (&lt;code&gt;SPOPP-ApprovalTrigger-TEMPLATE&lt;/code&gt;) is the blueprint for every Site-specific approval trigger. It lives in the solution and is &lt;strong&gt;never activated&lt;/strong&gt; — it exists solely to be cloned.&lt;/p&gt;

&lt;p&gt;Its trigger is a SharePoint &lt;code&gt;When a file is created or modified (properties only)&lt;/code&gt; action polling every 1 minute, pointed at two placeholders:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Site URL placeholder:&lt;/strong&gt; &lt;code&gt;https://companysite.sharepoint.com/Sites/ITDevelopment&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Library GUID placeholder:&lt;/strong&gt; &lt;code&gt;a3f7c291-84e6-4d1a-b509-2e763dc18f45&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A trigger condition filters the events down to only relevant ones:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ApprovalStatus = 3 (Pending Approval)
AND Editor is NOT the service account  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prevents the Flow from firing on system-generated updates and ensures it only acts when a real user has submitted a document for review.&lt;/p&gt;

&lt;p&gt;When the trigger fires, the Flow calls a single action inside a Try scope: &lt;strong&gt;Run a Child Flow — PP Approval Standard Process&lt;/strong&gt;. It passes the item's ID, Site URL, Library GUID, author claims, full path, approval status, and editor claims to the child Flow, then waits for a response.&lt;/p&gt;

&lt;p&gt;The Catch scope sends an error notification email to the support desk if anything fails.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fixcz0r9400ubje6h654g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fixcz0r9400ubje6h654g.png" alt="Screenshot: Template Flow overview in Power Automate designer" width="191" height="547"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;clientdata&lt;/code&gt; Column — the Key to Cloning
&lt;/h3&gt;

&lt;p&gt;When Power Automate stores a Flow in Dataverse, it uses the &lt;code&gt;workFlows&lt;/code&gt; ("Processes") table. The Flow's entire definition — triggers, actions, connections, expressions — is serialised as JSON and stored in a column called &lt;strong&gt;&lt;code&gt;clientdata&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is the column we read from the template and write to the new Flow. The string-replace approach works because the placeholders (the hardcoded Site URL and Library GUID) are literal strings embedded in that JSON. Swapping them out produces a valid, Site-specific Flow definition ready to run.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F47iz52xwmvr78y88siaz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F47iz52xwmvr78y88siaz.png" alt="Screenshot: workFlows table row for the template, showing clientdata column in Dataverse" width="323" height="614"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Provision Site Flow — Step by Step
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;SPO PP - Provision Site Flow&lt;/strong&gt; is triggered from the Model Driven App by an admin selecting a Site Registry row and running the Flow from the command bar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcklzky6h792c3mq1qsl2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcklzky6h792c3mq1qsl2.png" alt="Trigger the Flow for a Site and Library" width="800" height="281"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Trigger: Record Selected on Site_registries
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The trigger uses &lt;code&gt;splitOn&lt;/code&gt;, meaning if multiple rows are selected the Flow runs once per row — each Site is provisioned independently.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F94lcjkdw0i599smlgzca.png" alt="Screenshot: Provision Site Flow — full overview in Power Automate designer" width="780" height="1572"&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1 — Initialise Variable (&lt;code&gt;varClientData&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Before entering the Try scope, a string variable &lt;code&gt;varClientData&lt;/code&gt; is initialised empty. This will hold the cloned Flow definition once the placeholders have been replaced.&lt;/p&gt;

&lt;p&gt;This is declared outside the Try scope deliberately: it needs to be initialised before any branching logic, and the scoped Try/Catch pattern requires variables to be declared at the root level to be accessible in both branches.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 2 — Get Site Registry Row (&lt;code&gt;Get a row by ID — Site Registry from Trigger&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The trigger provides the &lt;code&gt;Site_Registryid&lt;/code&gt; from the selected record, but only the ID and Site name are included in the trigger payload. We need the full row — specifically the &lt;code&gt;Siteurl&lt;/code&gt; and &lt;code&gt;Libraryguid&lt;/code&gt; — so the first action inside the Try scope fetches it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Entity: Site_registries
Record ID: triggerBody()?['entity']?['Site_Registryid']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output of this action is referenced throughout the rest of the Flow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdkmovi5xev2sb892j9hg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdkmovi5xev2sb892j9hg.png" alt="Screenshot: Get a row by ID action — Site Registry" width="800" height="359"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 3 — Retrieve the Template Flow Definition (&lt;code&gt;List rows — Processes&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Next, the Flow queries the Dataverse &lt;code&gt;workFlows&lt;/code&gt; ("Processes") table to retrieve the template's &lt;code&gt;clientdata&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;Entity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;workFlows&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;clientdata&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;workFlowid&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;workFlowid&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt; &lt;span class="s1"&gt;'05a1a909-5b33-f111-88b3-6045bddd6b33'&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The template's workFlow ID is hardcoded here — it is a known, stable fixture in the solution. Using &lt;code&gt;$top: 1&lt;/code&gt; ensures a single result is returned efficiently.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;clientdata&lt;/code&gt; that comes back is the full JSON definition of the template Flow, including the hardcoded Site URL and Library GUID placeholders.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fafdgc0inkot5fu7vyjlc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fafdgc0inkot5fu7vyjlc.png" alt="Screenshot: List rows action — retrieving template clientdata from workFlows table" width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 4 — Inject Real Values (&lt;code&gt;Set variable — varClientData&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;This is the core of the cloning mechanism. A double-nested &lt;code&gt;replace()&lt;/code&gt; expression swaps out both placeholders in a single operation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;List_rows_-_Processes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)?[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;body/value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])?[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;clientdata&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://companySite.sharepoint.com/Sites/ITDevelopment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Get_a_row_by_ID_-_Site_Registry_from_Trigger&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)?[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;body/Siteurl&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a3f7c291-84e6-4d1a-b509-2e763dc18f45&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nf"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Get_a_row_by_ID_-_Site_Registry_from_Trigger&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)?[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;body/Libraryguid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The inner &lt;code&gt;replace&lt;/code&gt; substitutes the Site URL. The outer &lt;code&gt;replace&lt;/code&gt; then takes that result and substitutes the Library GUID. The outcome is stored in &lt;code&gt;varClientData&lt;/code&gt;: a complete, valid Flow definition targeting the new Site's Library.&lt;/p&gt;

&lt;p&gt;No parsing, no schema manipulation — just string replacement in JSON.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F20oquqth4p8f7m8upm94.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F20oquqth4p8f7m8upm94.png" alt="Screenshot: Set variable action — showing the double replace expression" width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 5 — Create the New Flow (&lt;code&gt;Add a new row — Processes&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The modified definition is now written back to the &lt;code&gt;workFlows&lt;/code&gt; ("Processes") table as a new row, creating the cloned Flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Entity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;workFlows&lt;/span&gt;
&lt;span class="na"&gt;item/name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;     &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SPO&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;PP&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Approval&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Trigger&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{Sitename}"&lt;/span&gt;
&lt;span class="na"&gt;item/category&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5        (Modern Flow)&lt;/span&gt;
&lt;span class="na"&gt;item/type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;     &lt;span class="s"&gt;1        (Definition)&lt;/span&gt;
&lt;span class="na"&gt;item/primaryentity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;none"&lt;/span&gt;
&lt;span class="na"&gt;item/xaml&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;     &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;     &lt;span class="s"&gt;(required field, but not used for modern Flows)&lt;/span&gt;
&lt;span class="na"&gt;item/clientdata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="s"&gt;variables('varClientData')&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;category: 5&lt;/code&gt; value identifies this as a cloud Flow. The &lt;code&gt;xaml&lt;/code&gt; field is a legacy artefact required by the API but irrelevant for modern Flows apparently — a single space " " keeps it happy.&lt;/p&gt;

&lt;p&gt;The response from this action includes the new Flow's &lt;code&gt;workFlowid&lt;/code&gt;, which is carried forward to the next two steps.&lt;/p&gt;

&lt;p&gt;The new Flow is created in a &lt;strong&gt;disabled/draft state&lt;/strong&gt;. It will not run until it is manually opened, saved (to authenticate connections), and turned on. This is by design — connections must be authorised by a human with the appropriate permissions, not ideal for automations, but we can live with it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmx3cztsc3m03jwjs00gh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmx3cztsc3m03jwjs00gh.png" alt="Screenshot: Add a new row action — creating the cloned workFlow in Dataverse" width="652" height="534"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 6 — Add to Solution (&lt;code&gt;Perform an unbound action — Add to Solution&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;With the Flow created, it exists in Dataverse but is not yet part of any solution. This step calls the &lt;code&gt;AddSolutionComponent&lt;/code&gt; unbound action to register it under the &lt;code&gt;SPOPPSiteConfig&lt;/code&gt; solution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;ComponentId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;         &lt;span class="s"&gt;(new Flow's workFlowid)&lt;/span&gt;
&lt;span class="na"&gt;ComponentType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;       &lt;span class="s"&gt;29    (Cloud Flow)&lt;/span&gt;
&lt;span class="na"&gt;SolutionUniqueName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="s"&gt;SPOPPSiteConfig&lt;/span&gt;
&lt;span class="na"&gt;AddRequiredComponents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="na"&gt;DoNotIncludeSubcomponents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Component type &lt;code&gt;29&lt;/code&gt; maps to cloud Flows in the Dataverse component type enumeration. By adding it to the solution, the provisioned Flow becomes visible in the main solution and is logically grouped with the rest of the P&amp;amp;P components - making management cleaner.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff3owyxvtdn9ygi2wpnaz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff3owyxvtdn9ygi2wpnaz.png" alt="Screenshot: Perform unbound action — AddSolutionComponent" width="679" height="794"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 7 — Write the Flow ID Back to Site Registry (&lt;code&gt;Update a row — Site Registry&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The final Dataverse write closes the loop: the new Flow's ID is written back to the Site Registry record that triggered this whole process. This is for record keeping maintenance mainly. As an added extra you could concatenate the full URL for the Flow if you wanted to.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Entity: Site_registries
Record ID: triggerBody()?['entity']['Site_Registryid']
Flowid: outputs('Add_a_new_row_-_Processes')?['body/workFlowid']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this step, the Site Registry row has a &lt;code&gt;Flow ID&lt;/code&gt; value. This serves as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A human-readable audit trail (the admin can see which Flow was provisioned for which Site)&lt;/li&gt;
&lt;li&gt;A navigation link back to the provisioned Flow&lt;/li&gt;
&lt;li&gt;A signal that provisioning has completed for this Site&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fea3yr72bn16w4v7k1xzo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fea3yr72bn16w4v7k1xzo.png" alt="Screenshot: Update a row action — writing the Flow ID back to Site Registry" width="669" height="634"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 8 — Notify via Teams Adaptive Card (&lt;code&gt;Post card — Turn Flow On&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The final action sends an Adaptive Card to the user who triggered the Flow via Teams (the &lt;code&gt;triggerOutputs()?['headers']['x-ms-user-email']&lt;/code&gt; header on the trigger response identifies them):&lt;/p&gt;

&lt;p&gt;![Screenshot: Adaptive Card in Teams — SPO P&amp;amp;P Flow Provisioning notification]&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fww990b6ipx6dsfu2p5er.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fww990b6ipx6dsfu2p5er.png" alt=" " width="660" height="582"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As mentioned earlier, I tried to use some Power Automate actions to Turn On the Flow, But couldn't find any that worked, so this is our only workaround and a quick step for the end user, although not ideal. If you know a way to easily do this, please leave a comment. &lt;/p&gt;

&lt;p&gt;The card surfaces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Completed automatically:&lt;/strong&gt; a green checklist of everything the Flow did&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manual activation required:&lt;/strong&gt; a warning block explaining the three steps the admin must take&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open Flow button:&lt;/strong&gt; a direct link to the new Flow in the Power Automate portal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The three manual steps are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the Flow via the link in the card&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Turn on&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This manual step is a conscious design decision. Power Automate does not permit programmatic activation of a Flow that has connection references requiring user consent — the connections must be authorised interactively. The card makes this as frictionless as possible.&lt;/p&gt;


&lt;h3&gt;
  
  
  Error Handling — Scope Catch
&lt;/h3&gt;

&lt;p&gt;If any action inside the Try scope fails, times out, or is skipped, the Catch scope runs. It:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Filters &lt;code&gt;result('Scope_-_Try')&lt;/code&gt; to find the actions that failed, timed out, or were skipped&lt;/li&gt;
&lt;li&gt;Posts a plain Teams message to the triggering user with a direct link to the failed Flow run
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❌ Provision Site Flow Failed
Site: {Sitename}
View Flow Run: [link]
Once resolved, re-trigger provisioning from the SPO P&amp;amp;P Administration app.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The admin can inspect the failed run, resolve the root cause, and re-trigger provisioning from the app. Because the Site Registry record is only updated in Step 7 (after everything else succeeds), a partial failure leaves the record in its original state — &lt;code&gt;Flow ID&lt;/code&gt; will be blank, signalling that provisioning is incomplete and can safely be re-run.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffuet0dyeb11dxfm5f97q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffuet0dyeb11dxfm5f97q.png" alt="Screenshot: Catch scope — Teams error message action" width="671" height="566"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  The Child Approval Flow
&lt;/h2&gt;

&lt;p&gt;This is the central Flow that the cloned trigger Flows hand off to. The team can iterate on this particular Flow / Process as much as is needed without having to worry about duplicate actions, etc., as the Process can be amended when needed. &lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Child: PP Approval Standard Process&lt;/strong&gt; is a manually-triggered child Flow that accepts seven parameters from every approval trigger:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ItemID&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;SharePoint list item ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SiteURL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;URL of the Site (passed through, not hardcoded)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ListGUID&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Library GUID (passed through)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AuthorClaims&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Claims string of the document author&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;FullPath&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Server-relative path of the document&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ApprovalStatus&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Numeric approval status value from SharePoint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Editor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Claims string of the last editor&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;On receipt, it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Checks the item isn't already approved (terminates gracefully if it is)&lt;/li&gt;
&lt;li&gt;Builds the server-relative URL via a &lt;code&gt;Compose&lt;/code&gt; expression&lt;/li&gt;
&lt;li&gt;Calls the SharePoint REST API to &lt;strong&gt;publish&lt;/strong&gt; the document (&lt;code&gt;_api/web/GetFileByServerRelativeUrl(...)/Publish&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Reads the updated file properties back from SharePoint&lt;/li&gt;
&lt;li&gt;Calls the SharePoint REST API to &lt;strong&gt;set the approval status&lt;/strong&gt;  to Approved (&lt;code&gt;OData__ModerationStatus: 0&lt;/code&gt;) and records the approval date and updates any other column metadata required.&lt;/li&gt;
&lt;li&gt;Posts a Teams message to the document author confirming approval and the new version number&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Because the Site URL and Library GUID are passed in as parameters (not hardcoded), this single child Flow serves every cloned approval trigger across the entire organisation.&lt;/p&gt;


&lt;h2&gt;
  
  
  How It All Fits Together
&lt;/h2&gt;

&lt;p&gt;Here's the end-to-end lifecycle for adding a new P&amp;amp;P Site to the system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Admin creates a SharePoint Online Site and Document Library
2. Admin notes the Library GUID (from the SharePoint URL or list settings)
3. Admin opens the SPO P&amp;amp;P Administration app
4. Admin creates a new Site Registry row:
      Site Name:    "Finance"
      Site URL:     https://companysite.sharepoint.com/Sites/Finance
      Library GUID: [GUID from SharePoint]
5. Admin selects the row and runs "SPO PP - Provision Site Flow" from the command bar
6. Flow runs (~10 seconds):
      - Reads Site Registry row
      - Fetches template clientdata from Dataverse
      - Replaces Site URL and Library GUID placeholders
      - Creates new Flow: "SPO PP - Approval Trigger - Finance"
      - Adds Flow to SPOPPSiteConfig solution
      - Writes Flow ID back to Site Registry
      - Sends Adaptive Card to The user that initiated the process via Teams
7. Admin clicks "Open Flow" in the Teams card
8. Admin saves and turns on the Flow
9. Finance P&amp;amp;P Site is live — approval triggers are active
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From step 4 to a live Flow takes under a minute of admin time, with no Flow editing or cloning required.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Design Decisions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why string replacement instead of a proper API?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Power Automate does not expose a public API for cloning Flows. The &lt;code&gt;clientdata&lt;/code&gt; approach is the only programmatic path available without leaving the Power Platform. It is undocumented but stable — Microsoft's own import/export tooling uses the same &lt;code&gt;workFlows&lt;/code&gt; ("Processes")("Processes") table and &lt;code&gt;clientdata&lt;/code&gt; column.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why store Library GUID and not Library Name?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
GUIDs are immutable. Library names can be changed by Site owners without affecting the trigger. Storing the GUID avoids a class of hard-to-diagnose breakages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why manual activation?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Connection references in Power Automate require user consent. There is no API to activate a Flow with unauthenticated connection references. The Adaptive Card makes the manual step as lightweight as possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why add the Flow to the solution?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
It keeps all provisioned Flows grouped under &lt;code&gt;SPOPPSiteConfig&lt;/code&gt; in the environment. This makes bulk management, export, and environment promotion practical — rather than having dozens of orphaned Flows scattered across the default solution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Environment Constraint: Unmanaged Required&lt;/strong&gt;&lt;br&gt;
⚠️ One big constraint worth flagging: the Environment where the provisioned flows are created must be &lt;strong&gt;unmanaged&lt;/strong&gt;.&lt;br&gt;
The cloning mechanism writes new rows directly to the workflows table at runtime. Those flows are unmanaged artefacts — they exist outside the solution package and outside the ALM pipeline. That is intentional; they are site-specific, runtime-generated, and self-service by design.&lt;br&gt;
But it means a managed-solution environment is incompatible with this pattern. The provisioning Flow will run fine as a managed component, but the governance model of a managed environment conflicts with generating unmanaged Flow records inside it.&lt;/p&gt;

&lt;p&gt;The default environment is the most common candidate simply because it is typically unmanaged — but the constraint is unmanaged vs. managed, not default vs. non-default. Any unmanaged environment works.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The project is delivered a self-service Site provisioning capability built on a single mechanism: reading a Flow's &lt;code&gt;clientdata&lt;/code&gt; from Dataverse, replacing two placeholder strings, and writing the result back as a new workFlow row. The Site Registry table is the operational hub — it drives provisioning and records the outcome. The template Flow is the blueprint — stable, never activated, just there to be cloned.&lt;/p&gt;

&lt;p&gt;The result is a system where adding a new P&amp;amp;P Site is a data entry task, not a development task.&lt;/p&gt;

</description>
      <category>powerautomate</category>
      <category>sharepoint</category>
      <category>powerplatform</category>
      <category>microsoftdataverse</category>
    </item>
    <item>
      <title>Generate a Dataverse ERD for Azure Dev Ops Wiki</title>
      <dc:creator>Matthew Collinge</dc:creator>
      <pubDate>Sun, 16 Nov 2025 09:44:04 +0000</pubDate>
      <link>https://dev.to/mcombp/generate-a-dataverse-erd-for-azure-dev-ops-wiki-3m4</link>
      <guid>https://dev.to/mcombp/generate-a-dataverse-erd-for-azure-dev-ops-wiki-3m4</guid>
      <description>&lt;p&gt;Nobody likes manually writing and updating Documentation. ERDs (Entity Relationship Diagrams) provide a really helpful overview of what your database relationships look like.&lt;/p&gt;

&lt;p&gt;Context: We are using Azure DevOps (ADO) to manage our CI/CD Pipelines using the &lt;a href="https://learn.microsoft.com/en-us/power-platform/alm/devops-build-tools" rel="noopener noreferrer"&gt;Power Platform Tools&lt;/a&gt; and therefore the Solutions are unpacked and stored in the Repository (there may be multiple Solutions inside of a Project).&lt;/p&gt;

&lt;p&gt;The idea: working with Power Platform solutions stored in ADO, it would be great to visualise complex entity relationships right inside ADO. Visualizing these relationships can make solution design and troubleshooting much easier, it certainly helps me.&lt;/p&gt;

&lt;p&gt;In this quick post, we'll use a short prompt using &lt;a href="https://code.visualstudio.com/docs/copilot/chat/getting-started-chat" rel="noopener noreferrer"&gt;Chat in VS Code&lt;/a&gt; to get an AI Agent to generate a &lt;strong&gt;Mermaid ERD&lt;/strong&gt; from our Dataverse solution files and then we can copy it and publish it to our ADO Wiki. &lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Why This Matters
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Better Documentation&lt;/strong&gt;: ERDs help us understand entity relationships at a glance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native Rendering&lt;/strong&gt;: Mermaid diagrams render natively in ADO Wiki.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automation Ready&lt;/strong&gt;: This process could be adapted for CI/CD pipelines later. For this we can implement &lt;a href="https://mightora.io/tools/cicd/upload-md-to-wiki/" rel="noopener noreferrer"&gt;Ian Tweedie - Upload Markdown to Wiki
&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 1: Clone the Repository in VS Code&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;In &lt;strong&gt;Azure DevOps&lt;/strong&gt;, go to &lt;strong&gt;Repos → Clone → IDE&lt;/strong&gt;.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyjqxs72pved3ub22yx0d.png" alt="azure-repo" width="800" height="320"&gt;
---&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Clone in VS Code&lt;/strong&gt;.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbddkwz0emux4yl82dd52.png" alt="Clone in VS Code" width="427" height="317"&gt;
---&lt;/li&gt;
&lt;li&gt;Choose a local folder where the repo will be stored.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Step 2: Locate a Relationships File&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;In VS Code, navigate to the Power Platform solution folder inside the repo.&lt;/li&gt;
&lt;li&gt;Go to: &lt;strong&gt;Other → Relationships.xml&lt;/strong&gt;
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsrw32z50uop8b6tus0ty.png" alt="Relationships XML" width="568" height="695"&gt;
---
(if there is more than one Relationships.xml file, you may need to repeat these steps)&lt;/li&gt;
&lt;li&gt;Open &lt;strong&gt;&lt;code&gt;Relationships.xml&lt;/code&gt;&lt;/strong&gt; in VS Code.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Step 3: Use AI to Generate the ERD&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;strong&gt;Chat&lt;/strong&gt; in VS Code with &lt;code&gt;Relationships.xml&lt;/code&gt; in file context.&lt;/li&gt;
&lt;li&gt;Paste this prompt:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Please scan this file and identify all Dataverse-related entities and their relationships. Focus on extracting entity names, attributes, and how they relate to each other (e.g. one-to-many, many-to-one, many-to-many). Then, generate a Mermaid entity-relationship diagram (ERD) that includes cardinality for each relationship.

 Format the output as a Markdown file containing the Mermaid ERD code block. Ensure the diagram is readable and reflects the structure of the Dataverse schema as accurately as possible.

If any assumptions are made due to missing or ambiguous information, please list them at the end of the Markdown file.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Step 4: Copy the Mermaid Diagram&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;From the AI response, copy everything starting from:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;erDiagram&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;erDiagram

    CUSTOMER ||--o{ ORDER : "1:N"
    CUSTOMER ||--o{ ADDRESS : "1:N"

    ORDER ||--o{ ORDER_LINE : "1:N"
    ORDER_LINE }o--|| PRODUCT : "N:1"

    PRODUCT ||--o{ PRODUCT_CATEGORY : "N:1"

    PRODUCT ||--o{ INVENTORY : "1:N"
    INVENTORY ||--|| WAREHOUSE : "1:1"

    PAYMENT ||--|| ORDER : "1:1"
    SHIPMENT ||--o{ ORDER : "1:N"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example Mermaid&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Step 5: Publish to ADO Wiki&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;In &lt;strong&gt;Azure DevOps&lt;/strong&gt;, go to &lt;strong&gt;Overview → Wiki&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;New Page&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Paste the Markdown (including the Mermaid block) into the &lt;strong&gt;left-hand pane&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Give the page a title.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Save&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi11p2i6jozaiy4bgvutm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi11p2i6jozaiy4bgvutm.png" alt="Dataverse Mermaid" width="800" height="191"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  ✅ Pro Tip
&lt;/h3&gt;

&lt;p&gt;Mermaid diagrams render natively in ADO Wiki, so your ERD will be interactive and easy to read 😜.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Possible Next Steps&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Automate this process using a pipeline - this is going to require me to learn some fancy PowerShell Scripts to parse the XML 😵‍💫.&lt;/li&gt;
&lt;li&gt;This could allow Automatic Documentation as part of a Release, keeping the ERD up to date.&lt;/li&gt;
&lt;li&gt;Add entity attributes for deeper insights.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>powerplatform</category>
      <category>devops</category>
      <category>documentation</category>
      <category>ai</category>
    </item>
    <item>
      <title>Extract table data from Documents using Azure AI Document Intelligence</title>
      <dc:creator>Matthew Collinge</dc:creator>
      <pubDate>Wed, 16 Oct 2024 15:30:29 +0000</pubDate>
      <link>https://dev.to/mcombp/extract-table-data-from-documents-using-azure-ai-document-intelligence-1maa</link>
      <guid>https://dev.to/mcombp/extract-table-data-from-documents-using-azure-ai-document-intelligence-1maa</guid>
      <description>&lt;h2&gt;
  
  
  Extract table data from Documents Using Azure AI Document Intelligence Layout Model with Power Automate
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx6so0e1ifuegxe8n025f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx6so0e1ifuegxe8n025f.png" alt="Document Intelligence Studio" width="800" height="379"&gt;&lt;/a&gt;&lt;br&gt;
Azure AI Document Intelligence is a cloud-based service that allows you to build intelligent document processing solutions. It uses machine learning to extract text, tables, and key-value pairs from documents, providing structured data for easy use.&lt;/p&gt;

&lt;p&gt;In this post, I’m going to go through how to send a PDF document using an Azure AI Document Intelligence REST API request and return the text and table information using the Layout model. I’ll go through some of my processes for transforming the received JSON output into an array that can be used to create rows in a Dataverse table, all within Power Automate.&lt;/p&gt;

&lt;p&gt;Power Automate isn’t Power Query, so I will use some techniques to get it to try and replicate some of the filtering, cleansing, and sorting capabilities of Power Query. Some of the filtering can be quite specific to the documents you have, so I will start quite general and then cover some techniques to cleanse the data by type alongside.&lt;/p&gt;
&lt;h1&gt;
  
  
  Choosing a Model
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;I would highly recommend that you use the &lt;a href="https://documentintelligence.ai.azure.com/studio" rel="noopener noreferrer"&gt;Azure AI Document Intelligence Studio&lt;/a&gt; to find the most suitable model for your documents. You can try out models in the studio with your own documents. I did this and was confused about how you can actually use the model. The studio provides code examples, but you are kind of left to it from then on. When I’d found the &lt;a href="https://learn.microsoft.com/en-us/azure/ai-services/document-intelligence/how-to-guides/use-sdk-rest-api?view=doc-intel-3.1.0&amp;amp;tabs=windows&amp;amp;pivots=programming-language-rest-api" rel="noopener noreferrer"&gt;REST API Documentation &lt;/a&gt;I certainly felt more comfortable, as I can use this with Power Automate!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Test multiple documents as you may discover inconsistencies in the results. To get around these, you can adjust some of the actions and expressions in your Flow to deal with them.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  My Example
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv7a1nnasppsumcncxboc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv7a1nnasppsumcncxboc.png" alt="Example PDF Preview" width="724" height="363"&gt;&lt;/a&gt;&lt;br&gt;
I have created a simple document that includes one table and I like sausages, but in the real world, I have dealt with documents of all shapes and sizes. For example, where the tables start on a different page (we can append &lt;code&gt;&amp;amp;pages=&lt;/code&gt; to the URI to extract a specific page 🙂).&lt;/p&gt;
&lt;h1&gt;
  
  
  Passing the Document to Azure AI Document Intelligence
&lt;/h1&gt;

&lt;p&gt;I have to start by mentioning that I could not have done this first part without the help of this YouTube video from the excellent &lt;a href="https://damobird365.com/" rel="noopener noreferrer"&gt;Damien Bird&lt;/a&gt; on &lt;a href="https://youtu.be/fLHmEwcg8Jo?si=whD4IAvsr-oojTm5" rel="noopener noreferrer"&gt;Power Automate Invoice Processing Tutorial AI Builder and Azure&lt;/a&gt;. Here Damien explores the AI Builder option and compares the costs, introduces the Document Intelligence Service on Azure, polling the services, reviewing the Response, and selecting data from the response.&lt;/p&gt;

&lt;p&gt;We’re basically going to do the same, but select the &lt;strong&gt;Layout Model API Version 2023-07-31&lt;/strong&gt; from Azure AI Document Intelligence.&lt;/p&gt;
&lt;h1&gt;
  
  
  Azure Services
&lt;/h1&gt;

&lt;p&gt;Before we start building our Flow, we will need some Azure Services set up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resource Group&lt;/li&gt;
&lt;li&gt;Azure AI Services &amp;gt; Document Intelligence (Select the F0 Pricing tier for up to 500 documents per month for free, much better than AI Builder).&lt;/li&gt;
&lt;li&gt;Azure Key Vault Secret&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Make sure to copy the Endpoint, as we will need this in our Flow. To keep things secure keep your key inside Azure Key Vault. I can recommend following this video &lt;a href="https://www.youtube.com/watch?v=HA1BMJJCDF0" rel="noopener noreferrer"&gt;Power Automate +Azure Key Vault - get key and secret and pass to Flow&lt;/a&gt; from Sean Astrakhan on how to do this.&lt;/p&gt;
&lt;h1&gt;
  
  
  Flow Structure
&lt;/h1&gt;

&lt;p&gt;Ok, let’s get on with the Flow!&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faz8jn4un0gb38m0q3wq3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faz8jn4un0gb38m0q3wq3.png" alt="Flow Overview" width="488" height="1504"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Manual Trigger
&lt;/h3&gt;

&lt;p&gt;Start with a manual trigger with a File Content Input. This will be used to bring the PDF Document into the Flow.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvmkb5imws0u18s39zag9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvmkb5imws0u18s39zag9.png" alt="Manual Trigger" width="785" height="170"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and then set up some variables....&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Initialize variable – Status&lt;/strong&gt; - We will need to use this String Variable to set the outcome of the second HTTP request status.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Initialize variable – Metadata&lt;/strong&gt; - We will use this Object Variable to contextualise and reference the Document that we have extracted from.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Initialize variable - ParsedCellsArray&lt;/strong&gt; - We will use this Array Variable to loop through the table cells.&lt;/p&gt;
&lt;h3&gt;
  
  
  Azure Key Vault Get secret
&lt;/h3&gt;

&lt;p&gt;Enter the name of your Azure Key Vault secret to return its value. In settings, enable ‘Secure inputs’ and ‘Secure outputs’ to ensure the secret is hidden.&lt;/p&gt;
&lt;h3&gt;
  
  
  HTTP Request
&lt;/h3&gt;

&lt;p&gt;This is where the fun starts. Add an HTTP Action.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;URL&lt;/strong&gt;: &lt;em&gt;{Your Azure AI Service Endpoint}/formrecognizer/documentModels/prebuilt-layout:analyze?api-version=2023-07-31&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There’s some &lt;a href="https://learn.microsoft.com/en-us/azure/ai-services/document-intelligence/how-to-guides/use-sdk-rest-api?view=doc-intel-3.1.0&amp;amp;tabs=windows&amp;amp;pivots=programming-language-rest-api" rel="noopener noreferrer"&gt;more information here&lt;/a&gt; on versions and models. Here I have chosen the Model: &lt;strong&gt;prebuilt-layout&lt;/strong&gt; and the api-version of &lt;strong&gt;2023-07-31&lt;/strong&gt; – which is GA at the time of writing. It’s worth noting that I struggled to use the newer preview models due to my Azure AI services location being UK South (we have to wait for the new toys!).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Method&lt;/em&gt;: &lt;em&gt;POST&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Headers&lt;/em&gt;: &lt;em&gt;Ocp-Apim-Subscription-Key: {Azure Key Vault Secret Value}&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Body&lt;/strong&gt;:&lt;br&gt;
&lt;code&gt;{"base64Source": triggerBody()?['file']?'contentBytes']}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For the body, we are passing the '‘File content contentBytes’' value from the Manual Trigger. This converts the file into base64 format so that it can be uploaded as part of the request.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmyc252s5cud511kvmmvq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmyc252s5cud511kvmmvq.png" alt="HTTP Request" width="560" height="454"&gt;&lt;/a&gt;&lt;br&gt;
Now we have a way to send the Document, we then need a way to wait until it has been processed.&lt;/p&gt;
&lt;h3&gt;
  
  
  Do Until
&lt;/h3&gt;

&lt;p&gt;Create a Do Until polling loop using &lt;strong&gt;Loop Until&lt;/strong&gt; so that we can wait for the service to process the document and send back a response.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj98iyfkbhr0qe1ciz0fd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj98iyfkbhr0qe1ciz0fd.png" alt="Do until" width="558" height="427"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Variable Status is equal to “succeeded”, with a Count of 5 to limit the number of retries, with a 1 hour timeout.
&lt;/h3&gt;

&lt;p&gt;Within the Do Until we need:&lt;/p&gt;
&lt;h3&gt;
  
  
  Delay: 10 Second Delay
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;HTTP_1:&lt;/strong&gt; This HTTP action uses the ‘Operation-Location’ Header from the first HTTP action to check if the service has completed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;URL:&lt;/strong&gt; &lt;em&gt;outputs('HTTP')?['headers/Operation-Location']&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Method&lt;/strong&gt;: &lt;em&gt;GET&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Headers&lt;/strong&gt;: &lt;em&gt;Ocp-Apim-Subscription-Key: {Azure Key Vault Secret Value}&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6msc60366cne584brks.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6msc60366cne584brks.png" alt="HTTP_1" width="553" height="297"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Set the Status Variable:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Value&lt;/strong&gt;: &lt;em&gt;body('HTTP_1')?['status']&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  After the Do Until:
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;body('HTTP_1')?['analyzeResult']&lt;/code&gt;&lt;br&gt;
Now we have a response from the Azure AI Document Intelligence Model, we can start to deal with the JSON that we get back. As Damien Bird mentions, it is helpful to visualise this output using &lt;a href="https://codebeautify.org/jsonviewer" rel="noopener noreferrer"&gt;https://codebeautify.org/jsonviewer&lt;/a&gt; to give yourself an idea of the output structure and how to reference and extract the data in your Flow.&lt;/p&gt;
&lt;h3&gt;
  
  
  Extract the Document Information
&lt;/h3&gt;

&lt;p&gt;I have decided that it is important to extract some of the headers from the document as well as the table data in order to give context to the information.&lt;/p&gt;
&lt;h3&gt;
  
  
  Parse JSON – Paragraphs
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqaqjstqbld0htmvujkws.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqaqjstqbld0htmvujkws.png" alt="Layout Model Paragraphs" width="800" height="407"&gt;&lt;/a&gt;&lt;br&gt;
As the Layout model gives us the text in the &lt;code&gt;body('HTTP_1')?['analyzeResult/paragraphs']&lt;/code&gt; we can just select that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Content&lt;/strong&gt;: &lt;em&gt;body('HTTP_1')?['analyzeResult/paragraphs']&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Schema&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"array"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we only need the Content properties, I have shortened the Schema so that only the &lt;strong&gt;['content']&lt;/strong&gt; is returned in the output.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu2f70yc9qbizpbr3aqvw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu2f70yc9qbizpbr3aqvw.png" alt="Parse JSON - Paragraphs" width="548" height="525"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Set variable - Metadata Object
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Name&lt;/strong&gt;: &lt;em&gt;Metadata&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Value&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Report_Name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@{body('Parse_JSON_-_Paragraphs')['content']}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Issue_No"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@{first(split(&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;body('Parse_JSON_-_Paragraphs')['content'],'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;'))}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Issue_Date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@{last(split(&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s2"&gt;body('Parse_JSON_-_Paragraphs')['content'],'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;'))}"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we use the index of the &lt;strong&gt;['content']&lt;/strong&gt; property to extract the values that we want. This is where it is helpful to preview the output using &lt;a href="https://codebeautify.org/jsonviewer" rel="noopener noreferrer"&gt;https://codebeautify.org/jsonviewer&lt;/a&gt; so that you can work out the index beforehand. In my example, the Report Name is the 2nd value &lt;strong&gt;[1]&lt;/strong&gt; and then I have used a &lt;code&gt;Split()&lt;/code&gt; expression on the &lt;strong&gt;"|"&lt;/strong&gt; to allow me to capture the &lt;code&gt;first()&lt;/code&gt; and &lt;code&gt;last()&lt;/code&gt; values either side of the &lt;strong&gt;“|”&lt;/strong&gt; giving us the &lt;strong&gt;Issue_No&lt;/strong&gt; and &lt;strong&gt;Issue_Date&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is just an example, you will want to adjust the structure of your output to meet your own needs. We have captured this as an object here so that we can then align it alongside the table rows later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extracting the table rows
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6h98l1aharcj2kr8bec3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6h98l1aharcj2kr8bec3.png" alt="Layout Tables" width="800" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Parse JSON
&lt;/h3&gt;

&lt;p&gt;We can now use a Parse JSON to extract all the Table data by selecting the child property &lt;code&gt;/tables&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvrtv3a7thcdsfcxiidph.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvrtv3a7thcdsfcxiidph.png" alt="Parse JSON" width="557" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Content&lt;/strong&gt;: &lt;em&gt;body('HTTP_1')?['analyzeResult/tables']&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Schema&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"array"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"columnCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"integer"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"cells"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"array"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"rowIndex"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"integer"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"columnIndex"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"integer"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
              &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"rowIndex"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"columnIndex"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"columnCount"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cells"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the full schema as we do need a few of the properties.&lt;/p&gt;

&lt;h3&gt;
  
  
  For each – Table
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Input&lt;/strong&gt;: &lt;em&gt;body('Parse_JSON')&lt;/em&gt;&lt;br&gt;
If you have multiple tables to go through, this is useful; if not, you can skip this action.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbwxwjjogev1vwbiq2k6p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbwxwjjogev1vwbiq2k6p.png" alt="For each - Table" width="557" height="416"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Set variable ParsedCellsArray
&lt;/h3&gt;

&lt;p&gt;Set the &lt;strong&gt;ParsedCellsArray&lt;/strong&gt; variable with 'cells' - this is the tables cells.&lt;br&gt;
&lt;strong&gt;Name&lt;/strong&gt;: &lt;em&gt;ParsedCellsArray&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Value&lt;/strong&gt;: &lt;em&gt;items('For_each&lt;/em&gt;-&lt;em&gt;Table')['cells']&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Select
&lt;/h3&gt;

&lt;p&gt;So, if we were to just use....&lt;/p&gt;
&lt;h3&gt;
  
  
  From: "@variables('ParsedCellsArray')",
&lt;/h3&gt;
&lt;h3&gt;
  
  
  Map:
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@item()?&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;'content'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"rowIndex"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@item()?&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;'rowIndex'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"columnIndex"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@item()?&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;'columnIndex'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then we would get each cell on top of each other in separate objects,&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F49z5qcip8rrng422884z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F49z5qcip8rrng422884z.png" alt="Image description" width="345" height="345"&gt;&lt;/a&gt;&lt;br&gt;
which we would have to somehow ZigZag across or remap, as we want every object in our array to contain a Name and a Price. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnesj9gledrh6w3gxijmk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnesj9gledrh6w3gxijmk.png" alt="Standard Select Power Query" width="511" height="298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To do this we need to integrate a Range into the Select action using:&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;range(0, length(variables('ParsedCellsArray')))&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
 to generate an index to iterate over the array.&lt;/p&gt;
&lt;h4&gt;
  
  
  From
&lt;/h4&gt;

&lt;p&gt;In order to get the value of the adjacent column in the Select action, we can use &lt;code&gt;range(startIndex: integer, count: integer)&lt;/code&gt; and use &lt;code&gt;length()&lt;/code&gt; to use the length of &lt;strong&gt;ParsedCellsArray&lt;/strong&gt;. This allows the Select action to iterate over each element in **ParsedCellsArray **and generate a sequence of numbers.&lt;/p&gt;
&lt;h4&gt;
  
  
  Map
&lt;/h4&gt;

&lt;p&gt;This number sequence is then used in the &lt;strong&gt;Map&lt;/strong&gt; for the last Property to get the next element “&lt;strong&gt;nextContent&lt;/strong&gt;”.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;nextContent&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@{if(less(item(), sub(length(variables('ParsedCellsArray')), 1)), variables('ParsedCellsArray')[add(item(), 1)]?['content'], null)}&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;This expression uses the &lt;code&gt;If()&lt;/code&gt; function to check if the current index &lt;code&gt;item()&lt;/code&gt; is less than the last index of the array &lt;code&gt;sub(length(variables('ParsedCellsArray')), 1))&lt;/code&gt;. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If true, it retrieves the content of the next element &lt;code&gt;variables('ParsedCellsArray')[add(item(), 1)]?['content'])&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If false (i.e., the current element is the last one), it returns null.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So to put this all together we get:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From&lt;/strong&gt;: &lt;em&gt;range(0, length(variables('ParsedCellsArray')))&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Map&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@{variables('ParsedCellsArray')[item()]?['content']}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rowIndex"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@{variables('ParsedCellsArray')[item()]?['rowIndex']}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"columnIndex"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@{variables('ParsedCellsArray')[item()]?['columnIndex']}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"isColumnHeader"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@{equals(variables('ParsedCellsArray')[item()]?['kind'], 'columnHeader')}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@{item()}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"nextContent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@{if(less(item(), sub(length(variables('ParsedCellsArray')), 1)), variables('ParsedCellsArray')[add(item(), 1)]?['content'], null)}"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb2og84d2lnvd4vviw1qc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb2og84d2lnvd4vviw1qc.png" alt="Select" width="513" height="389"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The outcome of this starts to line up for us, but still needs Filtering... For example we only need the first Column and we can ignore the column headers.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyhfvpj0dadrr6r9u35zo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyhfvpj0dadrr6r9u35zo.png" alt="WorkingExport - Power Query" width="349" height="296"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Filter Array
&lt;/h3&gt;

&lt;p&gt;We can use Filter Array to filter the returned data. This is especially useful if the tables contain some data that we don’t want, such as comments or notes. Rather than using a single, &lt;strong&gt;basic filter&lt;/strong&gt;, we need to switch to &lt;strong&gt;advanced mode&lt;/strong&gt; 🤓 to combine the multiple conditions we want. &lt;br&gt;
You may want to use other conditions inside the &lt;code&gt;and()&lt;/code&gt; expression to fine-tune your data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From&lt;/strong&gt;: &lt;em&gt;body('Select')&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Advanced Filter:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;@and(&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;equals(item()?&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;'columnIndex'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="err"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//Only&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;first&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;column&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;equals(item()?&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;'isColumnHeader'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="err"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//Ignores&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Column&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Header&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;not(equals(item()?&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;'content'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'')),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//No&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Blanks&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;not(equals(item()?&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;'nextContent'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'')),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//No&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Blanks&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpvatdbb4qtpe8c4gd0fd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpvatdbb4qtpe8c4gd0fd.png" alt="Filter Array" width="555" height="254"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Select – Filtered Table
&lt;/h3&gt;

&lt;p&gt;We can merge in some of the metadata extracted from the Document, which we can now align in the context of each record in the array. The first three in my example are from the Metadata Object created earlier. You can also use this opportunity to further cleanse the values returned using string expressions if you need.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;From&lt;/strong&gt;: &lt;em&gt;body('Filter_Array')&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Map&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Report_Name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;variables('Metadata')?&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;'Report_Name'&lt;/span&gt;&lt;span class="p"&gt;]},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Issue_No"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;variables('Metadata')?&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;'Issue_No'&lt;/span&gt;&lt;span class="p"&gt;]},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Issue_Date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;variables('Metadata')?&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;'Issue_Date'&lt;/span&gt;&lt;span class="p"&gt;]},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Product"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;item()?&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;'content'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;item()?&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;'nextContent'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgjcclchanvq4zmu03k6i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgjcclchanvq4zmu03k6i.png" alt="Select - Filtered Table" width="518" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Set variable - Filtered TransformedArray
&lt;/h2&gt;

&lt;p&gt;Value: &lt;code&gt;body('Select_-_Filtered_Table')&lt;/code&gt;&lt;br&gt;
We will capture the table data into an array so that we can use it elsewhere. Here you can do whatever you want with your array. If you want to use an Add a new row Dataverse action, you can map each array property in the action for example.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Thank you for reading this post. Hopefully, this is useful to anyone who needs to use this particular Azure AI Document Intelligence Model to process their Documents and place the data into a more organised format.  Please leave feedback in the Comments if you found this useful, or if there are any improvements you could recommend. Please experiment with it too, I'd love to hear some of the outcomes.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>azure</category>
      <category>powerautomate</category>
      <category>json</category>
    </item>
    <item>
      <title>Using Mermaid JS to generate a diagram from Power Automate</title>
      <dc:creator>Matthew Collinge</dc:creator>
      <pubDate>Tue, 20 Feb 2024 19:52:20 +0000</pubDate>
      <link>https://dev.to/mcombp/using-mermaid-js-to-generate-a-diagram-from-power-automate-1f68</link>
      <guid>https://dev.to/mcombp/using-mermaid-js-to-generate-a-diagram-from-power-automate-1f68</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;This is the "bonus part" of my blog series on &lt;br&gt;
&lt;a href="https://dev.to/mcombp/conversational-approval-process-using-adaptive-cards-and-json-objects-4mih"&gt;creating a Conversational Approval Process using Power Automate and Microsoft Teams.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I needed a way to produce an easy to read depiction of the steps of a process to users or even a way to debug what happened. After seeing Jon Russell and Mike Gowland's amazing demo of&lt;br&gt;
&lt;strong&gt;JustAskIt&lt;/strong&gt; on a &lt;a href="https://youtu.be/yderRfy2wWA?si=gi11PmzVnYzyI_DP&amp;amp;t=3344" rel="noopener noreferrer"&gt;Microsoft 365 &amp;amp; Power Platform Development community call&lt;/a&gt; I have been keen to try out Mermaid JS in Power Automate.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Mermaid JS?
&lt;/h3&gt;

&lt;p&gt;Mermaid JS is a tool that lets you create diagrams and charts such as flowcharts, sequence diagrams, Gantt charts using simple text commands. It works by converting your text commands into a graphical representation that you can customize and share.&lt;br&gt;
&lt;a href="https://mermaid.live/" rel="noopener noreferrer"&gt;https://mermaid.live/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Using Mermaid JS we easily can convert Markdown like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

flowchart TD
    A[Christmas] --&amp;gt;|Get money| B(Go shopping)
    B --&amp;gt; C{Let me think}
    C --&amp;gt;|One| D[Laptop]
    C --&amp;gt;|Two| E[iPhone]
    C --&amp;gt;|Three| F[fa:fa-car Car]



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;into an image like this that lists the steps in an easy to read graphical format:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi4ibxk4m1ifw0bw156nf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi4ibxk4m1ifw0bw156nf.png" alt="Mermaid Example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the Flow
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Manual Trigger
&lt;/h3&gt;

&lt;p&gt;We start off our Flow with the manual trigger. The first text input is &lt;strong&gt;varSteps&lt;/strong&gt;, this is the steps that we are going to either create or append to our existing Flowchart.&lt;br&gt;
The other text input is the Flowchart, so this is where we could insert an existing Flowchart to our Power Automate Flow. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5inkmqwjnnhvklegv7is.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5inkmqwjnnhvklegv7is.png" alt="Manual Trigger"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Alphabets Variable
&lt;/h3&gt;

&lt;p&gt;The first variable to initialise is Alphabets, here we will have a string value of the 26 character alphabet. We will use this to pick out the next alphabetical character if we need to append to an existing Flowchart. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxw8tw1umoooxjavqvkaz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxw8tw1umoooxjavqvkaz.png" alt="Alphabets Variable"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Flowchart Variable
&lt;/h3&gt;

&lt;p&gt;The next variable to initialise is Flowchart, which is a string variable that will capture the Flowchart text input from the manual trigger. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqz95zy37uiofpxtsogu5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqz95zy37uiofpxtsogu5.png" alt="Flowchart Variable"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  varSteps Variable
&lt;/h3&gt;

&lt;p&gt;Then the next variable to initialise is the &lt;strong&gt;varSteps&lt;/strong&gt;, which is an object variable. It will capture the text input for &lt;strong&gt;varSteps&lt;/strong&gt; from the manual input, but we will wrap this inside JSON() so that it is converted to JSON from a string value. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6bv2mspejta1l7nxvyl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6bv2mspejta1l7nxvyl.png" alt="varSteps Variable"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Condition
&lt;/h2&gt;

&lt;p&gt;We will start the actions with a Condition action. The condition will check whether variable('Flowchart') is equal to Null. If it is  Null, then we'll create on from scratch. If it's not, then we can append to it with further Steps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwlqxk6qjnc7upqvo1aqy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwlqxk6qjnc7upqvo1aqy.png" alt="Condition - 1st Time Around"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a new FlowChart
&lt;/h2&gt;

&lt;p&gt;I will first go through the steps that are required in the Yes or True side. In here we are just creating a brand new Flowchart that is created in the format ready for Mermaid JS. Set the variable &lt;strong&gt;FlowChart&lt;/strong&gt; and in the value box we will build our markdown so that it can be read inside the Mermaid JS. We will reference the Object properties from the &lt;strong&gt;varSteps&lt;/strong&gt; to build that.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define the type using "flowchart TD"&lt;/li&gt;
&lt;li&gt;Starting with &lt;strong&gt;“A”&lt;/strong&gt; we will enter &lt;strong&gt;variables('varSteps')?['Trigger']&lt;/strong&gt; .&lt;/li&gt;
&lt;li&gt;Then for &lt;strong&gt;“B”&lt;/strong&gt; we will add the &lt;strong&gt;variables('varSteps')?['Condition']&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;Then &lt;strong&gt;”B--&amp;gt;”&lt;/strong&gt; for variables('varSteps')?['Outcome'] &lt;/li&gt;
&lt;li&gt;Lastly we will insert the &lt;strong&gt;“C”&lt;/strong&gt; &lt;strong&gt;variables('varSteps')?['Action']&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That should give us all we need to create a new Flowchart.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7zvp9rlxjr433gxf6o1y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7zvp9rlxjr433gxf6o1y.png" alt="Set Variable - FlowChart"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Appending to an Existing Flowchart
&lt;/h2&gt;

&lt;p&gt;On the No / False side of the Condition Action we will be appending to an existing Flowchart. This is useful if there are multiple child flows that make up part of the full process that you are trying to build into a Flowchart. In my Conversational Approval process, there may only be one run of the Approver's Adaptive card, or there may be a need to the Requestor to respond to an Adaptive Card also. Having the Append option allows us to keep building on top of the initial FlowChart that gets created.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compose - Last Step
&lt;/h2&gt;

&lt;p&gt;We will start by extracting the alphabetical character for the last step that exists in the Flowchart. For example; if the existing Flowchart is:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

flowchart TD
A[RM Request] --&amp;gt; B{Matthew Collinge - receives Approval Card}
B --&amp;gt;|Pending| C[Send back to Matthew Collinge]
Then we want the letter **“C”**


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Using a Compose action we can use. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 sub(lastIndexOf(variables('flowchart'), '['), 1), 1)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2mzzl9brk8ec2n40v698.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2mzzl9brk8ec2n40v698.png" alt="Compose - Last Step"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will need to use this value to increment to the next letter in the alphabet. &lt;/p&gt;

&lt;h2&gt;
  
  
  Compose Letter No
&lt;/h2&gt;

&lt;p&gt;We now get the next letter's number by using the next compose action. Referencing the alphabet variable we get the next number (D would be 4). &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 outputs('Compose_-_Last_Step'),1)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2gxjgs4hmfgu4kn5ebwj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2gxjgs4hmfgu4kn5ebwj.png" alt="Compose - Letter No"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Compose Approval
&lt;/h2&gt;

&lt;p&gt;The next compose step is actually composing the approval Markdown text, starting with the original Flowchart and then appending the next steps. It will start with the starting letter that we have derived from the previous few actions. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

@{variables('FlowChart')}
@{outputs('Compose_-_Last_Step')} --&amp;gt; @{substring(variables('Alphabets'), add(outputs('Compose_-_Letter_No'),2),1)
}@{variables('varSteps')?['Condition']}
@{substring(variables('Alphabets'), add(outputs('Compose_-_Letter_No'),2),1)
} --&amp;gt;@{variables('varSteps')?['Outcome']} @{substring(variables('Alphabets'), add(outputs('Compose_-_Letter_No'),3),1)
}@{variables('varSteps')?['Action']}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwehwgmjg8qtgvljzzth3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwehwgmjg8qtgvljzzth3.png" alt="Compose Approval"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The last step on this append side is setting the Flowchart variable with the output from the previous compose action, so that we have a variable with the whole Flowchart ready to convert to Mermaid JS.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhzpyam2i1ty7o4c5vv7c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhzpyam2i1ty7o4c5vv7c.png" alt="Set variable - FlowChart Appended"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it all together
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Compose - URL
&lt;/h3&gt;

&lt;p&gt;After the Condition Action we have a single compose action. &lt;br&gt;
This will concatenate a string starting with &lt;strong&gt;'&lt;a href="https://mermaid.ink/img/" rel="noopener noreferrer"&gt;https://mermaid.ink/img/&lt;/a&gt;'&lt;/strong&gt;, and here is where we convert the Flowchart variable to base 64 giving us the correct encoding to create a URL.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

concat('https://mermaid.ink/img/',base64(variables('FlowChart')))


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi5q0heechxjc4wznos7p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi5q0heechxjc4wznos7p.png" alt="Compose - URL"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Respond to App or Flow
&lt;/h3&gt;

&lt;p&gt;All we need to do now, is respond to the App or Flow that triggered this Flow. We will use Text input of Flowchart using the Flowchart variable and a text input of Mermaid URL which includes the URL we have just generated.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1fgvyisoo7coouw643w4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1fgvyisoo7coouw643w4.png" alt="Respond to App or Flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Inserting this Child Flow into another Flow to capture the steps
&lt;/h2&gt;

&lt;p&gt;Using the &lt;strong&gt;"[child] - Approver Card"&lt;/strong&gt; as an example from my previous posts. In our Parent Flow we can construct a JSON Object inside of a Compose action.&lt;/p&gt;

&lt;h3&gt;
  
  
  Compose - Outcome
&lt;/h3&gt;

&lt;p&gt;Capture the outcome of the Adaptive Card&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp64pumgbabhndg836dee.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp64pumgbabhndg836dee.png" alt="Compose - Outcome"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

outputs('Post_adaptive_card_and_wait_for_a_response')?['body/submitActionId']


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Compose - Action
&lt;/h3&gt;

&lt;p&gt;Convert this outcome using "If(equals" to what the follow on Action will be:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

if(equals(outputs('Post_adaptive_card_and_wait_for_a_response')?['body/submitActionId'], 'approve'),'Complete Approval',
if(equals(outputs('Post_adaptive_card_and_wait_for_a_response')?['body/submitActionId'], 'respond'), 'Send back to Requestor', 
if(equals(outputs('Post_adaptive_card_and_wait_for_a_response')?['body/submitActionId'], 'reject'),'Inform Requestor',
if(equals(outputs('Post_adaptive_card_and_wait_for_a_response')?['body/submitActionId'], 'acAssignCard'), 'Assign to other person'))))


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz8z61g6wg49d5pa07m51.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz8z61g6wg49d5pa07m51.png" alt="Compose - Action"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Compose - varSteps
&lt;/h2&gt;

&lt;p&gt;The JSON Object will be written in a format that could capture various outcomes and statuses that happen within the flow in . For Example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

{
  "Trigger": "[@{variables('varObject')?['Request_Type']} Request]",
  "Condition": "{@{variables('varObject')?['Approver_Name']} - receives Approval Card}",
  "Outcome": "|@{outputs('Compose_-_Status')}|",
  "Action": "[@{outputs('Compose_-_Outcome')}]"
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh1wrtozxww9asu3c27ub.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh1wrtozxww9asu3c27ub.png" alt="Compose - varSteps"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then we can trigger the Child Flow using 'Compose - varSteps' as a String.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

string(outputs('Compose_-_varSteps'))


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;and then FlowChart. If we're carrying over a previous one held inside our varObject or Null if we're creating a new one.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

if(empty(variables('varObject')['FlowChart']), 'null', variables('varObject')['FlowChart'])



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqy2upa1p8vqkiveh9r4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqy2upa1p8vqkiveh9r4.png" alt="Run a Child Flow - Generate Mermaid Flowchart"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Capture the Response
&lt;/h3&gt;

&lt;p&gt;To then capture from our child flow and add it to our varObject.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbye58sdydt138krtdxm8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbye58sdydt138krtdxm8.png" alt="Update Property"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc9z09ol5tmvjrtbhabvb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc9z09ol5tmvjrtbhabvb.png" alt="Set FlowChart"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Thank you for reading this post. Please leave feedback in the Comments if you found this useful, or if there are any improvements you could recommend. Please experiment with it too, I'd love to hear some of the outcomes.&lt;/p&gt;

&lt;p&gt;For such a simple Flow, I found it quite difficult to write and explain, so I hope it all makes sense!&lt;/p&gt;

</description>
      <category>powerautomate</category>
      <category>powerplatform</category>
      <category>javascript</category>
      <category>markdown</category>
    </item>
    <item>
      <title>Conversational Approval process using Adaptive Cards and JSON objects</title>
      <dc:creator>Matthew Collinge</dc:creator>
      <pubDate>Mon, 29 Jan 2024 20:49:16 +0000</pubDate>
      <link>https://dev.to/mcombp/conversational-approval-process-using-adaptive-cards-and-json-objects-4mih</link>
      <guid>https://dev.to/mcombp/conversational-approval-process-using-adaptive-cards-and-json-objects-4mih</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This is Part 3 of a series of posts where I try to explain how to send Form answers from a Power App into Power Automate and then send Adaptive Cards in Microsoft Teams to allow the Requestor and Approver make incremental changes to the Form answers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/mcombp/passing-objects-from-power-apps-to-power-automate-31ji"&gt;Part 1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/mcombp/passing-a-choices-list-from-power-apps-to-an-adaptive-card-2nga"&gt;Part 2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We're going to start Part 3 by building a second Flow. In this Form Approval Process this Flow will actually be the one that sends an Adaptive Card to our Approver.&lt;/p&gt;

&lt;p&gt;Here is an overview of what we're going to do here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgle4iksyoo6f8ar1aazy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgle4iksyoo6f8ar1aazy.png" alt="Solution Process Flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why don't I use the standard Approvals Actions?
&lt;/h2&gt;

&lt;p&gt;What I'm trying to achieve is a more conversational process for the Approval, where the Requestor and Approver can both edit the data inside Message Cards in Teams until the Approver decides what to do with it.. We'll do this by passing our Object again, plus a few other useful Expressions.&lt;/p&gt;

&lt;p&gt;We're going to trigger this from our "[proxy] - Object Flow" we made in an earlier Post: &lt;a href="https://dev.to/mcombp/passing-objects-from-power-apps-to-power-automate-31ji"&gt;Passing Objects from Power Apps to Power Automate&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Approver's Flow
&lt;/h2&gt;

&lt;p&gt;As this will be a Child Flow. We'll need a Manual trigger and I'll call this Flow &lt;strong&gt;"[child] - Approver Card"&lt;/strong&gt;. We just need one text Input. &lt;strong&gt;varObject&lt;/strong&gt; as this can contain everything we need.&lt;/p&gt;

&lt;p&gt;Then, we'll Initialize a Variable that will convert the Text Input to JSON. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

json(triggerBody()['text'])


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc8doqcunjsnxb3vtbhjq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc8doqcunjsnxb3vtbhjq.png" alt="Power Automate - Manual Trigger"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adaptive Card
&lt;/h2&gt;

&lt;p&gt;Let's add another action - &lt;strong&gt;Post adaptive card and wait for a response&lt;/strong&gt;. We'll need to construct an Adaptive card for this. Again I would recommend you build your full Adaptive Card by previewing it with the Help of &lt;a href="https://adaptivecards.io/designer" rel="noopener noreferrer"&gt;The Adaptive Card Designer&lt;/a&gt; or the &lt;a href="https://marketplace.visualstudio.com/items?itemName=TeamsDevApp.vscode-adaptive-cards#:~:text=The%20Microsoft%20Adaptive%20Card%20Previewer,%2C%20and%20high%2Dcontrast%20themes." rel="noopener noreferrer"&gt;VSCode Microsoft Adaptive Card Previewer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnxyss5pinjgy81at54s3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnxyss5pinjgy81at54s3.png" alt="Power Automate - Post adaptive card and wait for a response"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Text Inputs&lt;/strong&gt;&lt;br&gt;
I will start with the Text value we're getting for the "Name" field in the Form.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We need a type, this will be &lt;strong&gt;Input.Text&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;We can specify the Label above the field as "Name"&lt;/li&gt;
&lt;li&gt;For the Value, we can reference the property inside of &lt;strong&gt;varObject&lt;/strong&gt; by inserting "@{variables('varObject')?['Name']}" &lt;/li&gt;
&lt;li&gt;Finally, each field in the Adaptive Card needs an id, which we can keep exactly the same as the Object Property name to make it easier to reference in the future.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In my scenario, we already have an input value, so 'Placeholder Text' isn't really needed.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

    {
      "type": "Input.Text",
      "label": "Name",
      "value": "@{variables('varObject')?['Name']}",
      "id": "Name"
    },


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can use the example above to build any other Text Inputs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Toggle&lt;/strong&gt;&lt;br&gt;
The 'Mortgaged' field is a Boolean field in our Power Apps Form, so we can replicate this with &lt;strong&gt;Input.Toggle&lt;/strong&gt;, similar to the Text Input we need to give an &lt;strong&gt;id&lt;/strong&gt;, &lt;strong&gt;label&lt;/strong&gt; and &lt;strong&gt;value&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

    {
      "type": "Input.Toggle",
      "title": "Mortgaged",
      "id": "Mortgaged",
      "label": "Mortgaged",
      "value": "@{variables('varObject')?['Mortgaged']}"
    },


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Choices&lt;/strong&gt;&lt;br&gt;
I have previously described how we can have a Choices Dropdown in this Blog Post: &lt;br&gt;
&lt;a href="https://dev.to/mcombp/passing-a-choices-list-from-power-apps-to-an-adaptive-card-2nga"&gt;Passing a Choices List from Power Apps to an Adaptive Card&lt;/a&gt; - in this example, we can add a Label: &lt;strong&gt;"Country"&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

    {
    "type": "Input.ChoiceSet",
    "label": "Country",
    "choices": @{variables('varObject')?['Countries']},
    "id": "Country",
    "value": "@{variables('varObject')?['Country']}"
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;For the &lt;strong&gt;Rating&lt;/strong&gt; Field, we know there's only five options, so we might as well enter these manually, giving us this: &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

{
      "type": "Input.ChoiceSet",
      "choices": [
        {
          "title": "1",
          "value": "1"
        },
        {
          "title": "2",
          "value": "2"
        },
        {
          "title": "3",
          "value": "3"
        },
        {
          "title": "4",
          "value": "4"
        },
                {
          "title": "5",
          "value": "5"
        }
      ],
      "label": "Rating",
      "id": "Rating",
      "value": "@{variables('varObject')?['Rating']}"
    }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Actions&lt;/strong&gt;&lt;br&gt;
That's the fields done, now we need some actions to respond with. These can be placed at the foot of the Adaptive Card like this and will be where the Approver makes their decision.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

  "actions": [
        {
            "type": "Action.Submit",
            "title": "Approve",
            "style": "positive",
            "id": "approve"
        },
        {
            "type": "Action.Submit",
            "title": "Respond",
            "id": "respond"
        },
        {
            "type": "Action.Submit",
            "title": "Reject",
            "style": "destructive",
            "id": "reject"
        },
        {
        "type": "Action.ShowCard",
        "title": "ReAssign",
        "card": {
            "type": "AdaptiveCard",
            "body": [
                {
                "type": "Input.Text",
                "label": "ReAssign to",
                "style": "Email",
                "id": "ReAssign_To",
                "isRequired": true,
                "errorMessage": "Please enter an email address"
                }
            ],
            "actions": [
                {
                "type": "Action.Submit",
                "title": "ReAssign"
                }
            ]
        },
        "id": "acAssignCard"
        }
    ]


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Feel free to elaborate on the options you provide, such as comments, or even an option to reassign. We'll use these soon in a Switch Action to decide on the next step. IF you want to use this you'll see that there's an expandable section (&lt;a href="https://adaptivecards.io/explorer/Action.ShowCard.html)%5BAction.ShowCard%5D" rel="noopener noreferrer"&gt;https://adaptivecards.io/explorer/Action.ShowCard.html)[Action.ShowCard]&lt;/a&gt; when &lt;strong&gt;ReAssign&lt;/strong&gt; is selected, this is to ensure an email address is entered. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fih8l00gjkemqfszfmwt8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fih8l00gjkemqfszfmwt8.png" alt="Adaptive Card - Approver Actions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/madmat01/devtoBlog/blob/main/Approver%20Card.json" rel="noopener noreferrer"&gt;The JSON for the Approval Adaptive Card is here.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Union
&lt;/h2&gt;

&lt;p&gt;Now we have an Adaptive card that we can send to an Approver and Wait for a response. &lt;/p&gt;

&lt;p&gt;We can now capture any changes that the Approver may have made back into our original &lt;strong&gt;varObject&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Start by adding a Compose Action, and in the Compose Action we can enter this Expression&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

union(variables('varObject'),outputs('Post_adaptive_card_and_wait_for_a_response').body.data)


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgpehha063xcao82dsbfj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgpehha063xcao82dsbfj.png" alt="Compose - Union Body Data with varObject"&gt;&lt;/a&gt;&lt;br&gt;
What the Union expression does is combine the properties from the varObject with the data obtained from the response of the action &lt;strong&gt;Post_adaptive_card_and_wait_for_a_response&lt;/strong&gt;. This is done to update or synchronize the values in the &lt;strong&gt;varObject&lt;/strong&gt; with the field values changed in the Adaptive Card.&lt;/p&gt;

&lt;p&gt;Then we just need to feed the output of our Compose expression into Set the &lt;strong&gt;varObject&lt;/strong&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F46viu3n3x7xrlcijz0q7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F46viu3n3x7xrlcijz0q7.png" alt="Set variable - varObject"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Switch
&lt;/h2&gt;

&lt;p&gt;We'll add a switch Condition to allow us to decide the path of the Flow from this point using some Switch Cases, which match the the ID of our Actions.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

outputs('Post_adaptive_card_and_wait_for_a_response')?['body/submitActionId']


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We have the options: &lt;strong&gt;approve&lt;/strong&gt;, &lt;strong&gt;respond&lt;/strong&gt;, &lt;strong&gt;reject&lt;/strong&gt;, &lt;strong&gt;ReAssign_To&lt;/strong&gt; and we can decide what we we want to happen with each of these paths. I'll come to &lt;strong&gt;respond&lt;/strong&gt; in a moment, but I will first give some examples of how you can use the other Switch Cases.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frw1sewu61kir7vzwn796.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frw1sewu61kir7vzwn796.png" alt="Power Automate - Switch"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Approve&lt;/strong&gt;&lt;br&gt;
This would be where you would define what you want to happen if the Adaptive Card is approved; Send an Email, update a SharePoint List Item etc...&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reject&lt;/strong&gt;&lt;br&gt;
Here you could send Post a Standard Adaptive card or send an email to the Requestor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ReAssign&lt;/strong&gt;&lt;br&gt;
A good example for using the &lt;strong&gt;setProperty()&lt;/strong&gt; expression would be if you had a defined Approver_Email in your varObject. You could use a Compose Action with:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

setProperty(variables('varObject'), 'Approver_Email', outputs('Approver_adaptive_card')?['body/data/ReAssign_To'])


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then, Set Variable - varObject again with the output of the Compose Action.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4fq2s12iroz5syxmnkmv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4fq2s12iroz5syxmnkmv.png" alt="Power Automate - ReAssign"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Respond&lt;/strong&gt;&lt;br&gt;
So for the Respond Case, we're going to create another Child Flow, it will be a copy of this Flow where the Requestor can make changes to re-submit to the Approver.&lt;/p&gt;

&lt;h3&gt;
  
  
  Respond to a PowerApp or flow
&lt;/h3&gt;

&lt;p&gt;To make sure this Child Card let's the Parent Flow it has run, place in a &lt;strong&gt;Respond to a PowerApp or flow&lt;/strong&gt; as the last Action.&lt;/p&gt;

&lt;h2&gt;
  
  
  [proxy] - Object Flow
&lt;/h2&gt;

&lt;p&gt;Before we move on to the Requestor Card, we need to trigger this Child Flow from the &lt;strong&gt;[proxy] - Object Flow&lt;/strong&gt; by making this the 3rd action in the Flow.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc55672arxmxdf2qm64g0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc55672arxmxdf2qm64g0.png" alt="Object Flow - Run a Child Flow - [child] - Approver Card.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Requestor Card
&lt;/h2&gt;

&lt;p&gt;Now - back to the &lt;strong&gt;[child] - Approver Card]&lt;/strong&gt; Flow, so we can copy it....&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fexjjtr61ge4day8b0v6u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fexjjtr61ge4day8b0v6u.png" alt="Copy of - [child] - Approver Card"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We'll call this: &lt;strong&gt;[child] - Requestor Card&lt;/strong&gt; and add it to the same solution as our App and other Flows.&lt;/p&gt;

&lt;p&gt;Let's first make a couple of small adjustments to the &lt;strong&gt;Post adaptive card and wait for a response&lt;/strong&gt; Message in this one by changing the first TextBlock with text Property from:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F90eynqlss86t35550rb7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F90eynqlss86t35550rb7.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

    {
      "type": "TextBlock",
      "size": "Medium",
      "weight": "Bolder",
      "text": "Requestor Request"
    },


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then we just need to swap out the &lt;strong&gt;"actions": []&lt;/strong&gt; section at the bottom of the Card. The Requestor won't have the same options as the Approver, so we can swap out the whole section for this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

  "actions": [
        {   
        "type": "Action.Submit",
        "title": "Re-Submit 🔁",
        "id": "acSubmit",
        "style": "positive"
      },
      {
        "type": "Action.Submit",
        "title": "Cancel Request ❌",
        "id": "acCancelRequest",
        "style": "destructive"
      }
    ]


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And of course, change the Receipient, so that the message goes to our Receipient. The Union action is still here to update any changes which then update our varObject.&lt;/p&gt;

&lt;h2&gt;
  
  
  Switch
&lt;/h2&gt;

&lt;p&gt;As we've changed the Actions, we'll now need to change the cases to &lt;strong&gt;"acSubmit"&lt;/strong&gt; and &lt;strong&gt;"acCancelRequest"&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fugdhlkvq4g2c9wv0rkyq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fugdhlkvq4g2c9wv0rkyq.png" alt="Power Automate - Requestor Switch"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;acCancelRequest&lt;/strong&gt;&lt;br&gt;
Again, I'll leave it up to you what to do with this path; you may want to imform the Approver with another standard Adaptive Card message.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;acSubmit&lt;/strong&gt;&lt;br&gt;
So here's the key feature that allows us to perform this conversation loop between the Approver and Requestor. - We're now going to re-trigger &lt;strong&gt;[child] - Approver Card&lt;/strong&gt; and with that, pass back the varObject as a String again.&lt;/p&gt;

&lt;p&gt;Create a &lt;strong&gt;'Run a Child Flow'&lt;/strong&gt; action and select our &lt;strong&gt;[child] - Approver Card&lt;/strong&gt; Flow we created earlier. For the varObject Text Input enter: &lt;strong&gt;&lt;em&gt;string(variables('varObject'))&lt;/em&gt;&lt;/strong&gt; - this converts the &lt;strong&gt;varObject&lt;/strong&gt; into a String again to pass to Approver Flow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fubt2qdgft8igtp7i0n86.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fubt2qdgft8igtp7i0n86.png" alt="Child - Approver Card"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Respond to a PowerApp or flow
&lt;/h2&gt;

&lt;p&gt;Again, to make sure this Child Card let's the Parent Flow it has run, place in a &lt;strong&gt;Respond to a PowerApp or flow&lt;/strong&gt; as the last Action.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/madmat01/devtoBlog/blob/main/Requestor%20Card.json" rel="noopener noreferrer"&gt;JSON for the Requestor Adaptive Card is here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Back to [child] - Approver Card to finish off
&lt;/h2&gt;

&lt;p&gt;All we need to do now is the mirror opposite of this in the &lt;strong&gt;[child] - Approver Card&lt;/strong&gt; Flow. Go back to that flow and underneath the &lt;strong&gt;Case - respond&lt;/strong&gt; create a &lt;strong&gt;'Run a Child Flow'&lt;/strong&gt; action and select our &lt;strong&gt;[child] - Requestor Card&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7oj1sulh4pdr6khwse4i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7oj1sulh4pdr6khwse4i.png" alt="Run a Child Flow - [child] - Requestor Card"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing and fine tuning
&lt;/h2&gt;

&lt;p&gt;To prevent any confusing repeat runs of these Flows, I would recommend changing the Retry Policy&lt;br&gt;
on each Run a Child Flow Action to &lt;strong&gt;None&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faqb4qi9z6w9r9sk4u46f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faqb4qi9z6w9r9sk4u46f.png" alt="Retry Policy - None"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, here are some examples that we should see in Microsoft Teams.&lt;/p&gt;

&lt;h3&gt;
  
  
  Power App Form
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqoh1avf7c2tx9bpq8klx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqoh1avf7c2tx9bpq8klx.png" alt="Power App Form"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Approver's 1st Message
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcnqbp9bapdg8e2fibysx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcnqbp9bapdg8e2fibysx.png" alt="Approver's 1st Message "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Requestor's 1st Message
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftyq28vlocm90db1qe112.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftyq28vlocm90db1qe112.png" alt="Requestor's 1st Message "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Approver's 2nd Message
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw7zu2rfav31v1f7u0dob.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw7zu2rfav31v1f7u0dob.png" alt="Approver's 2nd Message"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Hopefully, that was a helpful guide. I have one final Post to add a little bit extra to this type of Approval process. Please leave any questions or comments below.&lt;/p&gt;

</description>
      <category>powerautomate</category>
      <category>powerplatform</category>
      <category>javascript</category>
      <category>lowcode</category>
    </item>
    <item>
      <title>Passing a Choices List from Power Apps to an Adaptive Card</title>
      <dc:creator>Matthew Collinge</dc:creator>
      <pubDate>Sat, 13 Jan 2024 18:53:31 +0000</pubDate>
      <link>https://dev.to/mcombp/passing-a-choices-list-from-power-apps-to-an-adaptive-card-2nga</link>
      <guid>https://dev.to/mcombp/passing-a-choices-list-from-power-apps-to-an-adaptive-card-2nga</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In a follow-on from my previous post &lt;a href="https://dev.to/mcombp/passing-objects-from-power-apps-to-power-automate-31ji"&gt;Passing Objects from Power Apps to Power Automate&lt;/a&gt; I am now going to cover a method I have found to 'render' our JSON Object in an Adaptive Card that is part of an Approval Process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;p&gt;After we have got our Object into Power Automate I mentioned that we can then reference a property by first referencing the name of the Object (varObject) and then the property name &lt;code&gt;variables('varObject')?['____']&lt;/code&gt;. These can be used inside of an Adaptive Card to show single text values, but what if we want to have a dynamically generated dropdown (choice) list inside of the Adaptive Card?&lt;/p&gt;

&lt;h2&gt;
  
  
  ChoiceSet
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc3hq5qpbzttizr2325md.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc3hq5qpbzttizr2325md.png" alt="Adaptive Card - ChoiceSet"&gt;&lt;/a&gt; &lt;a href="https://adaptivecards.io/explorer/Input.ChoiceSet.html" rel="noopener noreferrer"&gt;Adaptive Card - ChoiceSet&lt;/a&gt;&lt;br&gt;
The Adaptive Card Input.ChoiceSet needs a &lt;strong&gt;Title&lt;/strong&gt; and a &lt;strong&gt;Value&lt;/strong&gt; for each choice. &lt;strong&gt;Title&lt;/strong&gt; is the user friendly name and &lt;strong&gt;Value&lt;/strong&gt; is the value passed to your app our service.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

{
            "type": "Input.ChoiceSet",
            "choices": [
                {
                    "title": "Choice 1",
                    "value": "Choice 1"
                },
                {
                    "title": "Choice 2",
                    "value": "Choice 2"
                }
            ],
            "placeholder": "Placeholder text"
        }


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So, we need to prepare our data in that format.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choice Collection
&lt;/h2&gt;

&lt;p&gt;The method I have been using to do this is done back in Power Apps...&lt;br&gt;
This is where I am already using a Collection inside my OnVisible property of the Form Screen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo6il1irs1uyw24eoucxz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo6il1irs1uyw24eoucxz.png" alt="Power Apps - colCountry Collection"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a very basic collection, but in practice your use case may involve generating this from a Datasource Such as Dataverse or SharePoint &lt;a href="https://www.matthewdevaney.com/powerapps-collections-cookbook/create-a-collection-from-datasource/" rel="noopener noreferrer"&gt;Create A Collection (from a datasource) - Matthew Devaney&lt;/a&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Collect(
    colCountry,
    "England",
    "Northern Ireland",
    "Scotland",
    "Wales"
)


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This Collection works well for the Country Combobox in our Form.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp3qszploqjct21gztex9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp3qszploqjct21gztex9.jpg" alt="Power Apps - colCountry Combobox"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But, this Collection isn't quite right for a ChoiceSet yet as it only has a "Value" column. So, to sort this out I have written this, which can run before we create the varObject.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

ClearCollect(
    colCurrentCountries,//Array of Current countries for passing to Adaptive Card
    ForAll(
        ShowColumns(
            SortByColumns(//Sort Alphabetically
                colCountry,
                "Value",
                SortOrder.Ascending
            ),
            "Value"//We only want this column
        ),
        {
            value: Value,
            title: Value
        }
    )
)


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I will break down what is happening here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;First we create a collection called "colCurrentCountries" &lt;code&gt;ClearCollect(colCurrentCountries,&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Then we're going to loop through each country in the existing "colCountry" Collection using ForAll() to do the looping. But, we only need the "Value" column (this isn't strictly necessary in my example). Neither is 'SortByColumns()', but it keeps things tidy 🙂.&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ForAll(&lt;br&gt;
       ShowColumns(&lt;br&gt;
           SortByColumns(//Sort Alphabetically&lt;br&gt;
               colCountry,&lt;br&gt;
               "Value",&lt;br&gt;
               SortOrder.Ascending&lt;br&gt;
           ),&lt;br&gt;
           "Value"//We only want this column&lt;br&gt;
       ),{% raw %}&lt;code&gt;&lt;br&gt;
&lt;/code&gt;``&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The last part to construct is the schema of each record inside this Collection. To do this I'm just repeating the "Value" column for both the Title and Value as I've no need to for these to be different in the Adaptive Card.
&lt;code&gt;`
    {
        value: Value,
        title: Value
    }
`&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Adding the Collection to the Object
&lt;/h2&gt;

&lt;p&gt;To add the Collection or Array to the Object we just need to add the line 'Countries: colCurrentCountries' like so:&lt;br&gt;
&lt;code&gt;`&lt;br&gt;
Set(&lt;br&gt;
    varObject,&lt;br&gt;
    {&lt;br&gt;
        Name: txt_Name.Text,&lt;br&gt;
        Address_1: txt_Address_1.Text,&lt;br&gt;
        Address_2: txt_Address_2.Text,&lt;br&gt;
        City: txt_City.Text,&lt;br&gt;
        Country: cbx_Country.Selected.Value,&lt;br&gt;
        Mortgaged: tgl_Mortgaged.Value,&lt;br&gt;
        Rating: rtg_Rating.Value,&lt;br&gt;
        **Countries: colCurrentCountries**&lt;br&gt;
    }&lt;br&gt;
`&lt;/code&gt;&lt;br&gt;
So now with everything put together in Power Apps we have this in the OnSelect Property that runs the Flow:&lt;br&gt;
&lt;code&gt;`&lt;br&gt;
ClearCollect(&lt;br&gt;
    colCurrentCountries,//Array of Current countries for passing to Adaptive Card&lt;br&gt;
    ForAll(&lt;br&gt;
        ShowColumns(&lt;br&gt;
            SortByColumns(//Sort Alphabetically&lt;br&gt;
                colCountry,&lt;br&gt;
                "Value",&lt;br&gt;
                SortOrder.Ascending&lt;br&gt;
            ),&lt;br&gt;
            "Value"//We only want this column&lt;br&gt;
        ),&lt;br&gt;
        {&lt;br&gt;
            value: Value,&lt;br&gt;
            title: Value&lt;br&gt;
        }&lt;br&gt;
    )&lt;br&gt;
);&lt;br&gt;
Set(&lt;br&gt;
    varObject,&lt;br&gt;
    {&lt;br&gt;
        Name: txt_Name.Text,&lt;br&gt;
        Address_1: txt_Address_1.Text,&lt;br&gt;
        Address_2: txt_Address_2.Text,&lt;br&gt;
        City: txt_City.Text,&lt;br&gt;
        Country: cbx_Country.Selected.Value,&lt;br&gt;
        Mortgaged: tgl_Mortgaged.Value,&lt;br&gt;
        Rating: rtg_Rating.Value,&lt;br&gt;
        Countries: colCurrentCountries&lt;br&gt;
    }&lt;br&gt;
);&lt;br&gt;
'[proxy]-ObjectFlow'.Run(&lt;br&gt;
    JSON(&lt;br&gt;
        varObject&lt;br&gt;
    )&lt;br&gt;
)&lt;br&gt;
`&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Power Automate
&lt;/h2&gt;

&lt;p&gt;To see this in an Adaptive Card in Power Automate for now we need to add an Action: "Post card in a chat or channel" Posting As: &lt;strong&gt;Flow Bot&lt;/strong&gt; and Post In: &lt;strong&gt;Chat with Flow Bot&lt;/strong&gt;. For testing add your email address for our "Approver" and then we can construct the Message.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fownwyd8ofxksxgbph7wd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fownwyd8ofxksxgbph7wd.png" alt="Power Automate - Adaptive Card Message"&gt;&lt;/a&gt; &lt;em&gt;Yes, this screenshot is from the V2 designer&lt;/em&gt; 😫&lt;/p&gt;

&lt;h2&gt;
  
  
  Adaptive Card
&lt;/h2&gt;

&lt;p&gt;I would recommend you build your full Adaptive Card by previewing it with the Help of (&lt;a href="https://adaptivecards.io/designer/)%5BThe" rel="noopener noreferrer"&gt;https://adaptivecards.io/designer/)[The&lt;/a&gt; Adaptive Card Designer] or the (&lt;a href="https://marketplace.visualstudio.com/items?itemName=TeamsDevApp.vscode-adaptive-cards#:%7E:text=The%20Microsoft%20Adaptive%20Card%20Previewer,%2C%20and%20high%2Dcontrast%20themes.)%5BVSCode" rel="noopener noreferrer"&gt;https://marketplace.visualstudio.com/items?itemName=TeamsDevApp.vscode-adaptive-cards#:~:text=The%20Microsoft%20Adaptive%20Card%20Previewer,%2C%20and%20high%2Dcontrast%20themes.)[VSCode&lt;/a&gt; Microsoft Adaptive Card Previewer]&lt;/p&gt;

&lt;p&gt;To help us out a little, here is a basic Adaptive Card with a Single ChoiceSet Input, with it waiting for you to type in some choices:&lt;br&gt;
&lt;code&gt;`&lt;br&gt;
{&lt;br&gt;
    "type": "AdaptiveCard",&lt;br&gt;
    "body": [&lt;br&gt;
        {&lt;br&gt;
            "type": "Input.ChoiceSet",&lt;br&gt;
            "choices": [&lt;br&gt;
                {&lt;br&gt;
                    "title": "Choice 1",&lt;br&gt;
                    "value": "Choice 1"&lt;br&gt;
                },&lt;br&gt;
                {&lt;br&gt;
                    "title": "Choice 2",&lt;br&gt;
                    "value": "Choice 2"&lt;br&gt;
                }&lt;br&gt;
            ],&lt;br&gt;
            "placeholder": "Placeholder text"&lt;br&gt;
        }&lt;br&gt;
    ],&lt;br&gt;
    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",&lt;br&gt;
    "version": "1.5"&lt;br&gt;
}&lt;br&gt;
`&lt;/code&gt;&lt;br&gt;
Now to make this work with the Data passed over from our varObject Variable in Power Automate.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First Remove the "choices" array - the &lt;strong&gt;[&lt;/strong&gt; to the &lt;strong&gt;]&lt;/strong&gt; and replace this with a reference to our Countries list in varObject, like this:
&lt;code&gt;`
"choices": @{variables('varObject')?['Countries']},
`&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Then we can add the Country value that was selected in the Power App Form, by adding this (The ? operator is only needed for handling null values.):
&lt;code&gt;`
"value": "@{variables('varObject')?['Country']}"
`&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Then  we need to add an ID for the field.
&lt;code&gt;`
"id": "Country",
`&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;And for reasons I don't understand we need to change the version from 1.5 to 1.4 to work with Teams version 1.7?!?&lt;code&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;
"version": "1.4"
}
&lt;code&gt;&lt;/code&gt;`&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Power Automate
&lt;/h2&gt;

&lt;p&gt;We then have an Adaptive Card that we can paste in to the Message in Power Automate.&lt;br&gt;
&lt;code&gt;`&lt;br&gt;
{&lt;br&gt;
    "type": "AdaptiveCard",&lt;br&gt;
    "body": [&lt;br&gt;
        {&lt;br&gt;
            "type": "Input.ChoiceSet",&lt;br&gt;
            "choices": @{variables('varObject')?['Countries']},&lt;br&gt;
            "placeholder": "Placeholder text",&lt;br&gt;
            "id": "Country",&lt;br&gt;
            "value": "@{variables('varObject')?['Country']}"&lt;br&gt;
        }&lt;br&gt;
    ],&lt;br&gt;
    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",&lt;br&gt;
    "version": "1.4"&lt;br&gt;
}&lt;br&gt;
`&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Save the Flow and Refresh the Flow in the Power App too. If you get &lt;br&gt;
"&lt;em&gt;[proxy]-ObjectFlow.Run failed: { "code":&lt;br&gt;
"InvokerConnectionOverrideFailed", "message": "Failed to parse invoker connections from trigger 'manual' outputs. Exception: Could not find any valid connection for connection reference name&lt;br&gt;
'shared_teams' in APIM header." }&lt;/em&gt;" Just Save and Re-Open the Power App 🙂.&lt;/p&gt;

&lt;h2&gt;
  
  
  Teams
&lt;/h2&gt;

&lt;p&gt;Submit the Form in the Power Apps and Teams should now send you a message with the Selected Country and when you select the Choices, give you a selection of other Countries.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk88ompzkx2pi4qpjp0lv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk88ompzkx2pi4qpjp0lv.png" alt="Teams - Selected Country"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faiyw79dssrxm3tihzt3f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faiyw79dssrxm3tihzt3f.png" alt="Teams - Countries"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Hopefully this is a helpful tip and I will elaborate on how we can get more in to Adaptive Cards soon.&lt;br&gt;
Please leave any questions or comments below.&lt;/p&gt;

</description>
      <category>powerapps</category>
      <category>powerautomate</category>
      <category>powerplatform</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Passing Objects from Power Apps to Power Automate</title>
      <dc:creator>Matthew Collinge</dc:creator>
      <pubDate>Wed, 10 Jan 2024 16:14:33 +0000</pubDate>
      <link>https://dev.to/mcombp/passing-objects-from-power-apps-to-power-automate-31ji</link>
      <guid>https://dev.to/mcombp/passing-objects-from-power-apps-to-power-automate-31ji</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;This is the first part, in what I hope will be a series of posts describing how to trigger an advanced approval process. Starting with Power Apps capturing data in a Form and then passing that as a JSON Object or "Record". &lt;/p&gt;

&lt;p&gt;We are passing a JavaScript object as a JSON string from Power Automate to Power Automate. Power Automate has many actions and expressions available to allow us to reference and manipulate the Object once it has been received. More on that later.&lt;/p&gt;

&lt;p&gt;I have chosen to implement a JSON Object as it is a common method to store and exchange data. The benefits are that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Power Apps code is simpler with all the fields being referenced the once when creating the Object.&lt;/li&gt;
&lt;li&gt;Power Automate is kept more efficient than initiating a Variable for each field value passed&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Power App
&lt;/h2&gt;

&lt;p&gt;Firstly we need a Power App where we will capture the values in a Form filled in by a user. The Form I have created is just a bunch of Text Input controls. We are going to capture these as a Record into an Object Variable using the Button Control OnSelect property.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0hwq7jrwecinx0f96epb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0hwq7jrwecinx0f96epb.jpg" alt="Power Apps - Form"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To begin this Function we need to start with this in in the Button's OnSelect Property:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Set(
    varObject,
    {


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then we can start building the object inside the record (curly brackets). each Field needs a unique name with no spaces. Make sure to make sure to reference the '.Text' Property of the Text Input control, it is quite strict on that.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Set(
    varObject,
    {
        Name: txt_Name.Text,
        Address_1: txt_Address_1.Text,
        Address_2: txt_Address_2.Text,
        City: txt_City.Text,
        Country: cbx_Country.Selected.Value,
        Mortgaged: tgl_Mortgaged.Value,
        Rating: rtg_Rating.Value
    }
);


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Power Automate
&lt;/h2&gt;

&lt;p&gt;We can now create a Flow ready to receive this Object. We can do this from inside Power Apps or Externally, just make sure that they are both inside the same Solution.&lt;/p&gt;

&lt;p&gt;We'll call this &lt;strong&gt;[proxy] - Object Flow&lt;/strong&gt; and add a Text Input to the Trigger. As there's no JSON Input option available, we will have to convert the record variable into a JSON text string inside the Power App to allow us to capture it here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7xeth9hnfq5400znvxqp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7xeth9hnfq5400znvxqp.jpg" alt="Power Automate - Create Flow with Trigger"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The only action we need so far is &lt;strong&gt;Initialize variable&lt;/strong&gt; this is where varObject can be converted back into a JSON Object like this by placing it inside 'json()'.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

json(triggerBody()?['text'])


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fva85k2lfr2pxol1niyzj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fva85k2lfr2pxol1niyzj.jpg" alt="Power Automate - Initialize Object Variable"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Power App
&lt;/h2&gt;

&lt;p&gt;Ok, so back to the Power App. To make sure to Refresh the Flow from the Power Automate section of Power Apps, this will just ensure that the Flow is up to date and ready to receive the Text Input.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzdv40zgno4ivpu2pmn0p.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzdv40zgno4ivpu2pmn0p.jpg" alt="Power Apps - Refresh Flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Back in the Button's OnSelect Property and underneath where we set the Variable varObject, we can now send it to the Flow, but inside a 'JSON()'.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

'[proxy]-ObjectFlow'.Run(
    JSON(
        varObject
    )
)


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa9hjt07vlu3mv0j60xpt.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa9hjt07vlu3mv0j60xpt.jpg" alt="Power Apps - Button OnSelect"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;Now enter some test values in the Form and click on the Button, which should now trigger the Flow and pass the Object over from the App for us.&lt;/p&gt;

&lt;p&gt;Now we have an Object ready inside our Flow that we can use to extract data from. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz89kpyini064n98f4n71.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz89kpyini064n98f4n71.jpg" alt="Power Automate - Object Received"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each time we need a value we can reference it by using ```&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;variables('varObject')?['____']&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The ? operator is only needed for handling null values.

For example:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;variables('varObject')?['Name']&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
![Power Automate - Name Property](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dgplwz8ylh9vye0zggux.jpg)

## Summary
Now we have a way to pass a record between Power Apps and Power Automate there are a few useful tricks that I will add soon. We will cover how we can bring over the alternative values for next....
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>powerautomate</category>
      <category>powerapps</category>
      <category>powerplatform</category>
    </item>
    <item>
      <title>Send Multiple files as email attachments from a SharePoint Document Library Folder using Power Automate 📂➡️📨</title>
      <dc:creator>Matthew Collinge</dc:creator>
      <pubDate>Sat, 12 Aug 2023 14:02:47 +0000</pubDate>
      <link>https://dev.to/mcombp/send-multiple-files-as-email-attachments-from-a-sharepoint-document-library-folder-using-power-automate-2k1j</link>
      <guid>https://dev.to/mcombp/send-multiple-files-as-email-attachments-from-a-sharepoint-document-library-folder-using-power-automate-2k1j</guid>
      <description>&lt;p&gt;Have you ever needed to email multiple specific files as attachments from a SharePoint Document Library? There is documentation on how to send ALL the files in a given folder (&lt;a href="https://learn.microsoft.com/en-us/microsoft-365/community/power-automate-send-sharepoint-files-as-attachments" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/microsoft-365/community/power-automate-send-sharepoint-files-as-attachments&lt;/a&gt;), but here we'd like to have some control over which files we want to email as attachments without having download the files beforehand.&lt;/p&gt;

&lt;h2&gt;
  
  
  User interaction
&lt;/h2&gt;

&lt;p&gt;The previously mentioned documentation provides us with a good Power Automate solution to build from, but how do we include the interaction that allows the user to see the available files to pick from and to select just the files they'd like to email? Well, that's where Adaptive Cards for Teams comes in. Adaptive Cards let us build an interactive and dynamic structure for a user interface for the actions of a Power Automate Flow.&lt;/p&gt;

&lt;p&gt;NOTE: I'd love to develop a way to open up a new email tab with Outlook for the Web to do this, or even a PWA that's opens up in the SharePoint Sidebar... maybe one day.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Power Automate process in summary
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Flow is triggered by the "For a selected file" trigger.&lt;/li&gt;
&lt;li&gt;Flow will locate the parent folder&lt;/li&gt;
&lt;li&gt;Flow will collect all the files&lt;/li&gt;
&lt;li&gt;Flow will add the files to an attachment names string&lt;/li&gt;
&lt;li&gt;An Adaptive Card will be sent to the user that Triggered the Flow&lt;/li&gt;
&lt;li&gt;The Adaptive Card will replicate the layout of an email, with Sent To, Subject, Body and a pick list using the attachments array&lt;/li&gt;
&lt;li&gt;The user fills out the fields, selects the files and clicks send.&lt;/li&gt;
&lt;li&gt;For each of the selected files the Flow will retrieve the file content and Append to an Array.&lt;/li&gt;
&lt;li&gt;Email is sent with selected Attachments&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How the flow works
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;The user can trigger the Flow by selecting a single file in a SharePoint Document Library and clicking on &lt;strong&gt;Automate &amp;gt; Send Attachments&lt;/strong&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkcy72mg6vfw33qizsotx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkcy72mg6vfw33qizsotx.png" alt="Flow Trigger - For Selected File"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;They are then then asked to &lt;strong&gt;\"Run Flow\"&lt;/strong&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An Adaptive Card is sent to them via the Microsoft Teams Flow Bot where the user can input the &lt;strong&gt;Receipient Email&lt;/strong&gt; (with Regex Validation), &lt;strong&gt;Subject&lt;/strong&gt;, &lt;strong&gt;Body&lt;/strong&gt; and a Dynamic Picklist of all the other files in the chosen folder. 😃 &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once the user clicks &lt;strong&gt;\"Send\"&lt;/strong&gt; the flow will verify that they actually selected any attachments and if so, send the email with the selected attachments via email from the user's mailbox.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How it is Built
&lt;/h2&gt;

&lt;h2&gt;
  
  
  For a selected item
&lt;/h2&gt;

&lt;p&gt;To start building the Flow for a given SharePoint Document Library, you need to start from that Library and then select &lt;em&gt;Integrate &amp;gt; Power Automate &amp;gt; Create a Flow&lt;/em&gt; then we can select a Template "&lt;strong&gt;Request approval in Microsoft Teams when a SharePoint item is created&lt;/strong&gt;". We're going to remove all the actions from this apart from the trigger.&lt;br&gt;
Doing this creates the relationship between the Document Library and the 'For a Selected Item' Flow Trigger. For some reason, if you don't create the Flow this way, the Document Library refuses to show the Flow under "Automate", which is very frustrating. 😩&lt;/p&gt;

&lt;h2&gt;
  
  
  Variables to Initialise
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;varUserEmail&lt;/li&gt;
&lt;li&gt;varFolderPath &lt;/li&gt;
&lt;li&gt;varAttachmentNames &lt;/li&gt;
&lt;li&gt;varAttachmentNamesArray
&lt;/li&gt;
&lt;li&gt;varSelectedArray&lt;/li&gt;
&lt;li&gt;BodyAsString&lt;/li&gt;
&lt;li&gt;varCardObject&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;varSiteLibrary&lt;/strong&gt; is an Object where I have set up the SharePoint Site and Document Library&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "Site": "&amp;lt;SharePoint Site&amp;gt;",
    "Library": "&amp;lt;Document Library&amp;gt;"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We can retreive these in our various actions just by referencing &lt;strong&gt;variables('varSiteLibrary')['Site']&lt;/strong&gt; or &lt;strong&gt;variables('varSiteLibrary')['Site']&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Get parent - the folder's path
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqceqqsa221ghm3qkxlae.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqceqqsa221ghm3qkxlae.png" alt="Set varFolderPath"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's the expression used to return the Folder Path without the '/' at the end, so we can use it in the next action.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

substring(
    outputs('Get_file_properties_-_Folder')?['body/{Path}']
    ,0
    ,sub(
        length(outputs('Get_file_properties_-_Folder')?['body/{Path}']))
    ,1
)


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Get an Array of all the available files in this folder
&lt;/h2&gt;

&lt;p&gt;Using \"Get files (properties only)\" and the Filter Query: &lt;strong&gt;FSObjType eq 0&lt;/strong&gt; to return just the files and not folders. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faf2qf7p516y16itk64ds.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faf2qf7p516y16itk64ds.png" alt="Get files (properties only)"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we use \"Apply to Each\" for each value (file) found.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F20z37o5ufrn5nz0w3nno.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F20z37o5ufrn5nz0w3nno.png" alt="Apply to Each"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each value is run through the "Get File Content" action to then append it's File name with extension and a unique Identifier.&lt;br&gt;
Adaptive cards need to have a unique ID for each property, so I have used the Identifier property.&lt;/p&gt;
&lt;h3&gt;
  
  
  Append to String varAttachmentNames schema:
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Input.Toggle"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@{items('Apply_to_each')?['{FilenameWithExtension}']}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Item_@{items('Apply_to_each')?['{Identifier}']}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  In Parallel Append to String &lt;strong&gt;varAttachmentNamesArray&lt;/strong&gt; schema (we will need this later to get the File Names):
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"FileName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@{items('Apply_to_each')?['{FilenameWithExtension}']}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Identifier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@{items('Apply_to_each')?['{Identifier}']}"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Post adaptive card and wait for a response
&lt;/h2&gt;

&lt;p&gt;The full build of the Adaptive card is &lt;a href="https://github.com/madmat01/devtoBlog/blob/main/Adaptive_Card.json" rel="noopener noreferrer"&gt;here&lt;/a&gt;, but the key bit here is to include the varAttachments as a dynamic repeatable item within the Card. To do this we can place varAttachments inside of &lt;strong&gt;"items": [ ]&lt;/strong&gt; , so that each filename is shown with it's own Input Toggle.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq78563ri2trvnj5uwneg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq78563ri2trvnj5uwneg.png" alt="Array inside Adaptive Card"&gt;&lt;/a&gt;&lt;br&gt;
We replace this with our varAttachmentNames String&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Container"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
               &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;variables('varAttachmentNames')&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Parse the Adaptive Card response
&lt;/h2&gt;

&lt;p&gt;Now the fun part, doing something with all the data we've gathered.&lt;br&gt;
To do this we need to Parse the JSON from the \"Data\" Property of the Adaptive Card Body.&lt;/p&gt;

&lt;p&gt;The Card body used here is in the form of this expression. We will set this as &lt;strong&gt;varCardObject&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

body('Post_adaptive_card_and_wait_for_a_response')['data']


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We will set this as &lt;strong&gt;\"varCardObject\"&lt;/strong&gt; and use is in the Content for the Parse JSON action.&lt;br&gt;
 &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1p8i7zuzjgryv2eb6f5g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1p8i7zuzjgryv2eb6f5g.png" alt="Parse JSON"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JSON Schema used&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"RecEmail"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Subject"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"EmailBody"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Item_"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Parsing this Data Object will allow us to extract the &lt;strong&gt;RecEmail&lt;/strong&gt;, &lt;strong&gt;Subject&lt;/strong&gt; and &lt;strong&gt;EmailBody&lt;/strong&gt; for use in the Send Email Action later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extracting the selected files
&lt;/h3&gt;

&lt;p&gt;A challenging part of this process is extracting the list of just the Selected Files from the Adaptive Card. We only want to get the ones that have the Toggle set to \"True\".&lt;/p&gt;

&lt;p&gt;To do this we'll need to convert the &lt;strong&gt;varCardObject&lt;/strong&gt; in to a String so that we can split it using an expression.&lt;/p&gt;

&lt;p&gt;Set the &lt;strong&gt;\"BodyAsString\"&lt;/strong&gt; variable the the &lt;strong&gt;\"Parse JSON Body\"&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Then bring that into a Compose action to use a &lt;strong&gt;Split&lt;/strong&gt; expression.&lt;br&gt;
 &lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhygdk94td7vjtooq4m73.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhygdk94td7vjtooq4m73.png" alt="Split Card Object String"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Compose - Split
&lt;/h3&gt;

&lt;p&gt;We will split the string at each &lt;strong&gt;_item&lt;/strong&gt; &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Split(variables('BodyAsString'),'Item_')


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Apply to Each Split Item
&lt;/h3&gt;

&lt;p&gt;In order to return just the selected (True) files we need to do an Apply to Each on the Output of &lt;strong&gt;Compose - Split&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq7wid06gpugrvvef30ah.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq7wid06gpugrvvef30ah.png" alt="Apply to Each Split Item"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Condition
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;CurrentItem&lt;/strong&gt; Contains:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

":"True"   


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Append to array variable - varSelectedArray
&lt;/h3&gt;

&lt;p&gt;With each Current Item that matches the Condition we will Append it to our &lt;strong&gt;varSelectedArray&lt;/strong&gt; and apply an expression to just give us just the File Identifier that we need. To do that we will use the expression: &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

replace(
    replace(
        items('Apply_to_each_-_Split_Item'),
        '":"True","',''
        )
        ,'":"True"}',''
    )


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Failover - No Attachments have been selected
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Forluwcayizht7inb6xju.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Forluwcayizht7inb6xju.png" alt="Has Attachments Condition"&gt;&lt;/a&gt;&lt;br&gt;
In case the user forgets to actually select any attachments we can add a failover that checks the number of attachments &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

length(variables('varSelectedArray'))


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;is or greater than 1. If the Condition is not matched, then we will send the User a Teams message \"No attachments were selected, please try sending this again\". Then the Flow will be Terminated&lt;/p&gt;

&lt;h2&gt;
  
  
  Get the File Content and prepare attachments for each of the files
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Apply to Each - Selected File
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2wadfz84aa1uzx8h5gn4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2wadfz84aa1uzx8h5gn4.png" alt="Apply to Each Selected File"&gt;&lt;/a&gt;&lt;br&gt;
To give us an Array of Attachments that Outlook can send in an email we need to find two things for each selected file: The File Name with Extension and the ContentBytes.&lt;/p&gt;

&lt;p&gt;To acheive this we can run two actions in Parallel for each item from the &lt;strong&gt;varSelectedArray&lt;/strong&gt; which has a list of file identifiers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Filter array - for Identifier
&lt;/h3&gt;

&lt;p&gt;From: &lt;strong&gt;varAttachmentNamesArray&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;item().Identifier&lt;/strong&gt; is equal to &lt;strong&gt;Current Item&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Advanced mode:&lt;/em&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

@equals(item().Identifier, items('Apply_to_each_-_Selected_File'))


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Using the expression below this can return us the matching FileName for the File Identifier&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;p&gt;first(body('Filter_array_-_for_Identifier'))?['FileName']&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Get file content - Each File&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;Search the Site Address for the Current Item (file identifier) to return the File Content.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

&lt;p&gt;@{body('Get_file_content_-_Each_File')}&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Append to array variable - AttachmentsArray&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;So, to join these two together we Append each of these to the &lt;strong&gt;AttachmentsArray&lt;/strong&gt; variable like this:&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&lt;br&gt;
 json&lt;br&gt;
{&lt;br&gt;
  "Name": @{first(body('Filter_array_-&lt;em&gt;for_Identifier'))?['FileName']},&lt;br&gt;
  "ContentBytes": @{body('Get_file_content&lt;/em&gt;-_Each_File')}&lt;br&gt;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Send an email&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;We can now use the data we've gathered above to compose and send an email.&lt;/p&gt;

&lt;p&gt;An important point to mention is that to add the AttchmentsArray we need to select the &lt;strong&gt;\"Switch to input entire array\"&lt;/strong&gt; toggle so that we can insert the combined Name and Content that we put together in &lt;strong&gt;AttachmentsArray&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqs4k78g3zc3ndk2bvtgp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqs4k78g3zc3ndk2bvtgp.png" alt="Send an Email"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>powerautomate</category>
      <category>powerplatform</category>
      <category>sharepoint</category>
      <category>adaptivecards</category>
    </item>
  </channel>
</rss>
