Share PowerApps to external users

This week I wanted to test out new PowerApps capability that is sharing PowerApps Canvas Apps to guest users. And as you may already know – it works like a charm! 🙂

If you’d like to know more about it here is great resource that cover this topic in details (licensing, connectors that supports it etc).

Add fields to SharePoint List using Flow

Last week I’ve explained how to create SharePoint list or library using Microsoft Flow. This time I’ll show you how you can add fields to your SharePoint List using Microsoft Flow, and add items to your list. This will complete the scenario so you’ll get a full solution for dynamic creation SharePoint List along with fields and values.

Automation is the key

Just before I’ll deep dive into the details let’s first cover the question of: why you may even need such dynamic list creation with fields and values?

So imagine you have multiple PowerApps apps for different purposes each ie:

  • time tracking
  • resources booking
  • goals review
  • team members praise
  • retrospective meetings notes

Each app stores data in SharePoint and is team specific – this means some team may want to have it, others not. Also the app data should be team related.

Other often scenario is when you have an app that you want easily deploy in your client’s environment. This was my case when I’ve created my Delegation Playground app that uses SharePoint list – I wanted to automate the process of list creation so app user don’t need to create it manually. I wanted it to be as simple as possible.

In PowerApps there is a Solution concept but it applies only to PowerApps with data stored in Common Data Service (which I highly recommend – check this post of mine) so if your app works with SharePoint Online lists or libraries you may need the below Flow.

The Plan

Ok, so last time we end up with created SharePoint list. Now we need to:

  • Add Number and Boolean fields
  • Add 3000 rows to the list
Image result for over 9000 meme
I wish to make it 9001 but…there are some limits 🙁

Add new fields to SharePoint list using Microsoft Flow

To create new SP field we’ll going to use SP REST API (by using Send an HTTP request to SharePoint action). However this time we need to use new Uri – the one dedicated to list modification. As you can see in this POST request example we need to know list guid to make proper operation. The Uri need to be like:

http://<site url>/_api/web/lists(guid'<your_new_list_guid')

But how to get a newly created list GUID? Oh that’s simple – make a sample call of the Flow we’ve made last time and use data it returns.

Disclaimer: Some of you may already know that there is a simpler Uri API endpoint _api/web/lists/GetByTitle(‘<list name>’) as described here but the way I present brings an additional learning value.

Just follow guideline below 🙂

1. Run Flow that creates list in SharePoint site location
2. Copy its output JSON
3. Add Parse JSON action
4. Put “body” in Content property
5. Click “Generate schema”, paste JSON and click Done
6. Add new string variable
7. As value add id field
8. Selected it and paste into the Expression field
9. Remove closing } and opening @{
10. Add split( on the beginning – we’ll use Split function and use id field value as first argument
11. Add ,’_api’)[1] on the end – we’ll split the string by ‘_api’ substring and take second element from the output collection
The whole expression looks like this:
split(body(‘Parse_JSON’)?[‘d’]?[‘__metadata’]?[‘id’],’_api’)[1]

Now once we have the Uri of our newly create SharePoint list we can use example from this documentation page and use a field type value related to expected field type (all possible sharepoint field types values are here).

Disclaimer: As you can see we’re now working a lot with Microsoft official documentation. I recommend this as a really well written and complete reference source for any O365 developer.

Your action should be configured this way now:

Warning: please note that for number field I used Number field type type value, not the Integer field type value. The latter won’t work

Create similar action to create Boolean field:

Protip: Use copying action to clipboard – it’s new and fancy and I love it. And everyone was waiting for it 😀

Add SharePoint items to SharePoint list using Microsoft Flow

To add 9001 items we’re going to use Microsoft Flow “Do Until” loop. It will do defined operations and at the end of the iteration it will increase the iterator. Once the iterator exceed 9001 flow will know that it’s the right time to go out of the loop.

So add new variable called “Iterator”

Now add Do Until loop and select Iterator variable as value property. Set the check to be “is greater than 3000”. Remember also to unfold Change limits section and increase Count to 3000 items and Timeout to PT5H (just in case 1 hour will be to short)

Warning: Do Until has hard limit on 5000 iterations at maximum.

At this point we’ll normally use “Create item” action for SharePoint in Microsoft Flow. However we’ve just created the list and the mentioned action won’t work with dynamically created list. So…for the forth time we’ll use Send HTTP request to SharePoint 🙂

Protip: “Send HTTP request to SharePoint” is sooo universal and powerful. You can do almost ANYTHING using this action. One of my favorite.

You can find here documentation page where the example Create List Item POST HTTP request is made (see? I told you it’s well written and helpful). Let me show you configured action and code first and then I’ll describe it:

{
  __metadata:  
            {  
                type: "SP.Data.Delegation_x0020_PlaygroundListItem"  
            }, 
Title: 'Item @{variables('Iterator')}',
Integer_x0020_Field:@{variables('Iterator')},
Bool_x0020_Field:@{if(equals(mod(variables('Iterator'),2),0),'true','false')}}

So what I’ve done is (follow my steps):

  1. Add “Send HTTP Request to SharePoint” action inside Do Until loop
  2. Fill Site Address, Method, Uri and Headers as in the screenshot
  3. Paste above code but please make sure to:
    • swap Delegation_x0020_Playground with your list name
    • have ListItem suffix. So for your list named “MyList” the type string will be SP.Data.MyListListItem
    • swap all special characters (like space) in the list name. Good article about it was written here by Stefan Bauer
    • When providing field names remember about special characters rule described above
    • In my case I used expression with modulo function so every even item has Bool field = true

Last thing we need to do is to increase the iterator by 1 inside Do Until loo to not end up with infinite loop.

AND THAT’S IT!

WOOHOO!

You’ve just created flow that create list with fields and list items. And everything done with one push of a button to trigger your flow 🙂

Automation is beautiful.

And just in case you want to download ready made solution – you can download it from here 🙂

Hope this post was helpful. Write me a comment if you have any question or used my flow.

Create SharePoint list using Flow

Microsoft Flow is a great automation tool. It integrates with over 230 services using connectors where each of them contains multiple triggers and actions. One of those connectors is a SharePoint Online connector with a set of 10 triggers and 47 actions(!). Such big set allows to create many scenarios. Starting from managing simple resource list to invoice approvals along with permissions on different levels. Even though, SharePoint Online connector does not contains actions like “Create list”. Such actionmay be useful if you want to create those elements dynamically. Before you think “what a bummer” and turn your eyes on custom code solutions please read this article. I’ll show you how you can create SharePoint List or SharePoint Library using Microsoft Flow.

Create list from list template

Before I’ll show you how I did that let me explain why I need this kind of solution.

Last week I’ve publishing Delegation Learning App. The app was an extension to what has been described in article How to overcome 500 items limit in PowerApps. Using my app a user is walkthrough different integration scenarios – static data, excel from onedrive and SharePoint Online. To make all steps easy I wanted the data sources to be already prepared for the user. With static and excel data there was no problem – I’ve simply attached them to app package. But how to prepare SharePoint Online list? I had 2 options:

  1. Give access to my environment – however I didn’t want to add external access for anyone who want to use an app. I didn’t want to create an account which I would be shared to others too.
  2. Prepare an excel that a user can import to his SharePoint Online – however this option has some import column limitations and I my aim was to create an universal solution.
  3. Create a list dynamically using Microsoft Flow – for me this method was perfect. I could defined any list definition and add items to this list. The only thing that the user had to do is import import flow (which is done automatically if you import PowerApps package) and run it.

Now you know why I decided to go with this option. Now let me explain what I’ve used and how it works.

Create SharePoint list using Flow

To achieve my goal I need use “Send as HTTP request to SharePoint” action which allows to execute any action that is available through SPO REST API.

SharePoint Online REST API is a special way of sending instructions to SPO using HTTP requests. I.e. by making HTTP GET call to https://<Site ABCD url>/_api/web/lists you can get a list off all lists in ABCD site.

Did you know?
Your browser is constantly using such way of communication. Every time when you open some web site your browser is making an HTTP GET request. Go ahead, open a new browser tab and try it: paste https://<Site ABCD url>/_api/web/lists URL (of course swap <Site ABCD url> with your own SPO site url) to see the XML representation of all lists that exists in the site along with metadata

To create a SharePoint list I need to do what is described in this section. In above section you can find below example:

1. url: "http://<site url>/_api/web/lists"
2. type: "POST"
3. headers:{
            "content-type": "application/json;odata=verbose",
            "accept": "application/json;odata=verbose"
}
4. body: { '__metadata': { 'type': 'SP.List' }, 'AllowContentTypes': true,
 'BaseTemplate': 100, 'ContentTypesEnabled': true, 'Description': 'My list description', 'Title': 'Test' }
           

Let me quickly translate it for you.

1. Hey SharePoint, I'm going to do something with your lists...
2. ...and that'll be a modification (create or update)...
3. ...And in step 4 (that is body) I'll send you the details using JSON notation ("content-type" header). If you want to communicate with me please use the JSON notation ("accept" header)...
4. Ok, so the message is this: <the body>

Normally you would also need to authorize yourself providing an token – OAuth token to be precise – but thanks to MS Flow action, the connector is taking care of it 🙂

The last question you may have now is: “how should I know what to put in the body?”. There is a wonderful resource that explains everything you can do using SharePoint REST API: REST API references and samples (add it to your bookmarks, trust me).

Now, in above knowledge base there is a sub-page where you can find all properties you can use in the body: List Properties. You can find there the definition of all used properties. I.e. Base Template represents a ListTemplateType value (see ListTemplateType reference for template type values).

So the last thing is to…

Bring everything back together

Now let’s convert theoretical knowledge into our Microsoft Flow solution.

Disclaimer: Normally I would paste some image below and describe what it shows + what you need to do to achieve the presented result. But thanks to Clarissa Gillingham I realized that if an image is worth a thousands words, a movie is worth a thousands images (23 images per second to be precise #GeekContent). That’s why I’ll just leave with a movie – I hope it’s self explanatory 🙂

Code used for Send an HTTP request to SharePoint is below:

URI:
_api/web/lists

HEADERS:
content-type = application/json;odata=verbose
accept = application/json;odata=verbose

BODY:
{ '__metadata': { 'type': 'SP.List' }, 'AllowContentTypes': true, 'BaseTemplate': 100, 'Description': 'List with items to work with delegations in PowerApps', 'Title': 'Delegation Playground' }

Ready Flow you can download from here.

PERFECT! Now you can click Flow button, provide ANY SharePoint Site URL you have access to and the defined list will be created there. Is that everything? OF COURSE NOT! A list with the default settings contains only built-in fields which won’t be enough in 99% cases. So now we should add some fields…but this part I’ll cover next week 🙂

Stay tuned!

Delegation Learning App

For last few weeks I was preparing a special app for all my readers. And today it has been finally finished. The Delegation Playground App is ready for you to be downloaded! What this app is all about?

Short brief

In january and february I was struggling with delegation in my PowerApps. I’ve noticed that it was not only problem for me – many people have it as well. Interesting part is that was not because of poor documentation – the official PowerApps documentation is really done well (I was a SharePoint On-Premise developer, I know what I’m talking about). Anyway – after reading documentation, few blogs and resolving all delegation warning in my PowerApps apps, I decided to gather all my knowledge in my own article: How to overcome 500 items limit in PowerApps. For my surprise it was very warmly welcomed by community and is the most read article in my blog

And even more than that – it is the most popular in the internet. I perceive that as a effect of giving true value to people learning and developing PowerApps. Every content author cannot imagine better price for helping others.

Learn by doing

There is a saying that says: “To write a code one must write a code” which means that if you want to do something well you must practice it. There is no way around. There is no shortcut and no book that will give you more than you can achieve by trying, making mistakes, fixing and finishing your job.

That’s why I’ve decided to create an app Delegation Playground App.

Using this app you can play with delegation and check how it behaves in scenarios like static assets, excel from onedrive and sharepoint online list.

And of course all resources are in the zip package so you won’t need to prepare anything.

Download Delegation Playground App, import it and bring learning to a higher level.

Have a great delegation time 🙂

5 steps that increased Office365 adoption

Implementation of the Office365 environment in an organization is a complex process. It is not enough to create a company account in Office365, buy subscriptions, add users and connect the organization’s domain. You also have to take care of the transfer of company resources, as well as transfer the solutions used in the organization (or take care of their integration) – that is, make the so-called migration. However, it does not guarantee the success of Office365 implementation. In order for the entire operation to be successful, it should be persuaded to change people in the organization. In this article, I will present 5 steps that will increase your chance for effective adoption.

Disclaimer: The steps have been written as a retrospection of the cooperation with one of my clients. Each company is different and requires an individual approach. I encourage you to make an conscious decision which of following steps will be useful to you.

Step 1: Discover the product you bought

Office365 is much more than Outlook, Word, Excel and PowerPoint. Even if we add OneDrive, SharePoint Online, Microsoft Flow and PowerApps to this list, there are still many left! And using only platforms mentioned above, you can achieve a lot (examples can be found here). So what is the total number of platforms/applications in Office365? A very successful combination was made by the jump365.com team:

Be sure to try the interactive version! https://app.jumpto365.com/

It is worth remembering that each of the products has a huge range of its own functionalities and various configurations that allow you to cover countless scenarios.

Finally, the maximum use of the built-in capabilities of Office365 seems to not have a limit – Microsoft constantly improves its products and adds new opportunities, so the answer to the question “to build yourself or to wait a while” is not obvious at all . I.e. recently appeared the possibility of integrating the Common Data Service with Outlook, which is another argument to use the CDS database as a data container instead of SQL or SharePoint.

Tip # 1: Make sure you have used the maximum of Office365 built-in features before you approach the development of custom solutions

Step 2: Keep it Simple and Straightforward

We, consultants, know that everything can be achieved in various ways. For example, sharing the file can be done from the level of SharePoint, OneDrive application, synchronized folder on the computer, Teams etc. For many people a lot of options are freedom of choice and high integration. But for many, it’s chaos (“so you mean…again…how many ways can I do it?”), lack of coherence (“why sometimes you share file using browser and sometimes directly from a folder on your computer?”) And this makes them want to return to “the safe places “: the old habits and methods they used to use so far – those that were simple, transparent and consistent.

That’s why:

  1. Choose the best and the only right way to proceed. At least at the beginning of implementation. For example, to share a file with people outside the organization, you must first synchronize the OneDrive folder on your computer. Period.
  2. Create instructions for the most key scenarios. For us, these were:
    • Document scanning (using the mobile application)
    • Synchronize all team files on your computer
    • Providing a file to a person outside the organization
    • Submitting the attachments from the email to the channel in the team
    • Planning a meeting with the Teams conference
  3. The statement can not be based on an action that has not been described. For example, if you need to synchronize a folder on your computer at some point, remember to create an instruction to set up such a synchronization

Tip # 2: Choose the best and only right course of action. Clearly communicate it in the organization.

Step 3: Segmentation of users

The language of the needs is important (see the next paragraph), but if the organization is of medium size (more than 50 people) or more, it is impossible to talk to each employee. So one should approach the topic methodically.

  • group employees according to the areas they deal with, for example: finance, processes, IT
  • identify “key people”, ie people who have a high impact on others and / or decision-making and have resistance to implementing new solutions
  • identify “influencers” or people who will be promoters of change. They will help others adapt the change not only out of a sense of duty, but they will also realistically see the benefits of the upcoming changes. Important: try as hard as possible to not force people to take this role! They should be natural, not controlled and managed.

Step 4: Learn the language of needs

Users themselves will not start using ready-made tools. Even if the company thinks otherwise, for some employees, “excel on the local computer is enough”. The reason is simple – tools are just tools. They are there to meet needs. So in order to implement tools effectively:

  1. Understand the needs of users: get to know the context of their work. See what difficulties are currently. Understand why new solutions would not help them (if they say so)
  2. Express your needs: explain to users the needs for which change is being implemented (see scenario 1)
  3. Speak the language of the users’ needs: show them what benefits they will get thanks to the change. How this change will affect their work (see scenario 1)
  4. think out-of-the-box: declaring the user that something can not be done is not testimony. Because what the user actually says is “it can not be done differently for the adopted assumptions, limitations and understanding of the whole process”. He built a wall around his process. Your task is to move every brick of this wall and remove one after another until the wall collapses. It is important that it involves the process itself (that is, the business would continue its goal). (see scenario 2)

Scenario 1 (real life example)

  • [User] “Using OneDrive is pointless, I already have all the files on my disk and when I need it, I send them to other people by email. Why should we move all the files to another place?”
  • [Consultant] “We want to limit the e-mails we send in the organization, and we also want to archive all documents and maintain version history.”
  • [User] “Nothing is lost in emails, but I understand. I will send messages less frequently”
  • [Consultant] “Hm, and remember how much time it takes you to find the last version of the document in email messages. And imagine that you work on the document for 3 days and it was supposed to be sent in an email, but suddenly the computer broke down and you are not able to recover your 3-day job … “
  • [User] “Eh … I understand … maybe it’s actually better. But I have all the shortcuts on the desktop, how do we transfer the files, where are they going to be?” [here was the real reason for the resistance]
  • [Consultant] “Do not worry, we’ll do all the files will be available from your computer and all desktop shortcuts will work. Only the place where these files will be stored will change.”
  • [User] “super!”

Scenario 2 (real life example)

  • [Accountant] “We can not digitize the invoice circulation, because every invoice requires a president’s stamp, unless it is possible to attach a picture of such a stamp … but this is only an additional step in the whole process.
  • [Consultant] “Why is this stuff?”
  • [Accountant] “For the accounting department to know that the president read and accepted the invoice”
  • [Consultant] “And the invoice with the stamp stays later inside the company only?”
  • [Accountant] “Yes”
  • [Consultant] “And if the president came and said:” I read and accept it”, that would be enough?
  • [Accountant] “Yes”
  • [Consultant] “So you use stamps, because it’s faster than personal confirmation and also faster than writing an email. If it was just as simple as: The president gets a notification on the phone and only clicks “accepts” or “reject” and all further communication takes place automatically?
  • [Accountant] “Hm …. well … all in all it could be so …”

Bingo! 🙂

Tip # 3: Challenge “because we work like this”. Inquire. Be inquisitive. 5x Why.

Tip # 4: To learn about the needs of users, conduct a training / workshop with them. At the beginning for the groups of users and later on carry out ad hoc consultations 1 : 1.

Step 5: Make small step at a time

When you enter a lot of new tools, some users may be scared of the number of changes. They will feel lost and will return to the old known processes in which they felt comfortable. Therefore, add new tools and improvements slowly, one by one. If possible, do not multiply new applications. Integrate everything in one place. A good idea is, for example, to start with communication through Teams and define teams there. Then incrementally build a daily work process around Teams. Then talk to the identified employees / employee segments and slowly move the subsequent processes.

Tip # 5: Keep yourself updated – Office365 is constantly evolving.

Overview of SharePoint Virtual Summit 2019

In this article I’ll put short glimpse of what has been announced on SharePoint Virtual Summit 2019. Be aware that some of following features may be still in preview but are going to appear later this year. I skipped features that has been announced on Microsoft Build 2019

flow SharePoint Document Libraries

  • Build custom forms using PowerApps
  • Microsoft Teams will gets enriched metadata experience
  • Bulk Actions

    This feature was requested for a long time. And now here it is: you can select multiple items/document and take an action for all of them: update properties, download, delete, approve, move etc.

  • New Flow actions

    There are scenarios in which you need to check-in/check-out documents, get version information, grant access or create folders as a part of larger business process in Flow. Until now you could do that only by calling SharePoint HTTP REST API. But from now on you can do all of above simply by using Flow actions!

  • File request feature

    This is a bomb! You will be able to request files from other users directly from the place where you store your files! The recipients will get email with link. Once they click on it they will see consistent UI with built-in files upload.

  • Organization document templates

    governance becomes even easier!

flow Collaboration

  • Organization Home site

    It’s a communication site with some extra superpowers. It searches for data tenant wide, mark site news as organizational news, enables special SP mobile app. For me it completes perfectly org-wide Teams team. Just add tenant Home site as a tab in an Ord-wide Teams team

  • New page designs
  • New webparts – i.e. Yammer!
  • News links
  • Audience targeting
  • Sync Microsoft Teams files to you PC or Mac
  • Teams apps in SharePoint sites
  • Enhanced SharePoint list experience embedded in Teams
  • Enhanced co-authoring acroos mobile, web and desktop versions of Word, PowerPoint and Excel (only for Office 365 and files in the cloud)

flow Governance

  • Rename your SharePoint site (including its URL)
  • Replace the root site within a tenant

    you’ll be able to build a new org site on the side and once completed it swap it with a root site…it couldn’t be simpler.

  • Create SharePoint list using excel file with an option to configure columns types!
  • Share & Forget with external access expiration
  • File restore for SharePoint just as it is already for OneDrive
  • Sensitivity labels

    the mechanism known from Azure Information Protection is now being supported by SharePoint and OneDrive (and it is called Microsoft Information Protection)

  • Decide where your data related to SharePoint and O365 groups will be stored using multi-geo capabilities

flow Search

  • Customizable Search to rule them all!

    The same search experience will be shared across any Microsoft platform. Top, middle, search. Oh and there will be available to add custom verticals, custom refiners and custom display templates! What is more you will be able to search for conversations from Yammer and Microsoft Teams in any search endpoint!

  • Search in Office

    Discover your network of apps, files, folders, people, organization charts, SharePoint sites, site pages, lists and list items

  • Search in SharePoint

    Catch up on news and announcements. Find the sites that are relevant to you without scrolling through endless bookmarks. Pick up on that shared document you were working on

  • Search in OneDrive

    Discover relevant information to help you get work done where you’re working through intelligent results and sophisticated refinement

  • Search in Windows

    Search right from your Windows desktop. This way you can search not only inside your local files but also in Office365, person in organization with smart suggestions based on the people you work with the most

  • Administer your Microsoft Search

    Control organization search using provided powerful admin center and manage all of Microsoft Search endpoints!

flow Misc

As you can see SharePoint is not stopping in getting new capabilities. But what may not see and I have to tell you – many of above changes came from UserVoice. UserVoice is a forum where everyone can submit a bug, an idea or new feature request and Microsoft will implement it if only the post gets enough amount of community support (represented by likes). Changes presented on SharePoint Virtual Summit 2019 are the best prove that Microsoft is listening to its users!

How to overcome 500 items limit in PowerApps

I planned to publish another topic for today but I decided that this one will fits better to the post I’ve published a week ago.

So if you work with PowerApps connected to ANY data source you had to experienced or at least read about 500 items limitation. In this post I will show you 6 ways how you can exceed that limitation.

Limit? What limit?

If you’re one of those happy devs that have never heard of such limit I’ll make quick reminder:

In PowerApps every data source (SharePoint, Common Data Service, OneDrive) is under limitation of 500 items. It means you cannot get more that 500 items from a data source but even more than that – PowerApps won’t even “be aware” of any rows above 500.

Imagine simple case: On your OneDrive for Business you have an excel file with ~600 rows. Even though you need only last 10 rows you will get rows 490-500 instead of 590-600. As I told you in previous paragraph – it’s not the limit of total fetched items. It’s the limit of items that PowerApps knows about.

But before you think that’s a killer for PowerApps and “oh those architects, they’ve never use their tools so how they can design something that actually works” let’s imagine another example:

You have an excel with 2mln rows (yep, I saw over 2GB excel file in one company from financial sector). One of app users opens your app and…probably in an eyeblink you will get tons of emails that your app is not working (but of course it is working but the loading time is huge). That’s why this limitation make sense.

Learn by reading is great. Learn by practicing is even better. Download my Delegation Learning App and start practice delegation now!

Anyway there are many occasions where you will need more than 500 items. Maybe not 2mln but a simple task list for a company with ~1000 employees can easily generate around 50000 rows in total. So how you can overcome this 500 items limitation in PowerApps? In following sections I describe 6 options in the order from easiest/fastest to the most powerful (but also time consuming to setup):

  1. Increase the total limit items you can fetch
  2. Use static data
  3. OneDrive for Business connector specifics
  4. Use delegation
  5. Use delegation + iterative function
  6. Combine PowerApps with Flow

1. Increase the total limit items you can fetch

Okey so this method is the easiest and really quick to setup. Click file (top left corner) > App settings > Advanced settings > set value for non-delegable queries.

This method has one hard limit (limitation of the limitation) – 2000 is a maximum value you can set which means you can’t get more that 2000 items on the same rules as for 500 items (PowerApps won’t know about 2001 item). So if this method does not work for you let’s move to option 2.

2. Use static data

In some specific cases static data may be the best solution. Such data can be imported to your app and will be kept within assets of your app. You can have 10000 rows and still users will have access to all rows. However remember following notes:

  1. Static data are static – you cannot modify it from within PowerApp. But for some scenarios it may still do the job i.e. you build company travel app and you want to have index of all countries in the world (192) along with bigger cities (~30 x 192=5760) so your users can search and select to which city they’re traveling to. Countries and cities typically don’t change dynamically so we can freely import them as static data instead of using SQL database (for which you have to spend extra cash).
  2. Static data are attached to your app which means they’re enlarging total size of app which may affect app loading time.

If you still think static data is a best choice for you here is how you can add it:

  1. View > Data Sources > Add data source
  2. Click Import from Excel
  3. Select excel file and a its table that you want to import

Ok, now, what if this option also doesn’t suit to your needs: Excel is good but you need to be able to modify it from within app so all app users have access to same data. So you googled and decided to use OneDrive for Business data source connector. It uses excel file as a container which data can be modified, sounds perfect, right? So here is the deal…

3. OneDrive for Business connector specifics

Accessing Excel files using OneDrive for Business connector does not support delegations (I’m explaining delegations in section 4). Long story short here are the implications:

  • You can’t get more than 2000 rows
  • OneDriveForBusiness connector treats each table in excel file as separate connection. The 2000 limit is related only to a connection – not the source.

So if you know you may need more than 2000 rows stored in one data source you should switch from OneDrive for Business to any other like SharePoint, Common Data Service, SQL etc. and take use from delegable queries. What are these? Let’s see.

4. Use delegation

Delegation is a mechanism to access all data from a data source in a performance friendly manner.

Speaking a bit more clearly it’s a situation when your PowerApp app says to a data source:
“Ok, you know what, I need items that match these conditions but hey, can you do all the computations by yourself? I need to use my network bandwidth, memory and CPU power for something else…I just need results.”

Now, there are 3 catches:

  1. All results are fetched in a maximum of 100 items bundles. The next bundle is being fetched once a user scroll to the end of a gallery/table list (check out delegation demo gif down below)…
  2. …which means if you need to fetch more than 100 items (! not process but fetch. You can process 10000 of items but fetch only 15 of them as result) you can only use gallery or table. Collections are not supported and works under non-delegable queries limitation (Collect() or ClearCollect() functions breaks delegation!)
  3. Your query need to be supported by the data source. Figuratively speaking the data source must understand what PowerApps app is saying to it (check out example queries on the image down below). To complicate it a bit more not every data source supports all functions and operations – each data source connector documentation outlines delegable support (i.e. here you can find SharePoint Online delegation support). For better understanding of delegations in PowerApps I recommend you to read delegation documentation.
Delegation demo. Left gallery is sourced by OneDrive for Business (which is non-delegable). Right gallery is sourced by SPO list with 500+ items.
Look what happens once I scrolled to the bottom of the SPO items gallery.
Example delegable and non-delegable queries in PowerApps

Ok but what if need more than 2000 items here and now? There are 2 options for doing that. But before you read them please consider below:

Following approaches should be treated as potentially bad practices and should be used only under specific circumstances and with proper caution since they may have bad impact on your application performance or other O365 tenant services. It’s like with medicines – they can solve your problems but harm you in wrong dosage or used inadequate to needs. So in 95% of cases delegation will perfectly do the job. It may requires read & learn a bit but trust me – it’s easier than struggling with performance issues that may appeared if you misuse options 5 and 6.

Ok, so now we can safely move to options for those 5% of cases 🙂

5. Use delegation + iterative function

General idea is like this: for a delegable query build a loop and in each iteration filter data chunks. I.e. in 1st iteration you get rows 1-500, in 2nd 501-1000 and so on.

I won’t explain it in detail or show you code snippets because this method is not mine. Its author is MS employee Brian a.k.a Mr.Dang() and I would feel bad if I get his credits for this workaround. Read it and just in case it won’t meet your needs…

There is also another way of which I’m the author. Option 6. Here it comes.

6. Combine PowerApps with Flow

The last option is to use Flow as a middle man that was asked this:
“Dear Flow, since your data source connectors don’t care about this whole delegation stuff, can you please do me a favor, get all rows, join them in 1 big string and send me back please?”

A simple demo with excel and outlook email may look like this:

To make this work for more than 256 results I had to make few configuration tweaks of the “List rows present in a table” action:

Fetching 682 rows took 3 seconds.

Fetching 2101 rows took 11 seconds so that may be an issue.

However if you use SharePoint as a data source I have a good news for you – I’ve made a demo that fetches 1000 items in 2 seconds. In this blog post I describe step by step how to:

  • Build a PowerApp from scratch
    • Add input fields
    • Pass input fields values to Flow
    • Parse results from flow
    • Display all results in a gallery
  • Build a Flow from scratch
    • Get parameters from PowerApps
    • Integrate Flow with SharePoint
    • Send all results back to PowerApps

And that’s it! I hope you enjoy this blog post. If so please let me know in the comments down below. If not or maybe you know a better solution – let me know as well!

Performance – is Flow faster than PowerApps?

In this post I’ve showed you how you can create PowerApps app that utilize SharePoint Search for your business. I used there PowerApps for parsing big string containing our results from SharePoint Search.

But one o my readers asked me an interesting question

“Mike, wouldn’t it be easier and faster if we parse results in Flow and pass to PowerApps just raw field values?”

Jacek M.

Hm….at that time I didn’t know the correct answer. Neither I could find it in the PowerApps Canvas App Coding Standards and Guidelines . That’s why I’ve decided to make quick test on my own and publish its results on my blog.

Time measurement 1: parsing on PowerApps app side

It’s pretty straight forward to measure parsing time for the application we’ve built in my previous post. Just add timer control, start the timer before firing flow, fetch results from flow, parse it and stop the timer right after it. It will look like this:


I’ve setup my test to fetch 10 results. Result of it: 1 second! 1 second is the time that PowerApps need to fetch 10 results from flow and extracting required field values (Title in this case). But that was not enough to me. I thought: “let’s see how long will it takes to get 100 results and extract 4 fields”. The results surprised me. 1 second again!

3 of 100 fetched items from SharePoint Search via Flow. PowerApps extracted 4 fields from received string: Title, URL, Ranking Sum and UID of the item.

It will be very hard to beat it but let’s give it a shot! Let’s check how Microsoft Flow will manage to extracting field values.

Time measurement 2: parsing on Flow side

Disclaimer: John Liu in this tweet proved I was wrong. My double loop in flow was quite a bad idea..both from conceptual and performance perspective. He’s built a flow which was 15x faster than mine! This means PowerApps is not 30x but “only” 2x faster than Flow…and that also I need to take some flow building lesson 😉

To cheer myself up I can only say:
those who do nothing makes no mistakes.

First let’s start from small test that is fetching 10 items and only Title field. The modification of the flow is simple: I will iterate through each row of the SP search results, then through each cell in a row (each row contains multiple cells) and then once I find the cell I’m looking for (Title in this case) I’ll append cell value to an array variable. Modified flow will look like this:

Parse Cell action allows for using Key, Value, ValueType attributes in farther actions. The Join action that is in the bottom of the screenshot is used to convert array to text value (because PowerApps does not accepts arrays 🙁 ).

For start I will just take 10 results and extract only Title field. Let’s test this configuration:

WHAT?! 32 seconds!? I must admit – I expected that Flow will be slower that PowerApps but not ~30 times (it’s obvious why it’s a common pattern to use your end user CPU time, via browser or mobile memory, rather than your own) . That’s huge difference and strong argument for using PowerApps for all kind of parsing and any CPU expensive calculations and not using Flow for that.

Further testing (more fields, more items) has no point. Let’s jump right to the conclutions.

Conclusions

Personally I find this small test really informative.

First: It’s more efficient to use PowerApps for calculations that Flow. It’s worth to tell it even if most of us know that common good practice is to distribute calculations and delegate it to user device.

Second: In the light of above note, consider making more than 1 call to Flow and back to make most of the expensive calculation on the PowerApps side for the sake of whole process time consumption. E.g.:

  1. PowerApps asks Flow to get results from SPO Search
  2. Flow get results and pass it back to the app
  3. PowerApps extract some data (specific fields, values range, values sum etc) and pass it back to Flow
  4. Flow gets additional data for selected items or fields and pass it back to PowerApps again
  5. PowerApps display results to user
Check how I can help you or contact me.

What do you think about that? Does this test was also informative for you? Or maybe I missed something that may change whole results – let me know!

Search in SharePoint from PowerApps

Inspired by this post I realized that built-in connectors does not allow to utilize SharePoint Search. So theoretically it is not possible to use SharePoint search from PowerApps. However using Flow as a middle layer you can call SharePoint Search and parse results for your needs. Let’s see how to do that.

Why you may find SharePoint Search useful in your app?

Let’s consider is it worth to have such possibility as using SharePoint Search from your PowerApps app. To answer this question let’s see what we can and cannot do using built-in connectors.

You can:

  • Get content of any list or library in a single SharePoint site
  • Read, Update, Delete elements of list or library
  • Use specific subsets of items (filtering, sorting) in delegate manner
  • Get content of Office 365 Groups
  • Get OneDrive content (only excel files)

You cannot:

  • Find all items of a specific Content Type across whole tenant
  • Get elements from list or library in a site – even if the list or library was created after the connector has been declared
  • List SP sites in your tenant
  • Get OneDrive for Business content (all kind of)

All above are limitation coming from OOB SharePoint connectors. So if you want workaround them this post will tell you how to achieve it.

PowerApps SharePoint Search Architecture

We need 3 components:

  • PowerApps: acts as front-end, provides screen and controls to user and also display results,
  • Flow: acts as back-end, call SharePoint search (also keeps SPO url) and pass results to PowerApps
  • SharePoint: contains all the data of course

Those components will communicate each other in following manner:

  1. PowerApps uses Flow connector to make a call to it
  2. Flow uses “Send an HTTP request to SharePoint” and then…
  3. …parse returned result to JSON
  4. Flow join all rows as string variable and pass it as to PowerApps as respond
  5. PowerApps filters out the data it needs

Let’s start building it! To not make this post too much long I’ll focus only on most important part skipping parts like header creation or pagination functionality.

Follow this link to download complete demo app (remember that url to SPO is in the flow)

Step 1: Create a PowerApp

First we need to create an app, add screen to it and add controls to the screen (if you don’t know how to do any of those please check out this post). Some parts that may need additional explanation:

  • numRowLimitNumber – number of items to return
  • btnCallFlow – this is invisible button that call Flow on OnSelect event. Other controls (like previous/next page buttons) can fire it using Select() function instead of duplicating code in it.
  • galSPSearchResultItems – gallery displaying results items
    • imgOpenInNewWindow – clicking it will open SharePoint item in browser
    • lblSPItemTitle – displays item Title
    • lblSPItemUniqueId – displays item UniqueId
    • lblSPItemRank – displays item ranking sum. Because why not 😉

Now let’s configure behavior of our controls.

  • On OnSelect action of the “Search” button put as follow:
Set(gblItemsToSkip,0);
Set(gblPaginationVisibility,false);
Select(btnCallFlow)
  • As you can see it fires btnCallFlow. On OnSelect action of that button we will call the flow
Clear(colSPSearchResultItems);
Set(
    gblRowLimitNumber,
    numRowLimitNumber.Text
);
Set(
    gblSearchResults,
    Searchforitemsintenant.Run(
        txtSearchPhrase.Text,
        numRowLimitNumber.Text,
        Text(gblItemsToSkip)
    )
);
<HERE WE WILL PUT CODE TO PARSE SP SEARCH RESULTS>
Set(
    gblPaginationVisibility,
    true
)

Now let’s add flow to our app. To do that click:
Action tab -> Flows button -> “Create a new flow”

Step 2: Create a Flow

On Microsoft Flow side add variables that will keep input parameters from PowerApps. Then add “Send and HTTP request to SharePoint”.

The Uri attribute contains function that replace apostrophe (‘) to empty sign in case user put ‘ in the search phrase (accidentally or intentionally) which will break the query:

_api/search/query?querytext='@{replace(variables('SearchQuery'),'''','')}'&clienttype='ContentSearchRegular'&selectproperties='UniqueId, Title, OriginalPath'&rowlimit=@{variables('RowLimit')}&startrow=@{variables('RowsToSkip')}

Next add Parse JSON with Body output in Content field and a Schema.

The schema however is a bit tricky because using sample (i.e. from search REST call using browser or Postman) may not include all variations of results (that was my case). So after quick debugging I’ve successfully created following schema – feel free to copy-paste it.

{
    "type": "object",
    "properties": {
        "odata.metadata": {
            "type": "string"
        },
        "ElapsedTime": {
            "type": "integer"
        },
        "PrimaryQueryResult": {
            "type": "object",
            "properties": {
                "CustomResults": {
                    "type": "array"
                },
                "QueryId": {
                    "type": "string"
                },
                "QueryRuleId": {
                    "type": "string"
                },
                "RefinementResults": {},
                "RelevantResults": {
                    "type": "object",
                    "properties": {
                        "GroupTemplateId": {},
                        "ItemTemplateId": {},
                        "Properties": {
                            "type": "array",
                            "items": {
                                "type": "object",
                                "properties": {
                                    "Key": {
                                        "type": "string"
                                    },
                                    "Value": {
                                        "type": "string"
                                    },
                                    "ValueType": {
                                        "type": "string"
                                    }
                                },
                                "required": [
                                    "Key",
                                    "Value",
                                    "ValueType"
                                ]
                            }
                        },
                        "ResultTitle": {},
                        "ResultTitleUrl": {},
                        "RowCount": {
                            "type": "integer"
                        },
                        "Table": {
                            "type": "object",
                            "properties": {
                                "Rows": {
                                    "type": "array",
                                    "items": {
                                        "type": "object",
                                        "properties": {
                                            "Cells": {
                                                "type": "array",
                                                "items": {
                                                    "type": "object",
                                                    "properties": {
                                                        "Key": {
                                                            "type": "string"
                                                        },
                                                        "Value": {
                                                            "type": [
                                                                "null",
                                                                "string"
                                                            ]
                                                        },
                                                        "ValueType": {
                                                            "type": [
                                                                "null",
                                                                "string"
                                                            ]
                                                        }
                                                    },
                                                    "required": [
                                                        "Key",
                                                        "Value",
                                                        "ValueType"
                                                    ]
                                                }
                                            }
                                        },
                                        "required": [
                                            "Cells"
                                        ]
                                    }
                                }
                            }
                        },
                        "TotalRows": {
                            "type": "integer"
                        },
                        "TotalRowsIncludingDuplicates": {
                            "type": "integer"
                        }
                    }
                },
                "SpecialTermResults": {}
            }
        },
        "Properties": {
            "type": "array",
            "items": {
                "type": "object",
                "properties": {
                    "Key": {
                        "type": "string"
                    },
                    "Value": {
                        "type": "string"
                    },
                    "ValueType": {
                        "type": "string"
                    }
                },
                "required": [
                    "Key",
                    "Value",
                    "ValueType"
                ]
            }
        },
        "SecondaryQueryResults": {
            "type": "array"
        },
        "SpellingSuggestion": {
            "type": "string"
        },
        "TriggeredRules": {
            "type": "array"
        }
    }
}

At the end, we just have to join rows (using some special separator like “/n” which is unique enough) and pass it back to PowerApps along with totalRows number

If you did everything properly your Flow should look like this

Now we can get back to PowerApps and parse the results.

Step 3: Parsing results in the PowerApps

Flow pass result to PowerApps in a string field (called “results”). But we cannot use it in a gallery right away. Just look at it:

{"Cells":[{"Key":"Rank","Value":"17.1283779144287","ValueType":"Edm.Double"},{"Key":"DocId","Value":"17594717461461","ValueType":"Edm.Int64"},{"Key":"Title","Value":"Michał Guzowski Team Site","ValueType":"Edm.String"},{"Key":"PartitionId","Value":"2037f0e8-05e7-4df7-bbe9-b8cf7c8af72a","ValueType":"Edm.Guid"},{"Key":"UrlZone","Value":"0","ValueType":"Edm.Int32"},{"Key":"Culture","Value":"en-US","ValueType":"Edm.String"},{"Key":"ResultTypeId","Value":"0","ValueType":"Edm.Int32"},{"Key":"RenderTemplateId","Value":"~sitecollection/_catalogs/masterpage/Display Templates/Search/Item_Default.js","ValueType":"Edm.String"}]}"/n"{"Cells":[{"Key":"Rank","Value":"17.0755615234375","ValueType":"Edm.Double"},{"Key":"DocId","Value":"17595142086123","ValueType":"Edm.Int64"},{"Key":"Title","Value":"pl","ValueType":"Edm.String"},{"Key":"PartitionId","Value":"2037f0e8-05e7-4df7-bbe9-b8cf7c8af72a","ValueType":"Edm.Guid"},{"Key":"UrlZone","Value":"0","ValueType":"Edm.Int32"},{"Key":"Culture","Value":"en-US","ValueType":"Edm.String"},{"Key":"ResultTypeId","Value":"0","ValueType":"Edm.Int32"},{"Key":"RenderTemplateId","Value":"~sitecollection/_catalogs/masterpage/Display Templates/Search/Item_Default.js","ValueType":"Edm.String"}]}"/n"{"Cells":[{"Key":"Rank","Value":"17.0755615234375","ValueType":"Edm.Double"},{"Key":"DocId","Value":"17595383574480","ValueType":"Edm.Int64"},{"Key":"Title","Value":"en","ValueType":"Edm.String"},{"Key":"PartitionId","Value":"2037f0e8-05e7-4df7-bbe9-b8cf7c8af72a","ValueType":"Edm.Guid"},{"Key":"UrlZone","Value":"0","ValueType":"Edm.Int32"},{"Key":"Culture","Value":"en-US","ValueType":"Edm.String"},{"Key":"ResultTypeId","Value":"0","ValueType":"Edm.Int32"},{"Key":"RenderTemplateId","Value":"~sitecollection/_catalogs/masterpage/Display Templates/Search/Item_Default.js","ValueType":"Edm.String"}]}"/n"{"Cells":[{"Key":"Rank","Value":"17.0755615234375","ValueType":"Edm.Double"},{"Key":"DocId","Value":"17595390074495","ValueType":"Edm.Int64"},{"Key":"Title","Value":"fr","ValueType":"Edm.String"},{"Key":"PartitionId","Value":"2037f0e8-05e7-4df7-bbe9-b8cf7c8af72a","ValueType":"Edm.Guid"},{"Key":"UrlZone","Value":"0","ValueType":"Edm.Int32"},{"Key":"Culture","Value":"en-US","ValueType":"Edm.String"},{"Key":"ResultTypeId","Value":"0","ValueType":"Edm.Int32"},{"Key":"RenderTemplateId","Value":"~sitecollection/_catalogs/masterpage/Display Templates/Search/Item_Default.js","ValueType":"Edm.String"}]}"/n"{"Cells":[{"Key":"Rank","Value":"17.0755615234375","ValueType":"Edm.Double"},{"Key":"DocId","Value":"17595412154536","ValueType":"Edm.Int64"},{"Key":"Title","Value":"da","ValueType":"Edm.String"},{"Key":"PartitionId","Value":"2037f0e8-05e7-4df7-bbe9-b8cf7c8af72a","ValueType":"Edm.Guid"},{"Key":"UrlZone","Value":"0","ValueType":"Edm.Int32"},{"Key":"Culture","Value":"en-US","ValueType":"Edm.String"},{"Key":"ResultTypeId","Value":"0","ValueType":"Edm.Int32"},{"Key":"RenderTemplateId","Value":"~sitecollection/_catalogs/masterpage/Display Templates/Search/Item_Default.js","ValueType":"Edm.String"}]}"/n"{"Cells":[{"Key":"Rank","Value":"17.0755615234375","ValueType":"Edm.Double"},{"Key":"DocId","Value":"17595412284536","ValueType":"Edm.Int64"},{"Key":"Title","Value":"de","ValueType":"Edm.String"},{"Key":"PartitionId","Value":"2037f0e8-05e7-4df7-bbe9-b8cf7c8af72a","ValueType":"Edm.Guid"},{"Key":"UrlZone","Value":"0","ValueType":"Edm.Int32"},{"Key":"Culture","Value":"en-US","ValueType":"Edm.String"},{"Key":"ResultTypeId","Value":"0","ValueType":"Edm.Int32"},{"Key":"RenderTemplateId","Value":"~sitecollection/_catalogs/masterpage/Display Templates/Search/Item_Default.js","ValueType":"Edm.String"}]}"/n"{"Cells":[{"Key":"Rank","Value":"17.0755615234375","ValueType":"Edm.Double"},{"Key":"DocId","Value":"17595451564436","ValueType":"Edm.Int64"},{"Key":"Title","Value":"sv","ValueType":"Edm.String"},{"Key":"PartitionId","Value":"2037f0e8-05e7-4df7-bbe9-b8cf7c8af72a","ValueType":"Edm.Guid"},{"Key":"UrlZone","Value":"0","ValueType":"Edm.Int32"},{"Key":"Culture","Value":"en-US","ValueType":"Edm.String"},{"Key":"ResultTypeId","Value":"0","ValueType":"Edm.Int32"},{"Key":"RenderTemplateId","Value":"~sitecollection/_catalogs/masterpage/Display Templates/Search/Item_Default.js","ValueType":"Edm.String"}]}"/n"{"Cells":[{"Key":"Rank","Value":"17.0755615234375","ValueType":"Edm.Double"},{"Key":"DocId","Value":"17595498094501","ValueType":"Edm.Int64"},{"Key":"Title","Value":"lv","ValueType":"Edm.String"},{"Key":"PartitionId","Value":"2037f0e8-05e7-4df7-bbe9-b8cf7c8af72a","ValueType":"Edm.Guid"},{"Key":"UrlZone","Value":"0","ValueType":"Edm.Int32"},{"Key":"Culture","Value":"en-US","ValueType":"Edm.String"},{"Key":"ResultTypeId","Value":"0","ValueType":"Edm.Int32"},{"Key":"RenderTemplateId","Value":"~sitecollection/_catalogs/masterpage/Display Templates/Search/Item_Default.js","ValueType":"Edm.String"}]}"/n"{"Cells":[{"Key":"Rank","Value":"17.0755615234375","ValueType":"Edm.Double"},{"Key":"DocId","Value":"17595513184435","ValueType":"Edm.Int64"},{"Key":"Title","Value":"ro","ValueType":"Edm.String"},{"Key":"PartitionId","Value":"2037f0e8-05e7-4df7-bbe9-b8cf7c8af72a","ValueType":"Edm.Guid"},{"Key":"UrlZone","Value":"0","ValueType":"Edm.Int32"},{"Key":"Culture","Value":"en-US","ValueType":"Edm.String"},{"Key":"ResultTypeId","Value":"0","ValueType":"Edm.Int32"},{"Key":"RenderTemplateId","Value":"~sitecollection/_catalogs/masterpage/Display Templates/Search/Item_Default.js","ValueType":"Edm.String"}]}"/n"{"Cells":[{"Key":"Rank","Value":"17.0754928588867","ValueType":"Edm.Double"},{"Key":"DocId","Value":"17594717461464","ValueType":"Edm.Int64"},{"Key":"Title","Value":"How To Use This Library","ValueType":"Edm.String"},{"Key":"PartitionId","Value":"2037f0e8-05e7-4df7-bbe9-b8cf7c8af72a","ValueType":"Edm.Guid"},{"Key":"UrlZone","Value":"0","ValueType":"Edm.Int32"},{"Key":"Culture","Value":"en-US","ValueType":"Edm.String"},{"Key":"ResultTypeId","Value":"0","ValueType":"Edm.Int32"},{"Key":"RenderTemplateId","Value":"~sitecollection/_catalogs/masterpage/Display Templates/Search/Item_Default.js","ValueType":"Edm.String"}]}

How to extract specific parts of that?

  • Split string with our special delimiter: “/n”
    • For each string part we split it once again using following scheme:
      • “_FieldName_”,”Value”:
      • I.e. for Title field it will looks like this “Title”,”Value”:
      • Also we need to encode quote mark (“) so example after encoding looks like this: Char(34)&”Title”&Char(34)&”,”&Char(34)&”Value”&Char(34)&Char(58)&Char(34)
    • We take second element (above split always returns only 2 elements) and split one more time using following scheme:
      • “,”ValueType
      • After encoding it look like this: Char(34)&”,”&Char(34)&”ValueType”
    • We take first element (above split always returns 2 elements) and add it as value of a specific column.

Wow, felt a little dizzy? Don’t worry. Just copy below code, paste it in your app and replace name “Title” with field name you want to extract.

ClearCollect(
    sposearchitems,
    AddColumns(
        Split(
            Items,
            "/n"
        ),
        "Title",        First(Split(Last(Split(Result,Char(34)&"Title"&Char(34)&","&Char(34)&"Value"&Char(34)&Char(58)&Char(34))).Result,Char(34)&","&Char(34)&"ValueType")).Result
    )
)

In my case (for fields UniqueId, Title, OriginalPath and Rank) my parse operation looks like this:

Step 4: Display results

Finally! We made up to this part. Just set the values of labels in the gallery and enjoy the results!

For me the final result looks like below but your can be totally different (and better than mine ;] )

THAT’S IT! Wasn’t that hard, was it? 😉 If it was, remember that you can download my Demo SharePoint Search PowerApps application to compare or just copy paste some parts – just click here!

Hope you find this post useful. If so please share it and comment if you like.

Thanks and have a great coding 🙂

Update 22.02.2019 – If you’re curious if you can use Flow for parse computations I’ve done such comparison in my next blog post.

26.02.2019 – O365 User Group PL Warszawa #1

Breaking news: I will be a speaker on the first O365 User Group PL Warszawa meeting. Woohoo!

I will tell about how to build smart app that enthused MVPs and Microsoft employees around the world (also known as “the story of 1 tweet” 😉). But I’m just a shadow of the others: hosts Michał Słowikowski and Kamil Bączyk and another speaker: Microsoft Teams Product Group representative: Jace Moreno !

O365 User Group PL Warszawa #1

Tuesday, Feb 26, 2019, 6:00 PM

Microsoft Polska
al. Jerozolimskie 195A Warszawa, PL

62 Członkowie Went

Zapraszamy na inauguracyjne spotkanie grupy Office 365 w Warszawie. Jako, że mamy wyjątkową okazję to sesje i agenda również takie będą. Podczas tego spotkania poruszymy tematy związane z platformami Teams oraz PowerApps. Agenda: 18:00 – 18:15 Intro 18:15 – 19:05 Unleashing the Power of the Microsoft Teams Platform 19:05 – 19:15 Przerwa 19:15 – 20:…

Check out this Meetup →