2021-01-29

If you’re prone to losing paper copies of autographs (or indeed anything!), or wish to create an app that would allow you to combine images into a Word document, then here is a solution using a combination of PowerApps, Flow, SharePoint and Azure Functions that could be the answer to your problems. This demo uses the story of an autograph book, hopefully, you can see how this process can be slightly adapted to many other common scenarios.

It is worth pointing out at this point, that this example pulls together a number of different tools to achieve an end-to-end process. Whilst PowerApps is often described as a no-code/low-code tool, there are limits to what can be achieved without having to do small pieces of development. If, and when, you do meet those boundaries, you can easily pull on other resources to help provide the functionality which, at this time, may be lacking.

We’re going to use the following tools and processes to create and store the autograph book:

1) PowerApps: to take a photo and signature
2) Flow: to process the data obtained by the PowerApp
3) SharePoint: to store the data
4) Azure function: to combine the elements into a single document
5) SharePoint: to stored the final completed autograph book

Step 1. Use a PowerApp to capture images and autographs

The PowerApp contains a number of different screens, each of which moves the process on a stage at a time. Throughout the creation of the PowerApp, I’ve tried to promote some aspects of best practice which I always try to follow.

It’s always useful to create some standard screens in your apps to contain some basic information about the app itself. This means that, should someone else take over the maintenance/running of the app in the future, they have all the necessary documentation and explanation about how it all works for their future reference. These pages are not included within the navigation of the live app, however, when opened in PowerApps Studio an editor will be able to view the screens and read the documentation.

1) Governance – Documentation – An overview of the app and what it is intended to do, including any revisions which have taken place.
2) Governance – Collections – An explanation of the collections which are being used and the data being stored in them.
3) Governance – Styling – One method of being able to govern consistent styling where I have a number of controls governing colours etc. which are referenced by other controls in my app. This way, if I have to change a colour, I can do so just by updating the control on this screen.

Always name your components with meaningful descriptions, this makes it easier to identify your control when they appear in the Intellisense rather than trying to remember what Label1 and Label2 was. The format which I follow is:

Type_Screen_Description e.g. lbl_Home_Title

Home Screen

This screen is intended to be the first screen which the user sees when they load the app. The screen is comprised of a number of labels, images and icons to create the look and feel which I need.

The only piece of functionality required on this screen is to be able to navigate when we click on the icon next to “Get New Autograph”. The event which we are going to use is “OnSelect”, which is selectable within the property dropdown. I will use the “Navigate” function to navigate to the Autograph page using a fade transition.

Remember to use the help text with new formulas, the display provides hints to help you complete each section of the formula.

It’s a good idea to check your app works as intended as you develop it, this ensures that you don’t go too far off course at each stage and keeps you on track to create the functionality as intended. To test the app, click the “Run” button in the top left corner of your screen to Preview your progress so far.

In this case when clicking the “Get New Autograph Button” we should move to the next page, so we can enter the autograph details.

Autograph Screen

The purpose of the Autograph screen is to capture the name and autograph of someone within the PowerApp.

There are two types of text input control which I’m going to use on this page, both of which are available from the “Insert, Text” menu in PowerApps Studio.
First of all, I’m going to use a standard text box to capture the name of the person. This behaves exactly as you would expect from any standard text entry. You can type straight into it if you’re using a full browser, or you can use the virtual keyboard if you’re using a mobile device.
The second is the Pen Input control which, rather than taking a textual input, will allow me to sign, draw, scribble etc. within that area.

There are a number of user options associated with the pen control such as the ability to change the colour and thickness of the pen. As I want to only take a signature, in this case, I’ve removed the controls by toggling the “Show Controls” option to off. This is available in the properties blade on the right-hand side of the screen.

At the bottom of the autograph page, we have another navigate button to take us to the next stage to take a photograph.

Photograph Screen

This screen is dedicated to capturing the picture which I want to store along with my autograph.

Photographs can be captured by using the Camera control which can be found in the “Insert, Media” drop-down list.

Within this control, there are some really useful properties that can help us capture the photograph that we want. On the camera option, I’ve used a toggle control, which gives us a Boolean value and added a formula to the Camera property of the camera control to reference this toggle field. This will give the user the option to select which camera is being used, so for example on my phone, I can use the primary or secondary camera as needed.

There are a couple of ways you can trigger a photo caption within PowerApps. The first is by using the Camera Control and changing the OnSelect property to store the Photo by capturing cam_Photograph_Photograph.Photo. This property unfortunately can only be used directly on the camera control, which may not necessarily be the functionality you want.
The alternative is to add an icon and use that to capture the image. The thing to be aware of here is that the .Photo property can only be captured by interacting with the camera control. To use an external control to capture the photo we need to do two things. The first is to change the StreamRate property of the camera control. By default, it is 0, and I usually set it to 100. Then from our “take photo” control, we will call the Stream property e.g. cam_Photograph_Photograph.Stream.

Storing the data

There are numerous ways in which you can store data within a PowerApp, however for the purpose of this demonstration I’m going to use a Collection which will store an array of data within the app for as long as it remains running. Storing it in a collection means I can use the data in various ways across the app e.g. referencing it from other controls
There are two main formulas which are used for putting data into a Collection:
• Collect – each time this is called it will add a new entry into the collection
• ClearCollect – this will clear down any existing data within a collection and then add the new data into it. Using this method will only ever give you one item in the collection.
I am going to add the formula to save my data to a collection to the “OnSelect” property of my “take photo” button. As we only want one photo stored against each autograph we need to use “ClearCollect” (so if the first photo is not clear and you want to take another, the first one is deleted, leaving you with the final best shot to keep).

As well as the photograph, we also need to include the person’s name and also the signature so that we have all of the data we need to create the autograph book entry.
When creating a collection, it is important to ensure that you identify the elements in the collection or think of it as naming your columns. I would always follow this type of convention:
Collect(<Name of my Collection>, { FieldATitle: FieldAContent, FieldBTitle: FieldBContent}

In my case the formula is:
ClearCollect(MyAutographs,{Person: txt_Autograph_Name.Text, Autograph: pen_Autograph_Autograph.Image, Photograph: cam_Photograph_Photograph.Photo})
This will save the photo to the collection.

To review the collection, you can go to File, Collections, and then select the collection you want to view. In the example, we can see the penned signature, name of the person and their photograph.

Alternatively, I can use the View menu within PowerApps studio and select Collections from there.

Review Screen

The purpose of this screen is to review the data which has been collected over the previous screens. It will retrieve the data which we’ve stored within the collection and show it in a few controls.

I am using very simple controls such as a label to display the name, and image controls to display the photograph and autograph.
Each control just needs to pull out the first entry in the collection (as I have only one), and for that, I will use the keyword First.
The Image property of the photograph image control, therefore, would be “First(MyAutographs). Photograph” and the image will be displayed in the photo window. So effectively it is First(<Name of my Collection>).<Element of the Collection>.
Now that we have captured the data, we need to get it into a Word document. I can’t do this directly from PowerApps, so I’m going to use Microsoft Flow to process the data for me.

Step 2: Use Flow to process the data

When creating Flows, it’s a good idea to use “Try, Catch, Finally” as a pattern. This is something which developers use extensively to ensure that any errors are graciously handled. The same can be achieved in Flow by using Scopes and the Run-After configuration.
The actions of your Flow are placed into the Try phase, any errors are caught and handled in the Catch phase. E.g. if one of my actions failed, I want to email the IT Help Desk to raise a ticket for someone to investigate. This is a template which has been added to the Flow Templates gallery by Pieter Veenstra MVP, and is highly recommended pattern when adhering to best practices.

There are Triggers for PowerApps within Flow, and for the most part that will work with a lot of data. If I just wanted to take the photographing element from PowerApps and place it straight into my Flow, then I could use the PowerApps trigger. This is because what is passed from PowerApps is a fully encoded image file which Flow can quite happily accept and turn into a file using one of the many Create File actions (e.g. SharePoint, OneDrive etc).
The complexity with this example is that the image created by the Pen Input is not stored and passed as an image, it is passed as a URI. Therefore, I need to use a different trigger, the “When a HTTP request is received” which allows me to fully define the types for the data being passed to Flow. This type of trigger will generate a HTTP endpoint which I can use in a connector later to join PowerApps to Flow.
When you first create a HTTP request, the HTTP POST URL field will be blank. Upon your first save, it will generate the URL and populate this field in the trigger.

Within the Try, we will be extracting data from the Trigger using Data Compose actions. This will allow me to extract the exact data I need for each action e.g. I need to extract the person’s name, their photograph and their autograph.


For the purpose of showing how data can be passed through a HTTP call, I’m going to pass the person’s name through the query string, and the files through the http body.
The first compose, for the person’s name, will use an expression to parse the query string and identify the person’s name. Expressions can take a bit of time to get your head around, but once you have got the hang of them, they can be quite powerful. The expression for extracting the person’s name will be:
trigger()[‘outputs’][‘queries’][‘person’]
So, if I look at the output of the trigger, it will have a JSON string which contains a section titled queries, and within that, there will be a person. So for example if I pass ?person=Matt on the query string, then the output of this action will be “Matt”.
I’m going to tell Flow that the images for the autograph and photograph are going to be passed through as files, therefore they will be passed as multi-part form data. Therefore, the compose actions for both Autograph and Photograph will use the expression “triggerMultipartBody” and then a value e.g. 0 or 1 depending on the order of things I’ve been sent through. They get passed through as an array of items, therefore it will start at index 0.

The outputs of the compose actions for the Photograph and the Autograph will be a base64 encoded string of the images, which means that I can now happily store them in SharePoint using the Create File action. I will simply use the output of the “person” action in the title, so I will create a file called “Matt-Autograph.jpg” and then the output of the relevant compose action to get the pictures will be used within the File Content.


The next stage within the Flow, once I’ve saved the constituent parts within SharePoint, is to call an Azure Function to take everything and combine it into a Word Document. For this, I’m going to call my Azure Function by using a HTTP action which will allow me to post the data I need to my function for processing. You will see how we get the URL for this later, but all we need to do is provide it with the URL, and any other information I need within the body. For this demonstration, I’m passing the tenancy, the site, and the name of the person whose autograph I’ve collected.

Creating the Connection from PowerApps to Flow

As previously mentioned, I’ve not been able to use the standard connector to bind PowerApps to Flow. As I have a “HTTP” based trigger, I need to use a Custom Connector. A custom connector can be used to create your own connectors to any data source which uses a REST API, which makes them really powerful. The thing to remember, however, is that from the 1st February 2019, you need to have a PowerApps or Flow Plan 1 license to be able to use them. This applies to both the person who’s creating the Custom Connector, but also to any users who are using a PowerApp or Flow which uses the Custom Connector. If you already have custom connectors in place, you are currently in a grace period which lasts until the 31st January 2020, by which time you will need to have purchased the additional licenses or refactored your solution.
Custom Connectors are available for both PowerApps and Flow under the data heading on the left-hand menu.


There are several ways you can create the connector. You can create from Blank using a wizard, Import an OpenAPI file (also known as a Swagger file) from your local file system or from a URL, or import a Postman collection if you have been developing using that free tool.
Once the connector is created you can download to move it between tenancies or update it to reflect any changes or updates.

General Information

As the title suggests this is the high-level information required for our custom connector, but it doesn’t really do it justice as some of the critical pieces of information are required on this page: Host and Base URL.
You can change your icon and your colour etc if you wish, but I’m going to concentrate on what’s below i.e. the scheme, the host and base URL. The content which I need to put in these fields is generated from your Flow, to be exact the URL which was generated from our Trigger.
The scheme is obviously whether it is HTTP or HTTPS:
https://prod-39.westeurope.logic.azure.com:443/workflows/FLOWID/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=SIGNATURE

The host is the URL which hosts your web service. In this case, it is the Azure tenancy address we want:
https://prod-39.westeurope.logic.azure.com:443/workflows/FLOWID/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=SIGNATURE

Base URL is the section after the Host which will remain static i.e. with Flow, you will always have /workflows/FLOWID. Therefore the base URL will be /workflows.
https://prod-39.westeurope.logic.azure.com:443/workflows/FLOWID/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=SIGNATURE

Then you can set the relevant security requirements based on the documentation provided by the end point you’re calling. It will support no authentication, API keys, oauth etc so it can be quite flexible to allow you to authenticate using different methods.

The definition step in the wizard is one of the best tools I have found within the O365 stack for being able to do a lot in little time. It allows us to define what actions are going to take place within the connector, what triggers there are. Realistically I’m going to just concentrate on the actions as my trigger is being provided by Flow.
I will add a new action by clicking New Action and then filling out the form with the basic details such as the summary and the description.

General

The summary is what specifies the title for the action so make it short but descriptive of what it is you’re doing.

The summary is a line of text which offers a little more context around what your action is going to do. Finally is the Operation ID which is the unique name for identifying this operation and will be used when we call it from PowerApps.

Creating the main bulk of the request is really quite simple too because we can import from a sample. We have most of the sample already by taking the generated URL from the trigger event in our Flow.
My request URL looks like this, note that I’m also going to include a custom query string parameter which will take across my name:
https://prod-39.westeurope.logic.azure.com:443/workflows/FLOWID/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=SIGNATURE&Person=MattWeston365

We will now use this completed URL in the wizard to generate our request. Click on “Import from Sample” and you will see the “Import from Sample” blade appear on the right of your screen. Paste your request URL into the URL box, and because Flow is triggered by a Post event, I will select that as my verb.

If I know what my body is going to look like, I can also post in a sample payload into the “Body” area. Whilst I can’t fully configure my payload correctly unless you’ve actually run a test against your Flow using Postman or another tool, I won’t know what my sample payload looks like in terms of pushing through two images so I’m going to add that manually later directly into my Swagger file.


After you’ve clicked Import, you’ll see that your request is now being represented, and the various elements of the query and the body are now represented as objects which you can interact with.

In the query, I know what four out of the five elements are, they are all in the query string which I copied from Flow, so I can assign each element a default value. For each of the following I’m going to make the query string parameters mandatory, but not necessarily visible to the end user as I don’t need them to provide the information. Therefore, I will mark them as “Internal”.
• api-version
• sp
• sv
• sig


For “Person” I am going to make it mandatory and make it “Important” as I need the user to provide some data here at the point of calling the connector.
To make the process work, a few small tweaks are needed to the Swagger file. The tweaks are relevant to the files (images) which I’m going to pass through it, so I need to make a couple of small changes. An example of the working swagger file can be found here:
https://dev.azure.com/MATTWESTON365/_git/A%20Modern%20Autgraph%20Book%20-%20Swagger/branches
The first change is to tell the swagger file the exact type of data that it is expecting, therefore I’ve added “multipart/form-data” to what it consumes.


I then need to ensure that I have entries for both autograph and photograph. Unlike the other pieces of data being passed in, which are strings, I need to pass autograph and photograph as a file. Therefore, I’ve set the “in” property to be “FormData” as it’s being passed as part of the submission body, and also changed the type to “File”.


Once I’ve made the changes to the swagger file, I can update my connector by selecting to “update from OpenAPI file”.

Step 4: Azure Function

Azure functions are intended to be small, short running single task pieces of serverless code. Azure functions can be written using your preferred language, whether that is C#, nodeJS or even PowerShell.
The Azure Function will take some basic information from Flow which is passed through the body of the HTTP request. It will connect to the SharePoint site, locally copy the files that it needs (photograph / autograph etc.) and generate a new word document which it will upload back to SharePoint.
As I need to interact with the contents of a Word document, I’ve used the OpenXML SDK. I’m not able to use the Office Interop within an Azure Function as it needs Office to be installed locally. You can get the OpenXML assemblies using NuGet, as well as any other libraries which you might need such as SharePoint PnP Core which allows me to interact with SharePoint using the Client Site Object Model (CSOM).


You can find the complete code for the Azure function here:
https://dev.azure.com/MATTWESTON365/A%20Modern%20Autograph%20Book%20-%20Azure%20Function

Using the Custom Connector

Now that we have all constituent parts of our solution, we can start using the app to generate autographs, and see the whole process working. But just before we start snapping photographs, we need to connect the PowerApp to our Flow, using our custom connector. Our custom connector is added to our App by adding it as a data source.


We also need to add the formula to the save button to submit the data through the custom connector into Flow so it can be processed. To do this we will use the “OnSelect” and reference the name of our data source which will appear in Intellisense. I will then select my action, which I defined in my custom connector, and pass it the parameters that it wants the user to provide i.e. anything which we didn’t mark as internal when creating the connector. In our case, this will be the name of the person, the photograph and the autograph.

Using the PowerApp

There are numerous ways in which you can interact with your PowerApp, however, I’m going to focus on three key methods:
• SharePoint
• Teams
• Mobile device

SharePoint

If I want to use my PowerApp in SharePoint, I can add it as a web part on a modern page. When I edit the page and go to my webpart toolbox, I have a PowerApps web part which I need to provide with the App URL or App ID. Once I’ve added it to the page, the app will load on the page and will allow users to interact with it without the need to load PowerApps themselves.


The AppID or Weblink can be found within the “details” of your app, so you just need to copy either of these the WebPart properties and the autograph app will begin to render into the page. We can then use the Autograph App directly from the SharePoint page.

Teams

The experience of adding a PowerApp to Teams is much better than the experience of adding it to SharePoint. When we go into Teams and add a tab, we can add a PowerApp Tab which will allow you to select the PowerApp which you want to add. There is no need to provide IDs etc, you can simply click the one that you want the App can then be directly accessed from the Teams Tab.

Mobile Device

However, I really created this app for use on a mobile phone. We can install the PowerApps app on a phone (available for both iOS and Android) and then launch the Autograph app from there.

To make things even easier, rather than launch from within PowerApps, you can pin the App to your home screen. This doesn’t install it as an app in its own right, it simply creates a link for the app from the home page to launch it directly. To do this, use the ellipsis to the right of the app and select “Pin to Home”.

Then follow the instructions to add it to the home page, this obviously differs depending on the device, and it will create a shortcut for you to use (you can rename this if wished).

You can then use the app to take the autograph details. Click “Get New Autograph”, add the details, take a photo, review the 3 elements & click save.

After a few minutes, you can go back into SharePoint and review the final autograph document.

This Ebook was written from Matt’s session at the PowerApps Virtual Summit, you can still purchase a Pass to watch it and all the others.

About the author 

Matt Weston