Yep, you read that correctly. Microsoft is at it again – changing the licensing for PowerApps and Flow. Even though they just changed the licensing in February of 2019, they are making significant changes that will be launching in October. These changes come on the heels of the launch of PowerApps Portals, which are low-code websites for external users. Although I understand the need to add new/different levels of licensing for this new feature, it seems like overkill to change all the licensing just 5 months after a major overhaul. Furthermore, the changes could have significant financial implications for some, and the announcement has left the community up in arms.
I attended the Azure Virtual Day Camp put on by the Power Platform Users Group earlier this week. I registered for sessions from two different tracks (Developer and Architect); but in the end, they only registered me for 3 sessions in the Architect track (some of which were sessions for which I had not even registered). I was a bit disappointed, because I really wanted to attend the Developer sessions. The saving grace is that they sent me the recordings from the Developer sessions. Hopefully, I can find some time to watch them.
Developing with PowerApps, Flow and Azure Cognitive Services
My first session by Mariano Gomez was the most interesting. Mariano walked us through developing a Conference Badge Scanner App. The app scans a badge, converts the data to text, and sends an email to the badge owner. This same technology could easily be used to scan business cards and send them to a contacts list/data base. The App uses PowerApps, Flow and the Computer Vision API. Mariano demontrated building the app during the 45-minute session. That is how easy it is to leverage the power of the power platform. Continue reading “Azure Virtual Day Camp Review”
I’ve been working on a solution for a customer that utilizes SharePoint Online lists and libraries, PowerApps, Logic Apps, and Azure Functions. The solution works something like this: Project documents are stored and updated in a SharePoint Library by office staff. The shop floor needs to access the documents and know at a glance when documents have been updated. The PowerApp displays a count of the most recently updated documents by project and document type, and also displays the documents. A SharePoint List is used to store the counts of the most recently updated documents. The Logic App and Azure Function work together to update the SharePoint List with the counts from the SharePoint Library.
As part of the solution, we wanted a way to be notified if the Azure Function threw an error. This is where SendGrid comes in. SendGrid is a third-party email delivery service. Azure Functions support an output binding for SendGrid, which makes it very easy to integrate into your solution.Here is a grand overview of how my solution (just the Azure Function and SendGrid piece) will work – If my Azure Function throws an error, it will send the error message to Azure Queue Storage. The error message will be stored in Azure Queue Storage until another Azure Function (2) comes and picks it up. Azure Function (2) will use SendGrid to send an email containing the error message. Easy-peasy. You can use SendGrid to send emails for all kinds of reasons – when a customer places an order, you can send a confirmation email with the details of the order; when someone clicks a button on your site to request information, you can send an email with the requested information; the options are endless.
Happy New Year! January is here – new year, new you, right? Personally, I don’t believe in all that new year’s resolution stuff. Every day is a new opportunity to live your best life. How about we stick to new year, new updates for Office 365? There are some changes that will increase security, a change that may affect network traffic, best practice guidelines, and as always, an exciting new feature to highlight. Regarding security, Microsoft is retiring 3DES in Office 365, and sharing links that block download have begun rolling out. If you have configured your network to restrict resource access to Azure AD IP address ranges, make sure to read the piece on Azure AD updating IP Addresses. PowerApps users will be happy to see the release of a white paper on coding guidelines and standards. And finally, the exciting new feature we are highlighting this month is reminders in SharePoint.
Microsoft is very permissive when it comes to creating Office 365 groups. The default is that everyone can create Office 365 groups. Users can create groups from several different applications, and each user can create up to 250 groups. With this kind of freedom, things can get out of control pretty quickly. Before you know it, your environment can have a plethora of Office 365 Groups that may not be useful or even used. Sometimes the old adage is true – just because they can, doesn’t always mean they should.
Microsoft Ignite was held September 24-28 in Orlando, Florida with more than 1600 sessions on all that Microsoft has to offer. This session, by Dux Raymond Sy, covered guidelines for proper governance of Microsoft Teams. Dux makes basic recommendations but cautions listeners that Azure Active Directory P1 is a requirement for some of the features he highlights.
Overall, it was an informative session. Dux does a great job explaining the relationship between Microsoft Teams and Office 365 Groups; and breaking down governance into 3 manageable areas: provisioning, operations and information cycle. Continue reading “Review of How to Ensure Operational Governance for Microsoft Teams Session from Microsoft Ignite 2018”
I didn’t actually attend the summit, but rather took advantage of the fact that Microsoft is generous enough to make all of the sessions available on-demand. The Advanced Expressions for MS Flow session, led by Stephen Siciliano, was chock-full of information on the various types of advanced expressions available in MS Flow, suggested uses for these different types, and real-world demos. Using advanced expressions can seriously kick up your MS Flow game, so I highly recommend becoming familiar with these gems.
Advanced expressions are function expressions that can be written in a compose action or inline in a conditional. When an advanced expression is written in a compose action, the result of the expression can then be used in other areas of your flow. On the other hand, if the expression is written in a conditional, the result of the expression will be used to determine to which path the flow will continue. In this case, the expression must begin with the @ character, and the expressions that can be used here include equals(), and(), or(), not(), less(), lessOrEquals(), greater(), and greaterOrEquals().
However, I may be getting ahead of myself. You may still be asking “Where do I find advanced expressions?” So, let me start there. Once you create an action, click on “Add dynamic content”, in the pop up, there are tabs for “Dynamic content” and “Expression”. Click on “Expression”. All of the advanced expressions are listed by type. They also include a short snippet description to assist you in determining what they do and how you might use them. It helps that most of their names are fairly descriptive as well.
The beauty of advanced expressions is they give you many more options for working with your data; and therefore, you can create flows that can do more for you. With advanced expressions you have the power to manipulate and generate data in the following ways:
Converting Data Types
- MS Flow automatically converts some data types. For example, integers will automatically be converted to strings. What this means is that the data will be available both as an integer and as a string in the data content.
- Other, less obvious, conversions can be written as an expression by the flow author. For example, if you need to convert a base64 encoded string to a string, you would use base64ToString(). There are advanced expressions for converting to string, floating point, integer, boolean, base64, Data URI, URI component, binary, array, JSON object, and XML content.
Working with Strings
- There are expressions for joining two strings, concat(); extracting a chunk of a string, substring(); or replacing sections of a string, replace().
- If you need to convert the case of a string, you can use toLower() and toUpper().
- Finding the location of text in a string is easy with indexOf() and lastIndexOf().
- Lastly, if you need to check if a string starts with or ends with a value, you can use startsWith() or endsWith().
- Doing simple arithmetic, or even advanced arithmetic, can be achieved with the arithmetic expressions. These include:
- add(), returns the result of adding two numbers
- sub(), returns the result of subtracting two numbers
- mul(), returns the result of multiplying two numbers
- div(), returns the result of dividing two numbers
- mod(), returns the remainder after dividing two numbers
- Advanced arithmetic is possible, because you can use expressions within expressions. For example, if you want to complete a + b / c, your expression would be add(a, div(b,c)).
- Min() and max() are expressions that return the minimum or maximum value from an array of numbers.
- There are a bunch of advanced expressions for manipulating date/time. These include, but are not limited to, expressions for:
- Returning the current timestamp as a string, utcNow()
- Adding times together, addMinutes(), addHours(), addDays(), etc
- Converting time zones, convertTimeZone(), convertToUtc(), convertFromUtc()
- Formatting date/time into a string, formatDateTime()
- Returning a segment of time from a timestamp, dayOfWeek(), dayOfMonth(), etc.
- The two most helpful examples of expressions that generate data are:
- guid(), returns a globally unique string
- rand(), which returns a random integer within the specified range
The if() expression can be helpful if you are simply trying to add styling or set a value based on a condition. You can write a simple if() expression rather than add an additional layer of conditions into the flow. Multiple layers of nested conditions can become confusing and can get short circuited if a missing property gets referenced.
Properties that are not set or return as null will cause your flow to fail. To avoid this, use the coalesce() function in conjunction with the ? character. The idea is to set a default value for the property that will be used if the property returns as null. This looks something like this: coalesce(body(‘Get_record’)?[‘content’], ‘Default Value’).
There are also some really cool advanced expressions for working with lists/arrays, and workflows. I encourage you to poke around in the Expression tab to see what else is available. In the session, Siciliano also briefly discussed asynchronous actions (using 2 triggers in the same flow), working with other flows (using the Flow Management Connector), and calling nested workflows (use this to break up larger flows into smaller chunks). As I stated earlier, this session was chock-full of information. It was well worth the time spent. I’d like to think my Flow game has been kicked up a notch as a result.