The simplest No-Code Solution to Save Picture Files from PowerApps to Flow

pexels-photo-1028624.jpg

Today, we are going to talk about a new technique (hack) to send any pictures from PowerApps to Flow.

We will do this with a modified Flow Button trigger.


Update 2019-04 Save Picture Files from PowerApps to Flow via unused Outlook Connector

I’ve came up with an EVEN EASIER hack that you should check out. The 2019 April method is the best one so far.

http://johnliu.net/blog/2019/4/flowninja-hack-87-lock-microsoft-flow-powerapps-trigger-to-upload-images-to-sharepoint-with-ease

Update 2019-03 there’s some JSON definition changes to the PowerApps trigger. See note below.

Update 2019-01 - I did a YouTube recording of this blog post

Quite possibly the easiest way to let us upload an image from PowerApps into SharePoint - from the Add Pictures control (not the low res camera control). Without having to write a custom connection. By hacking a Flow Button into a PowerApps trigger.

Why John, what is the problem? 

Why do you repeatedly write the same post?

The problem is that we want to use PowerApps to collect binary files (mainly images, but also documents, video, anything) and send them to Flow - Flow can then decide where to send the pictures.  To SharePoint, to Email, to Cognitive Services etc.

This is a problem that isn't out of box, and has several good workarounds - some choices more difficult (or limited) than others.

 

What have we got so far?

This is the first method - we can send PowerApps' Camera to Flow via a built in dataUriToBinary() expression.  But it doesn't work for Add Picture from device gallery.  We also can't use this method for sending files - documents, zip, sound, movie clips.

This method lets us use Add Picture from gallery and we can send any binary file formats.  But the input parameter is specialized multipart formdata bytes, so this method needs a Custom Connection (need a Swagger definition file) to work with PowerApps.

 

What is this new method?

We are going to take a Flow Button and hack it into a PowerApps trigger to send Files from PowerApps to Flow.

It will be magical.  Because there will be no Swagger.

 

1. Build a Button-triggered Flow

We start with a Flow Button trigger - which lets us specify which parameters we want as part of the button click.  Flow Button let us select File.

Create FileName and FileContent compose actions to extract the value from the File trigger parameter.  Then use SharePoint's create file to create this file.

Test this Flow - upload a picture of LEGO 10234 - success.

 

2. Examine this Flow Button trigger and switch it to a PowerApps trigger.

Next, we need to check the Flow button trigger and convert it to a PowerApps trigger.

This can be done via Exporting the Flow, open up the export in ZIP file, and change the JSON definition of the trigger.manual.kind from "Button" to "PowerApp".  But here I'm using a simpler way by opening the Flow using Flow Studio's Edit Flow JSON capability.

Try it: https://flow-studio.azurewebsites.net/welcome

Save the changed definition and this is now a PowerApp trigger.

Note: Have a look at the JSON schema generated for the Flow Button's file trigger parameter.  We'll need to know this later.

 

3. Build our PowerApp

Note - this is the Add Picture control.  Not the camera control.

Because our Flow is now a PowerApps trigger - it appears in the available list without us having to build a Swagger file.

The parameters needed is { file: { name: "x", contentBytes: ... }} 
This matches what Flow Button wants for a file upload.

 

4. That's it.  Done.

Run the PowerApps to test.

And the result - LEGO 851400 cup is uploaded to SharePoint via Binary.  No Swagger.

 

Future thoughts

Eventually, I hope we have a way to officially define the input parameters we want to use in a PowerApps trigger.  The way it currently works is awkward.  It should just use the same way that the Flow Button trigger works.

Until that day - this method is possibly the simplest way to send any binary files from PowerApps to Flow.  Because this method doesn't need custom connections - you might find this useful in not hitting your Flow plan limit of 1 custom connection.

Underneath the hood though, a Flow Button trigger is the same as a PowerApps trigger (they are both HTTP Request Triggers).

 

Download File:

https://github.com/johnnliu/flow/blob/master/FlowNinja-SendFileToFlow_20180728000358.zip

 

Bonus Exercises:

  • Create multiple files first in Flow Button before converting to PowerApps trigger.

  • In the definition, made some (but not all) of the file parameters required

 

Update: adding additional arguments

The converted PowerApps trigger works, but you may find it troublesome to edit the Flow after it was changed.  And attempts to use Ask Parameter in PowerApp Trigger within the Flow Designer will cause the PowerApp trigger to be regenerated, potentially breaking the file argument.

Instead, do this.  First make sure it is a Button trigger again.  

Then, create multiple arguments with the Flow Button

Note the two new arguments have very boring names text and text_1

Note the two new string arguments in addition to the file JSON record object.
Result:

 

2019-03 update

  1. When editing the Button trigger to Powerapp do:

    Change Button to Powerapp
    Rename variables to nicer ones file1 and file2 - rather than file and file_1
    fix up references within the Flow to point to triggerBody()?[‘file1’]?[‘name’] and triggerBody()?[‘file1’]?]’contentBytes’]

  2. In PowerApps - call Flow method with two files

  3. See result

Flow For-Selected-Item trigger and SharePoint Site Pages, in a detective story

This is a long blog post, there are two parts:

  1. How do you make a SharePoint For Selected Item in Flow, and have it appear on the SharePoint Site Pages library
  2. Explain the magic rituals you just did to figure all this out

The Problem

Paul Matthews reached out and asked if it's possible to create a "For a selected item" Flow against Site Pages.  

I was able to reproduce what he's asking fairly quickly.

 

The Solution

May be you just want the solution.  The solution is that you need to use the "list guid" as the custom value for the SharePoint For Selected Item trigger, not the List Title.

 

The Detective Novella

Ah you are still here.  OK, buckle yourself in, we are going another Flow adventure.

First, when realizing that the For a Selected Item doesn't appear in Site Pages, I immediately call the SharePoint REST method SyncFlowInstances()

I do this of course, with another Flow.

This returns empty array for SynchronizationData.  This means:

SharePoint Site Pages don't know anything about my Flow.  It thinks there's no Flow connected to it.

Create an Out of Box Request sign-off Flow on Site Pages

SyncFlowInstances returns this Request sign-off Flow

So we know Flow can run on the Site Pages library, just not "Our" Flow.

I want to compare the JSON definition differences.

The Request sign-off Flow is owned by the SharePoint list, not by me.  So I can't read its definitions (I can't even see it in my list of Flows view)

So I created a Flow to assign the Request sign-off Flow to me.

This is necessary to add myself as a Owner to this Flow.

Now I open these two Flows with Flow Studio.

I can see both the working Flow (on the left) and the not-working Flow (on the right)

https://flow-studio.azurewebsites.net/

Checking the trigger JSON, I find that the Flow on the right (not working) has "Site Pages" as the name, but on the left (working) has a GUID as its name.

Summary

We explained the problem - it is the Site Pages not appearing as a choice - it's not a List nor a base Document Library.  Typing the name "Site Pages" doesn't work.

The solution is to use the list Guid.

And the debugging steps takes us to SyncFlowInstances, Modify FLow as Admin to assign a new template flow back to me as the owner, and finally using Flow Studio to change the existing "Site Pages" to the list guid.

 

 

 

Office 365 Saturday Canberra 2018 #O365CBR #SPSCBR

This Saturday - 14 July, we'll be converging on SharePoint and Office 365 Saturday Canberra.  I'm planning to take my time and drive down for the weekend.

028Canberra0021.jpg

https://www.meetup.com/en-AU/O365-Saturday/events/252110689/ 

The event is held at Microsoft office this time (so not at the previous Clifton's venue).  We will be covering a mix of Office 365, modern SharePoint, and security topics.

I'll be around all day as well - ask me anything about SharePoint, Flow, PowerApps, Office Development, Todo, Xbox and everything!

I believe we have an Xbox One and a bunch of swag to give away too!  But you are definitely coming for the wide range of content and topics, and definitely not for the swag.

We hope to see you there!

 

10 Things in Microsoft Flow that isn't in Azure Logic Apps

Sorry about the catchy headline.  I will start by saying I am perfectly ready to see a response post containing 20 things in Azure Logic Apps that we wish are in Microsoft Flow.  The point of this post isn't about whether one product is better than another product, it is simply to highlight the very-intentional design differences and how as users we have access to both and should make our choice accordingly.

If a comparison must be made, then I think in reality, they are better seen as two siblings - LogicApps is the big sibling with more features, Flow piggybacks LogicApps, but itself has several unique tricks and sometimes, features do move between them.  I love both teams & products.

To best describe Flow to an Azure / Logic Apps person, Flow is Logic Apps + power-user / human workflow-focused workloads, combined with a mobile experience and better in-product integration.  As a result, it caters to a whole different set of scenarios that Logic Apps isn't focused on.

 

1. Resource-Owned Flows

Flows can have multiple owners, but it can also have a Resource as a owner.  The best example of this is in SharePoint connector.  A Flow can be 'owned' by the List or Library resource - so if we grant a user library owner permissions - that user automatically can see and modify the Flows owned by the resource.  This is awesome because we don't need to manage two sets of user ownership sets.

 

https://flow.microsoft.com/en-us/blog/share-with-sharepoint-office-365/


2. Run-as user

Several Flow connectors has a concept of the Run-As user, that is, the user can select a resource like a document or a library, and run the Flow as the current user.

LogicApps connectors can only run as the maker.

3. Approvals

Flow implements a simple set of approvals API with both one-must-approve as well as everyone-must-approve, this is setup with Office 365's Actionable Messages, so tasks can be completed directly from email.  These are also available within the Flow Mobile app.  These approval tasks can be reassigned, and there is a history trail of them in Flow.

In LogicApps - human approvals can be built Outlook's Send Approval Email.

https://flow.microsoft.com/en-us/blog/introducing-modern-approvals/ 
 

 

 

 


4. Notifications

Flow can send Mobile Notifications to the accompanying Flow mobile app.  

https://docs.microsoft.com/en-us/flow/guided-learning/build-flows?tutorial-step=2#step-2

5. Flow Buttons

Flow has digital buttons called "Flow Buttons" these appear as quick triggers on the Flow Mobile App, but is also a really easy way to set up a run-now test trigger.

https://flow.microsoft.com/en-us/blog/button-file-inputs/

6. PowerApps Trigger

Flow has a PowerApps trigger (and response) that can send structured JSON data to and from PowerApps.  This makes it much easier to use Flow as server-side middleware to extend PowerApps (which is client-side).

LogicApps has to publish custom connector (which can then be used in Flow and PowerApps).

 


7. Environments

Flows are created and grouped within Environments - an environment can have unique assets grouped, as well as shared custom connectors, and data leak prevention policies.

Logic Apps are grouped within subscriptions - you either have access to the subscription or you don't.

8. Selected-Row Trigger

Selected Row is part of the product integration feature of Flow - in which, Flow can be created and ran from within other products as part of an integrated experience.

Two examples we have right now are in SharePoint and (soon) in Excel.
On the roadmap there is also Outlook integration.

This trigger is specific in that in each of these integrated experiences, you can select an existing item (in SharePoint list, in Excel row, or in an email) and start a Flow with that item as the source trigger.  Additionally, Flow can run as the current user (see #2) as part of this integration.

https://flow.microsoft.com/en-us/blog/spring-2018-update/


9. Analytics

Flow has several builtin analytics charts out of box with PowerBI.

Logic Apps has Log Analytics integration and users can build their analytics via Insights.

 

 

 

 


10. Flow Management Connector

In Flow, the Flow Management Connector is a meta-level connector that lets you perform reflection-like actions on the Flows within your current environment.  You can even use Flow to make other Flows.

Somewhere, there is an insane Flow engineer that says wouldn't it be ultra-meta to deploy Flows with Flow.

Logic App's Logic Apps connector only lets you list other Logic Apps in the current subscription and run them.  To deploy LogicApps - talk to Azure Management API to deploy ARM templates.

I use this connector quite often to move Flows around:

http://johnliu.net/blog/2017/12/you-must-copy-all-your-flows-to-sharepoint-simple-ideas-are-the-most-brilliant

http://johnliu.net/blog/2018/5/save-all-your-flows-to-vsts-via-http-rest-in-8-actions

Think about this.  Flow can read itself.  Flow can call Azure Machine Learning.  Flow can update itself.

Insane.


11. Business Process Flows

Business Process Flows replace the old Business Process workflow in Dynamic 365,  and is a way to build a "state machine" that triggers and transitions between different business process stages in Dynamics.

https://flow.microsoft.com/en-us/blog/spring-2018-update/

This integration with Dynamics platform isn't available in LogicApps.

(I included an 11th because some may be picky and say well #9 analytics isn't a special power...)


Example of a powerful Flow feature that made it's way back to LogicApps

12. Data Gateway

Flow as part of the Business Application Platform had on-premises integration through the Data Gateway functionality first - including calling on-premises SharePoint, SQL, File System and REST endpoints.

This feature was integrated back to LogicApps later as well.

https://flow.microsoft.com/en-us/blog/on-premise-apis/

I connect SharePoint to my Minecraft via the Data Gateway with a custom REST API.

http://johnliu.net/blog/2017/10/from-office-365-to-minecraft-connected-with-flow


Summary

Flow, Logic Apps, Azure Integration - these are a multi-headed effort to move expand in multiple directions, each under a specific product offering.

Specifically, Flow's special powers fall under these categories, some are easy - others not so easy to replicate back in Logic Apps.

  • Flow Mobile app
  • Approvals
  • App-Integrated Flow (SharePoint, Dynamics, Teams, Excel, Outlook)
  • BAP-Integration  (Environments, Data Gateway, PowerApps, PowerBI) 

In Dynamics and Office 365, because we get a generous pool of free Flow runs as part of the license, Microsoft Flow can be cheaper.  Flows cost per run.  So it encourages building long-running, multi-step Flows, suitable for human workflows.

But in my own experience - some of the Flows that I call a lot (but doesn't have too many actions), it's actually cheaper to switch those to Logic Apps.  I consider these Flows more like Middleware calls - HTTP Request, do a few actions, finish.

Also, in building Flow Studio that works across tenants - I've opted to use Logic Apps rather than use the Flow runs of a single Office 365 Tenant.

Different scenarios, for different needs.

How to get live FIFA Worldcup results via Microsoft Flow into your SharePoint Intranet WebPart

Github tweeted a link to a NPM NodeJS CLI project that uses data from http://football-data.org.  Seeing that, I decided we need to build a SharePoint Modern SPFx webpart so we can load it into all our Intranets.

Plan

  • Use Microsoft Flow to call the football-data API
  • A Thesis in Microsoft Flow's Parse JSON action
  • Format the data and write it into a HTML segment in SharePoint
  • Build a simple SPFx webpart that will load the HTML segment into the DOM
  • Future: Using Events API
  • Future: Using API Key
  • Downloads

Use Microsoft Flow to call the football-data API

We want to build this:

First let's look at the data source API.

That's nice - we don't need to figure out which competition is the 2018 World Cup.  It's 467.

http://api.football-data.org/v1/competitions/467

We want the game fixtures though, so we will call

http://api.football-data.org/v1/competitions/467/fixtures

(from http://api.football-data.org/documentation )

 

A Thesis in Microsoft Flow's Parse JSON action

To make the Select Operation Easier, we have two choices:

  • "type the expressions manually" or
  • "configure Parse JSON to make our lives easier"

Parse JSON is a detailed exercise that requires a full post by itself, since it requires description of various problems that we'll see, and how to get around them.  The Parse JSON step is the next blog post.

http://johnliu.net/blog/2018/6/a-thesis-on-the-parse-json-action-in-microsoft-flow

 

Format the data and write it into a HTML segment in SharePoint

If we skipped Parse JSON - then we'll need to manually type out the expressions.

We are selecting From:

body('HTTP'_world-cup-fixtures')?['fixtures']

And we need the properties:

date: convertFromUtc(item()?['date'], 'AUS Eastern Standard Time')
Day: item()['matchday']
Team 1: item()['homeTeamName']
Team 2: item()['awayTeamName']
Team 1 Goals: item()['result']['goalsHomeTeam']
Team 2 Goals: item()['result']['goalsAwayTeam']
Status: item()['status']
 

If we used Parse JSON - then the step to select the properties are easier.

 

We do the work in Parse JSON to describe what the types of the properties are - this allows the dynamic content pane to be more intelligent in showing us the appropriate choices.

Still have to type out the date conversion to local-time, unless you want UTC time.

We have our nice HTML table now.

flow-fifa-request-call.jpg

 

Build a simple SPFx webpart that will load the HTML segment into the DOM

For this step, I cheated and just used Mikael Svenson's wonderful Modern Script Editor webpart

Then I pasted in this code: 

<div id="fifa-games"></div>
<script>
window.fetch('/Shared%20Documents/fifa-2018-fixtures.html', {
  credentials: "same-origin"
}).then(function(response){
  return response.text();
}).then(function(text) {
  document.getElementById('fifa-games').innerHTML = text;
});
</script>

Basically, fetch the contents of the HTML from fifa-2018-fixtures.html and write that into DIV#fifa-games element.

You can also just use the old Content Editor webpart and use Content Link property to the file, but that doesn't work on the new modern pages.

Results

Works really well in Microsoft Teams too.

 

Future: Using Events API

football-data.org has an Events API where they will call our callback URL when a team scores in a game fixture.

http://api.football-data.org/event_api

This requires a first Flow to loop through all the Fixtures in the FIFA 2018 competition and set up an event call for each fixture.  Then when those games are played - if any goals are scored - we can call the same parent Flow to immediately update the result HTML table.

This implementation won't require a scheduled recurrence to refresh the data daily (or hourly).  It can be refreshed on-demand!

Future: Using API Key

When calling the football-data.org API without an API-Key, there is a max rate limit of 50 calls per day.  We can sort of see this in the response header (it goes down by 2 per execution).

Now because this is running from a Microsoft Flow server, I have no idea if your calls are rate-limited by the same IP address as someone else running this in your Azure Data Centre region.  So if you do see rate limit, it is better to register an API Key with an email address, and then add that to the HTTP Request Header.