Vue lecture

Il y a de nouveaux articles disponibles, cliquez pour rafraîchir la page.
✇michelcarlo

Handling variables in SharePoint custom forms built with Power Apps

It’s possible to create custom forms for SharePoint lists/libraries using Power Apps, directly from the list command bar by using the option Integrate/Power Apps/Customize the form:

This allows you to create a custom form using all features that a Canvas app offers. While you can keep all the out-of-the-box SharePoint list view native features, such as sorting, filtering, grouping & using JSON formatting, you will be able to build an entire new form by using the Canvas apps studio.

Variables and form behaviour

It’s great to be able to customize the form only and quickly build more advanced forms by using Power Fx and Canvas apps features, however it’s important to bear in mind how variables work.

The event Screen.OnVisible, will run only by on the first time you open an item in a list/view, OR if you create multiple screens and navigate to it. This means that when you select another item in the view, the event Screen.OnVisible is not going to be triggered automatically. For a person used to work with Canvas apps this can cause some confusion and maybe lead to a few bugs in the form if the behaviour is not understood when building the form.

Based on this, even though you can use context variables, they might not be that useful if you want to control data related to specific items or form instances open. For example if you have a form with multiple tabs and want to store the selected tab value in a variable, using context variables won’t be much help.

Overcoming the behaviour

Every SharePoint list custom form built with Power Apps has integration events that are triggered when interact with the item and the form is open or closed.

You can find those events and add Power Fx formulas to them in the SharePoint integration object:

There are 5 available events:

  • OnNew: triggers when the form is open to create a new item
  • OnEdit: triggers when the form is open to edit an existing item
  • OnView: triggers when the form is open to view an existing item
  • OnSave: triggers when the save button is clicked
  • OnCancel: triggers when the cancel button is clicked

You can use global variables in your app, and reset them in those events if needed, so if you load another item from the list, it won’t be getting wrong variable values.

Bear in mind those events are triggered from the Power Apps form only, so if you are using quick edit view, they will not be triggered.

Conclusion

By using the SharePoint integration events we can proper handle variables in a custom form.

References

Customize a form for a SharePoint list or library – Microsoft learn

The post Handling variables in SharePoint custom forms built with Power Apps appeared first on michelcarlo.

✇michelcarlo

Customize the SharePoint command bar icons and titles with JSON formatting

Previously I posted about hiding buttons in a SharePoint list using JSON formatting using the command bar customization.

The same customization features can be used to edit the buttons icons and titles, for example, below we have a custom bar that replaced some of the native buttons icons and text.

By adding values to the ‘text‘ and ‘iconName‘ properties we can accomplish this.

For example, if we apply the below JSON snippet as view formatter in a view:

{
    "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/row-formatting.schema.json",
    "commandBarProps": {
      "commands": [
        {
          "key": "new",
          "text": "Add a new Event Session",
          "iconName": "Feedback"
        },
        {
          "key": "export",
          "text": "Export this list"       
        },
        {
          "key": "automate",
          "text": "Workflows",
          "iconName" : "WorkFlow"
           
        },
        {
          "key": "integrate",
          "text": "Power Platform",
          "iconName": "rocket"       
        }
      ]
    }
  }

It will replace the native icons/text for the buttons/menus:

  • New: Change the icon and change the text to ‘Add a new Event Session’
  • Export: Change the text to export this list
  • Automate: Change the icon, and change the text to ‘Workflows’
  • Integrate: Change the icon, and change the text to ‘Power Platform’

So the command bar will change from:

To:

Finding icons to use

The icons you can use to customize the command bar are the same as Microsoft’s Fluent UI, you can search them and grab the name on this page: Fluent UI Icons

Conclusion

By using JSON formatting we can easily change icons and text for list command bar buttons. Bear in mind the changes affect only the view where you apply them, they need to be manually applied in every view you want them to take effect.

Reference

Command bar customization syntax reference – Microsoft Learn

The post Customize the SharePoint command bar icons and titles with JSON formatting appeared first on michelcarlo.

✇michelcarlo

Microsoft Forms: Hiding the ‘Untitled Form’ label in forms without a title

If we want to create custom headers for Microsoft Forms, as we don’t have many customisation options, an alternative way would be to create a custom image.

But if we want to add the form title to the image and leave it as blank as below:

Forms always will set the title as ‘Untitled Form’ when you save it, even if you add spaces to it:

However, it turns out that if we add the ‘zero-width space character‘ to the form title, it is preserved:

To add this character, you can simply copy it using the button below, and paste it into your Form title:

And that’s it!

Important to remember that as the form had the title removed, it will appear without a title in your forms list:

Note:The image size that worked best for me was 1100×100 for the custom image. When editing the form it won’t show in full size but when playing the form from the shared link it will display properly.

The post Microsoft Forms: Hiding the ‘Untitled Form’ label in forms without a title appeared first on michelcarlo.

✇michelcarlo

Making a Canvas app become Teams & SharePoint theme aware (with the help of the PnP Enhanced Power Apps WebPart)

By detecting the theme parameter that Teams passes to Power Apps canvas apps when added as Tabs or Personal apps, we are able to make them Teams theme aware, but the same does not happen when we add a Canvas app to SharePoint using the standard Power Apps WebPart.

However, there is a free open-source sample in the Microsoft 365 PnP sp-dev-fx-webparts Repository (Enhanced Power Apps WebPart) that we can use to help achieving that. This WebPart adds extra features, such as dynamic resizing, theme awareness, and dynamic data detection.

Configuring theme variables in the Canvas App / Preparing it to be theme aware

If you have the App.OnStart function enabled in your app, use the following code on it, otherwise use it in the Screen.OnVisible event of the screen of your Start screen:

With(
    {tmpTheme: Param("theme")},
    If(
        !IsBlank(tmpTheme),//If this parameter is not blank, App is running on Teams
        Set(
            appTheme,
            {
                bodyBackground: If(
                    tmpTheme = "dark",
                    RGBA(31,31,31,1),
                    tmpTheme = "contrast",
                    Black,
                    RGBA(245,245,245,1)
                ),
                bodyText: If(
                    tmpTheme = "dark",
                    White,
                    tmpTheme = "contrast",
                    Yellow,
                    Black
                ),
                buttonBackground: If(
                    tmpTheme = "dark",
                    RGBA(98,100,167,0.2),
                    RGBA(98,100,167,1)
                ),
                buttonText: If(
                    tmpTheme = "dark",
                    White,
                    tmpTheme = "contrast",
                    Yellow,
                    White
                )
            }
        ),
        //Otherwise it is in SharePoint, or Standalone. 
        //Check values passed by the WebPart, otherwise uses a default one
        Set(
            appTheme,
            {
                bodyBackground: ColorValue(
                    Coalesce(
                        Param("bodyBackground"),
                        "white"
                    )
                ),
                bodyText: ColorValue(
                    Coalesce(
                        Param("bodyText"),
                        "black"
                    )
                ),
                buttonBackground: ColorValue(
                    Coalesce(
                        Param("primaryButtonBackground"),
                        "gray"
                    )
                ),
                buttonText: ColorValue(
                    Coalesce(
                        Param("primaryButtonText"),
                        "white"
                    )
                )
            }
        );
    )
);

The above code checks for the Teams theme parameter presence, and if it’s present it sets the colours according to Teams standards. The colours are not sent by Teams to the app, but by detecting the theme name we can manually set the variable value to the same colour schema.

If the Teams theme is not present, it means the app is running either as standalone, or as part of a page with the Enhanced Power Apps WebPart added. Then in this piece, the values configured earlier are checked, in case they are blank, default values are used by using the coalesce function.

Using the theme to make the app colours become dynamic

In this post’s sample app, the theme variable colours will have the following usage:

bodyBackground: colour for app body background, galleries background

bodyText: colour for common text in the app/galleries

buttonText: to be used in button text font colour

buttonBackground: to be used in buttons background, header background, icon colours. The same colour can be used in PressedFill / HoverFill with the help of the ColorFade function to give us the hover/click feel.

Sample properties for a button:

To make dynamic colours as in the session level field we use in the app’s galleries (button in view mode instead of a standard label in order to be able to use border radius):

We can use the colorfade function based on the session level value (choice) as below:

ColorFade(appTheme.buttonBackground,-1 * (Value(Coalesce(ThisItem.'Session Level'.Value,"0"))/1000))

This will make the buttons look darker as the session level field value increases.

Download the WebPart / Install it

The next step is to install the open-source PnP Enhanced Power Apps Webpart.

You can download the full source code and compile it:

https://github.com/pnp/sp-dev-fx-webparts/tree/main/samples/react-enhanced-powerapps

Or download the sppkg file directly to install from the direct link:

https://github.com/pnp/sp-dev-fx-webparts/tree/main/samples/react-enhanced-powerapps/sharepoint/solution

You will need to upload the WebPart either to the global app catalog, or to a site collection app catalog, in case you want to restrict it to a single SharePoint site collection. After uploading the WebPart and installing it to the site you want, now you need to add the WebPart to a SharePoint page.

Add the WebPart to a SharePoint page

After the WebPart is deployed & installed to the site, create a page and find the WebPart to add it from the gallery (preferrably to a one-column section):

Add the WebPart link, and select the settings you wish for layout. My preference is to keep it without borders and set fixed height (responsiveness works better this way):

Select also the theme properties to send as parameter:

In this example we will need the following properties:

  • bodyBackground
  • bodyText
  • primaryButtonBackground
  • buttonText

There are more useful properties, but as in the Canvas App we are using colour fading options, in this case those 4 are enough to illustrate the idea. Save the page and you are now good to go.

If you want to add the Canvas App to teams as a Teams app, you can easily do that from the Canvas App web player, from the top right side menu:

Then select where to add it in Teams:

Or alternatively, export a deployment package from the maker portal and deploy it globally from the Teams Admin center.

Results

Now, according to where you use the Canvas app, the theme will be dynamically detected and it will adjust itself as below.

Standalone Canvas App outside of SharePoint:

Canvas App added to a SharePoint page in a Site with bright themes:

Canvas App added to a SharePoint page in a Site with a dark theme:

App installed in Teams running Default theme:

App installed in Teams running Dark theme:

Conclusion

By detecting querystring parameters sent to a Canvas App and with the help of the PnP Enhanced Power Apps WebPart, we are able to make the same Canvas app be aware of the themes of SharePoint and Teams.

The post Making a Canvas app become Teams & SharePoint theme aware (with the help of the PnP Enhanced Power Apps WebPart) appeared first on michelcarlo.

✇michelcarlo

Hiding the New and Upload buttons from a SharePoint document library using JSON list formatting

Recently I got a query about hiding the New and Upload buttons for a SharePoint library, because there was a need to allow users to browse documents using out-of-the-box SharePoint views in a library while still having permissions to upload files so that they could upload files using an SPFx WebPart or a Canvas App.

This request can easily be achieved using list formatting, by adding customisations to the command bar to hide some buttons as below:

Items to hide/JSON content

Using list formatting, there is an option to hide an out-of-the-box SharePoint button from the command bar in a view (for both lists and libraries).

To hide the New and Upload buttons from a view, you can simply use the below JSON, by mentioning the command key, and the property ‘hide‘ as true:

{
    "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/row-formatting.schema.json",
    "commandBarProps": {
      "commands": [
        {
          "key": "new",
          "hide": true
        },
        {
          "key": "upload",
          "hide": true
        }
      ]
    }
  }
  

Although I also recommend if that is the purpose, you also hide the ‘Sync’, ‘Add shortcut to OneDrive’ and ‘Pin to quick access’ options, to avoid the users bypassing your custom upload form. You can use the below JSON formatting to do so:

{
  "$schema": "https://developer.microsoft.com/json-schemas/sp/v2/row-formatting.schema.json",
  "commandBarProps": {
    "commands": [
      {
        "key": "new",
        "hide": true
      },
      {
        "key": "upload",
        "hide": true
      },
      {
        "key": "sync",
        "hide": true
      },
      {
        "key": "addShortcut",
        "hide": true
      },
      {
        "key": "pinToQuickAccess",
        "hide": true
      }
    ]
  }
}

See below the difference from a view with all the buttons, and another with hidden buttons:

If you intend to hide the buttons for the whole library, you will need to apply the JSON formatting content in all library views.

Conclusion

By using a simple JSON formatting template, we are able to hide buttons from a view in SharePoint.

Important to note that, those customisations do not take effect on SharePoint mobile apps.

Reference

Command bar customization reference – Microsoft Learn

The post Hiding the New and Upload buttons from a SharePoint document library using JSON list formatting appeared first on michelcarlo.

✇michelcarlo

Build powerful Adaptive Card experiences for Teams using Cards for Power Apps

Cards For Power Apps (Preview) is a new type of app in the Power Apps family, designed to be used as mini apps instead of full-fledged web pages or mobile apps as normally Canvas apps are used to build.  Cards are based on the same technology that powers Adaptive Cards. 

As Cards for Power Apps support Power Fx, logic and data manipulation can be easily done with PowerFx and also with the help of Power Platform connectors, instead of tweaking JSON content or building external applications or Power Automate flows to parse the data.  

By now only Microsoft Dataverse is available, but more connectors will be supported in the future. 

Creating cards 

To create cards, from the maker portal, check the new option called ‘Cards (Preview)’, where you can see all your cards or create a new card (if it’s already available in your tenant): 

The Power Apps cards drag & drop no-code card designer allows quick card design and behaviours setup (but still allows editing the cards using JSON). 

The card designer also uses the screen concept like a Canvas app uses, enabling multiple cards to be part of the same card app. Navigation between cards can be controlled using custom Power Fx code: 

Variables usage 

A new variable persistence concept is introduced in Cards for Power Apps, and also in order to use variables, the variables need to be explicitly configured in the app: 

Two persistence types for variables are available to use in Cards: 

  • Temporary: The value is reset in each card session
  • Permanent: The value is persistent across card sessions in the same card instance, even if the card is sent to different users. Worth noting if you run the card to grab its shareable URL, it will generate a new instance, that then would clear the variable values. You can note that by each time a shareable link is generated, a different instance identifier is used in the end, e.g: https://make.powerapps.com/environment/<env-id>/cards/play/<card-id>/<card-instance-id>  

The same Set function is used to update variables in a Card: 

Connectors usage 

To add a new connector, the process is similar to a Canvas app, from the Data pane, you can select Dataverse, select a connection, and pick a table to be used: 

Then you will be able to use standard Power Fx formulas such as Filter, Lookup, Patch and Collect to manipulate Dataverse data. 

Updating data / Adding data to Dataverse tables

Slight differences in the approach for updating data from Cards: 

To update an existing item, you can run the following Power Fx code from a button: 

Patch(prefix_yourtablename,LookUp(prefix_yourtablename,Name = txtNameFilter),{ Comment : "Updated from Cards!"})

If you want to reference a choice set, text box or other control’s value/selection, simply use the control name instead:

Patch(prefix_yourtablename, LookUp(prefix_yourtablename, Name = txtNameFilter), { Comment: myTextInput })

But for new items, patching with defaults needs to be replaced with a Collect function call (so far by now it is the only supported way), for example normally in a Canvas app we would do something like: 

Patch('Your Table Name', Defaults('Your Table Name'), { Name: "Customer Name" } )  

But in cards we need to use collect, as below: 

Collect(prefix_yourtablename, { Name: "Customer Name" } ) 

Sharing the cards in teams

From the Cards for Power Apps player, by clicking the ‘Send’ button you can get a shareable link. 

After this link is pasted in a teams chat, the link will automatically render the card directly within the conversation and users can interact with it: 

Conclusion 

With Cards for Power Apps, quick and powerful Adaptive-card experiences can be built to be used within Teams. 

Instead of the standard process of purely using JSON to design Adaptive Cards and handling logic with a full custom Teams app/bot (which also requires additional setup as configuring an Azure AD app for your bot application) or logic in separate workflows built with Power Automate/Logic Apps, with Cards you quickly build interactive cards with a drag-and-drop designer, connect to data using Power Platform connectors and easily add logic using Power Fx language.

There are a few differences on Power Fx usage, some of which are documented by Microsoft here:
Power Fx and Cards – Microsoft Learn

Cards is still under Preview and it’s usage or features may change before going GA.

👉Follow me on Twitter and LinkedIn for Microsoft 365 and Power Platform updates and tips!

References

Cards for Power Apps overview – Microsoft Learn

The post Build powerful Adaptive Card experiences for Teams using Cards for Power Apps appeared first on michelcarlo.

✇michelcarlo

Ignite 2022: Curated list of posts from Microsoft related to Microsoft 365 and Power Platform

Microsoft Ignite 2022 brought several amazing announcements across all the Microsoft cloud platform.

If you interested in updates related to Microsoft 365 collaboration tools (SharePoint/Teams/Viva & related) and the Power Platform and want to know more details, or in case you missed any updates, here is a curated list of posts from Microsoft official blogs & sites released during Ignite with most of the relevant news:

SharePoint

Microsoft Lists announcements at Ignite 2022

Introducing Microsoft Syntex: Context AI in the flow of work

What’s new in Security and Management in SharePoint, OneDrive, and Teams – Microsoft Ignite 2022

Stream (on SharePoint) is now generally available

Microsoft Viva

Announcing new Microsoft Viva IT Admin features

Connect daily work to OKRs with our latest Viva Goals integrations

Microsoft Ignite 2022: Innovations and roadmap for Microsoft Viva

Microsoft Viva Insights – new productivity and wellbeing experiences coming soon

Storyline in Viva Engage and Microsoft 365 is now generally available

Viva Learning announcements at Ignite 2022

Viva Topics: New adoption dashboard and experiences in Teams Channels, Viva Connections and Outlook

What’s new in Viva Connections

Microsoft Teams

Enhance collaboration with Microsoft Teams chat and channels features for the hybrid workplace

Introducing Mesh avatars for Microsoft Teams in Private Preview

Introducing Microsoft Teams Premium, the better way to meet

What’s New in Microsoft Teams | Microsoft Ignite 2022

Microsoft 365 Developmemt

Boost your Microsoft Teams app experience with new link unfurling capabilities

Ignite 2022: Transforming collaboration with low and pro code dev tools

Scale access to Microsoft 365 data with Microsoft Graph Data Connect

Updates to Microsoft Teams API in Microsoft Graph 

Updates to the Planner API in Microsoft Graph

What’s new for Office Add-ins at Ignite 2022

Microsoft 365 – Other Apps

Introducing Microsoft Places: Turn your spaces into places

From bolt-on to built-in information protection in Microsoft 365 Apps

Customize retention and deletion to help meet your specific business requirements

Introducing new AI enhancements in Microsoft 365: New features coming to Microsoft Editor and more!

Microsoft Editor using Context IQ in Outlook on the web and Word for the web coming soon!

Microsoft Loop at Ignite 2022

Power Platform

Leverage low-code to do more with less at Microsoft Ignite 2022 

The future of low-code governance with Managed Environments for Power Platform

Microsoft Power Pages is now generally available

New ways to innovate with AI and Microsoft Power Automate

Power BI: Introducing Cross-tenant Power BI Dataset Sharing

Power BI: Microsoft Ignite 2022: Do more with enterprise self-service business intelligence

Power Automate: Automate Document Processing end-to-end with AI Builder

Power Automate: Begin your Robotic Process Automation modernization journey

Satya Nadella Ignite 2022 Keynote

Satya Nadella Ignite 2022 Keynote – YouTube

Ignite 2022 Book of News

Ignite 2022 Book of News (Updates across all Microsoft Cloud)

Final thoughts

Did you find any additional interesting post? Feel free to leave the link in the comments!

Follow me on Twitter and LinkedIn for Microsoft 365 and Power Platform updates and tips!

The post Ignite 2022: Curated list of posts from Microsoft related to Microsoft 365 and Power Platform appeared first on michelcarlo.

✇michelcarlo

Calling Graph API using a flow and manipulating the results from Power Apps using the ParseJSON function

Recently I posted about using a generic flow to call the SharePoint Rest API from a canvas app and parse the results using the ParseJSON experimental function, in a way that we can almost simulate as if we could call the SharePoint Rest API from a canvas app.

The same technique can be applied to call Microsoft Graph API, as in the example below where we retrieve the list of group members from a Microsoft 365 group, including nested group members (an action that cannot be done using the standard Microsoft 365 Groups action):

Why call Graph if we have Office 365 products connectors and actions in Power Apps?

Even though there are several actions available for Office 365 products in Power Apps, they don’t fully cover what we can accomplish using Microsoft Graph. For example, some actions we could do with Graph that are not available out-of-the-box (explained below in this blog post):

  • Create a Microsoft 365 Group
  • List nested groups members from an Office 365 group
  • Dynamically detect the root SharePoint site of the tenant (useful if you want to grab this value and make an app or flow ‘tenant agnostic’ while running HTTP requests to SharePoint)

There is an existing and direct ‘Send an HTTP Request’ option from the Office 365 Groups connector in Power Apps canvas apps, but this option runs the queries but doesn’t return objects as results (it only returns a boolean). Hence, this technique of calling a Power Automate flow and returning the results is useful.

Before creating the flow and calling it from the Canvas App, enable the experimental feature as explained in my previous post.

Creating the Flow

To keep using only standard licenses, let’s use the action ‘Send an HTTP Request’ from the Office 365 connectors.

To simplify the use case, in this Flow let’s only require the Graph endpoint, method and request body in the Trigger (Power Apps V2):

Add a ‘Send an HTTP Request’ action from the Office 365 Groups connector after the trigger, as below. In this example, we already prepend the path ‘https://graph.microsoft.com’ to the field, so we can only specify the endpoint piece of Graph when calling it from Power Apps:

The final action is simply to pass the response back to Power Apps:

Sending requests and parsing the results from Power Apps

Save the flow with the name ‘GraphHTTP’ and add it to your canvas app from the Power Automate pane:

Now that the Flow is added, you can then call Graph from the flow and parse the results back as in the examples below.

Listing Group Members

The sample query below runs a GET request against the groups segment in Microsoft Graph and lists all group members (including nested members) using the Flow, stores it in a String variable named locResponseBody, parses it using the ParseJSON function and then converts it to a proper table of typed objects by using a combination of AddColumns + DropColumns formulas (adding custom columns with transformed values, then removing the original ‘Value‘ property), which is stored in a collection named colGroupMembers (replace yourGroupIdGuid by your Group Id).

UpdateContext(
    {
        locResponseBody: GraphHTTP.Run(
            "/v1.0/groups/efbc5736-1cf4-4df6-81b0-05136d3d992f/transitiveMembers/microsoft.graph.user",//Graph endpoint
            "GET",//HTTP Method           
            ""//Body, in case it's needed
        ).body
    }
);
ClearCollect(
    colGroupMembers,
    DropColumns(
        AddColumns(
            Table(ParseJSON(locResponseBody).value),
            "id",Text(Value.id),
            "displayName",Text(Value.displayName),
            "givenName",Text(Value.givenName),
            "surname", Text(Value.surname),
            "jobTitle",Text(Value.jobTitle),
            "mail",Text(Value.mail),
            "userPrincipalName",Text(Value.userPrincipalName),
            "businessPhones",ForAll(Table(Value.BusinessPhones),Text(Value)),
            "officeLocation",Text(Value.officeLocation),                        
            "preferredLanguage",Text(Value.preferredLanguage),
            "mobilePhone",Text(Value.mobilePhone)
        ),
        "Value"
    )
)

Creating a Microsoft 365 Group

In the example below, the Flow is used to call Graph and create a Microsoft 365 group from a Canvas App (and store the response as an object in the local variable locGroupObject) by calling a POST request against the groups segment in Graph and passing the details of the group to be created in the request body:

UpdateContext(
    {
        locResponseBodyGroupAdded: GraphHTTP.Run(
            "/v1.0/groups",//Graph endpoint
            "POST",//HTTP Method                      
            "{
                'description': 'test group 123',
                'displayName': 'test group description 123',
                'groupTypes': [
                   'Unified'
                 ],
                'mailEnabled': true,
                'mailNickname': 'testGroup123',
                'securityEnabled': false,
                'visibility': 'Private'
            }"//Body                       
        ).body
    }
);
UpdateContext(
    {
        locGroupObject: With(
            {jsonItem: ParseJSON(locResponseBodyGroupAdded)},
            {
                Id: Text(jsonItem.id),
                Description: Text(jsonItem.description),
                DisplayName: Text(jsonItem.displayName),
                GroupTypes: ForAll(
                    Table(jsonItem.groupTypes),
                    Text(Value)
                ),
                Mail: Text(jsonItem.mail),
                MailEnabled: Boolean(jsonItem.mailEnabled),
                MailNickname: Text(jsonItem.mailNickname),
                Visibility: Text(jsonItem.visibility)
            }
        )
    }
);

Getting the address of the SharePoint root site of the tenant

In the example below, the Flow is used to call Graph and retrieve the root SharePoint site address of the tenant by running a simple GET request against the sites/root segment in Graph:

UpdateContext(
    {
        gblTenantRoot: Text(
            ParseJSON(
                GraphHTTP.Run(
                    "/v1.0/sites/root",
                    "GET",
                    ""
                ).body
            ).webUrl
        )
    }
)

Conclusion

The standard action ‘Send an HTTP Request’ in the Office 365 Groups connectors does not give us objects as responses, but we can use a Power Automate flow to do the job in this case.

This enables extra scenarios for querying and actions in Graph beyond the standard ones, within the endpoints that are accepted by the ‘Send an HTTP Request’ action under Office 365 Groups.

Remember that the ParseJSON feature is experimental, so for now it should not be used in Production apps.

References

ParseJSON function in Power Apps (experimental) – Power Platform | Microsoft Docs

List members – Microsoft Graph

List transitive members – Microsoft Graph

Create group – Microsoft Graph

The post Calling Graph API using a flow and manipulating the results from Power Apps using the ParseJSON function appeared first on michelcarlo.

✇michelcarlo

Export a Power Apps gallery as PDF file using the new PDF function, and email it with the Outlook connector

With the recently experimental PDF feature that is available from Power Apps authoring versions 3.22094.* we are now able to export screens, galleries and containers to PDF and obtain the output of this export as bytes, and use it on the PDF viewer or send it to a flow, so we can save it to SharePoint, OneDrive and etc.

The advantage of this approach instead using the Print function to print screens is that we can get the full content of galleries/containers in a PDF, so we are not limited to only what is displayed in the screen.

The text in the PDF file exported using this function is also selectable, so we are here exporting ‘real’ PDFs, and not screenshots from screens into PDF files:

Sending the exported PDF in an email message

Consider you have a gallery with content you want to export as below. The gallery content is not fully visible as below:

The PDF export function is really simple, you can use it to generate content directly or to save it in variables to be used later.

But in this example let’s only call it directly from the Office 365 Outlook Connector (Send an email V2) action.

Add the Office 365 Outlook connector to your app, and then simply add the code as the example below to a button/icon to Export the gallery to PDF and send the content as an Attachment:

Office365Outlook.SendEmailV2(
    "user@tenant.onmicrosoft.com",
    "Your pdf",
    "Your PDF is attached",
    {
        From: User().Email,
        Attachments: Table(
            {
                ContentBytes: PDF(
                    galSessionsData,
                    {
                        Orientation: PaperOrientation.Portrait,//Portrait or Landscape
                        Size: PaperSize.A4,//Select your page size
                        DPI: 150,
                        ExpandContainers: true /* This property makes sure the full content of gallery/containers is expanded as PDF */
                    }
                ),
                Name: "Export.pdf"
            }
        )
    }
);

Note that the Attachments parameter in the SendEmailV2 action expects a table of attachment objects with the ContentBytes and FileName as parameters. As ContentBytes we are using the PDF function to export it directly and send in the Email.

For the PDF function, use the proper DPI and page sizes you wish, but keep the ExpandContainers property value as true if you want to export the full gallery.

Results

After the button is clicked, the recipient will receive an email with a PDF copy of the gallery attached, as below:

Note: As of now, the PDF export function will only export items that were already loaded in the app. So for example if you have a SharePoint list with 8000 items, by default the gallery component loads the items in batches as you scroll (not all the 8000 at first), and if you call the PDF function in a situation like this, it will export only the items that were already loaded into the gallery.

Reference

[New] Create PDF from Power Apps with PDF function by Hiro Nagao

The post Export a Power Apps gallery as PDF file using the new PDF function, and email it with the Outlook connector appeared first on michelcarlo.

✇michelcarlo

New Sorting actions for arrays/tables In Power Automate: sort & reverse

Until recently it was not possible to easily sort arrays or collections of objects in Power Automate using a single expression, either complex logic techniques or Office Scripts were required.

But recently two new handy expressions became available in Power Automate that make it really simple to do:

  • sort
  • reverse

How the sort expression work

The sort expression accepts either an array with simple values or a collection of objects.

If you pass a simple array to the expression, no parameter is needed. For example, if you have the following array variable with people’s names:

[
"Michel",
"Nick",
"Michael",
"Carlos",
"Renan"
]

By using the sort expression as below:

sort(variables('Names'))

You will get as output:

[
  "Carlos",
  "Michael",
  "Michel",
  "Nick",
  "Renan"
]

If you have an array/collection with objects, you need to specify a property to use in the sorting, so for example, consider an array variable named ‘NamesCountries’ as below:

[
	{
		"firstName": "Donovan",
		"lastName": "Kristovich",
		"country": "Georgia"
	},
	{
		"firstName": "Kory",
		"lastName": "Melot",
		"country": "Azerbaijan"
	},
	{
		"firstName": "Gabriel",
		"lastName": "Balenzuela",
		"country": "Hong Kong"
	},
	{
		"firstName": "Reed",
		"lastName": "Dunne",
		"country": "Cape Verde"
	},
	{
		"firstName": "Sylvester",
		"lastName": "Mavros",
		"country": "Sudan"
	}
]

The output of the below formula will sort the arrays by Country:

sort(variables('NamesCountries'),'country')

Note the country order: “Azerbaijan”, “Cape Verde”, “Georgia”, “Hong Kong”,”Sudan”

[
  {
    "firstName": "Kory",
    "lastName": "Melot",
    "country": "Azerbaijan"
  },
  {
    "firstName": "Reed",
    "lastName": "Dunne",
    "country": "Cape Verde"
  },
  {
    "firstName": "Donovan",
    "lastName": "Kristovich",
    "country": "Georgia"
  },
  {
    "firstName": "Gabriel",
    "lastName": "Balenzuela",
    "country": "Hong Kong"
  },
  {
    "firstName": "Sylvester",
    "lastName": "Mavros",
    "country": "Sudan"
  }
]

How the reverse function works

The reverse function will only revert an array order, regardless of whether it is sorted or not. So for example, if we run it against the initial array of names mentioned above as below:

reverse(variables('Names'))

The output will be a reversed order array from the original one:

[
  "Renan",
  "Carlos",
  "Michael",
  "Nick",
  "Michel"
]

There is no second parameter accepted in this expression. If we use it against an array of objects, it will simply reverse the order of it. For example, using the below expression on top of the array of objects mentioned above:

reverse(variables('NamesCountries'))

Gives the output a reversed array based on its initial order:

[
  {
    "firstName": "Sylvester",
    "lastName": "Mavros",
    "country": "Sudan"
  },
  {
    "firstName": "Reed",
    "lastName": "Dunne",
    "country": "Cape Verde"
  },
  {
    "firstName": "Gabriel",
    "lastName": "Balenzuela",
    "country": "Hong Kong"
  },
  {
    "firstName": "Kory",
    "lastName": "Melot",
    "country": "Azerbaijan"
  },
  {
    "firstName": "Donovan",
    "lastName": "Kristovich",
    "country": "Georgia"
  }
]

In case we need to sort items from a collection of objects/array in descending order, we can use a combination of both sort and reverse formulas.

For example, the below formula using the names/countries array:

reverse(sort(variables('NamesCountries'),'country'))

Will have as an output an array with items sorted by Country in descending order (“Sudan”,”Hong Kong”,”Georgia”,”Cape Verde”,”Azerbaijan”):

[
  {
    "firstName": "Sylvester",
    "lastName": "Mavros",
    "country": "Sudan"
  },
  {
    "firstName": "Gabriel",
    "lastName": "Balenzuela",
    "country": "Hong Kong"
  },
  {
    "firstName": "Donovan",
    "lastName": "Kristovich",
    "country": "Georgia"
  },
  {
    "firstName": "Reed",
    "lastName": "Dunne",
    "country": "Cape Verde"
  },
  {
    "firstName": "Kory",
    "lastName": "Melot",
    "country": "Azerbaijan"
  }
]

Conclusion

By using the new sort and reverse expressions we can easily sort arrays and collections of objects, and avoid using complex techniques as it was needed earlier.

The post New Sorting actions for arrays/tables In Power Automate: sort & reverse appeared first on michelcarlo.

✇michelcarlo

How to use Power Apps named formulas (experimental feature)

Recently Microsoft announced a new experimental feature in Power Apps: Named formulas

Named formulas in summary are, defined functions without parameters, that can be reused anywhere in a Canvas App.

What are the advantages of using Named formulas instead of global variables (defined with ‘Set’)?

The formula’s values are always available, there is no time dependency as it happens on App.OnStart (if you enabled delayed start, some variables might not have been populated when you try to access their values).

Formula definitions work like constants, they need to be defined in the App.Formulas property and cannot be updated anywhere else in the app

Also, the formula’s output values are only calculated when needed, which will speed up app loading times if you defined a lot of them in the App.OnStart event

How to use them?

Enable Named formulas under experimental features (authoring version 3.22091):

After enabling the feature and reloading the app, add your formulas to the App.Formulas property. You can even add objects as named formulas, for example, if you had an object variable that you used to store all colours for the app and work as the ‘app theme config’ variable, you can convert it to a named formula:

Call or reference them as if they were global variables from anywhere in the app (except for using ‘Set’, so for example Set(myFormula,”Value”) would not work.

In the example below we are using a reference to a named formula to define the button fill color:

And below using a reference to a record to retrieve the last item submitted by the current user. This would also return the latest item Id as the formula values are always up to date, and we don’t need to worry about refreshing their values as we do with global variables:

Conclusion

By using the named formulas feature you can speed up your app’s loading time in case you had a lot of global variables defined on the App.OnStart event, while enabling functions that are read-only and will always have their return values up to date.

The post How to use Power Apps named formulas (experimental feature) appeared first on michelcarlo.

✇michelcarlo

Creating a Planner Plan and adding it as a tab to the General channel of a Teams team using Power Automate & Microsoft Graph

Some time ago I blogged about using Power Automate to create Planner Plans and recently I got a query on that post about adding the created plan to the General channel of the related Team as a tab.

The procedure to add a Planner plan as a tab using Graph is not documented by Microsoft, but by investigating manually added examples (using Graph Explorer to retrieve the tab content format), we can figure out how the structure of a Planner tab works. Bear in mind this is not a documented procedure and may break if the tab setup structure change later.

Find your Team ID (Microsoft 365 Group ID)

Find the ID of the Group/Team (easily found under Groups in the Azure portal) you want to create the planner plan and add it as a Tab:

It will be needed in the Flow so we can create the Plan under it and also set up the tab in the related Team.

Creating the Flow

For demo purposes, let’s create a manually Triggered flow. This can be tweaked so your Flow is part of a bigger automation piece, so let’s add the Plan name input also as a variable, making the reference able to be changed easily if needed. We also need another variable to store the Tab Name (in this case we simply prepend ‘Planner – ‘ to the Plan name) and the Team ID (which you got from Azure AD):

Retrieving the Channel ID

Next, we need to retrieve the ID of the General channel. To do it we list all channels from the Team we chose, run a filter action on top of the list and save the first result in a variable:

The formula for the first entry ID (considering a renamed Filter array action as above):

first(body('Filter_array_-_Channels'))['Id']

Creating the Plan and parsing the created plan data

To create the plan we can use the ‘Send an HTTP Request’ action from the Office 356 connectors and run a call to Microsoft Graph, then parse the response using the ‘Parse JSON’ action as below:

The below schema can be used to parse the Request Body:

{
    "type": "object",
    "properties": {
        "@@odata.context": {
            "type": "string"
        },
        "@@odata.etag": {
            "type": "string"
        },
        "createdDateTime": {
            "type": "string"
        },
        "owner": {
            "type": "string"
        },
        "title": {
            "type": "string"
        },
        "id": {
            "type": "string",
            "description": "The Plan ID"
        },
        "createdBy": {
            "type": "object",
            "properties": {
                "user": {
                    "type": "object",
                    "properties": {
                        "displayName": {},
                        "id": {
                            "type": "string"
                        }
                    }
                },
                "application": {
                    "type": "object",
                    "properties": {
                        "displayName": {},
                        "id": {
                            "type": "string"
                        }
                    }
                }
            }
        }
    }
}

Save the plan ID in a variable as below:


Adding it as a Tab

The last step is to call a POST request in the Graph endpoint related to the Channel tabs with the Planner configuration as body, as below:

This will add Planner as a tab to the General channel of the Team, and specify the Plan to use in that tab.

Given that all the variables in the flow respect the names of the sample pictures above, the below code can be copied and pasted into your ‘Send an HTTP request’ action’s body. This is what instructs teams what are the configuration details for the Planner tab:

  {
    "displayName": "@{variables('TabName')}",
    "teamsApp@odata.bind": "https://graph.microsoft.com/v1.0/appCatalogs/teamsApps/com.microsoft.teamspace.tab.planner",
    "configuration": {
        "entityId": "@{variables('ChannelID')}",
        "contentUrl": "https://tasks.teams.microsoft.com/teamsui/{tid}/Home/PlannerFrame?page=7&auth_pvr=OrgId&auth_upn={userPrincipalName}&groupId={groupId}&planId=@{variables('PlanID')}&channelId={channelId}&entityId={entityId}&tid={tid}&userObjectId={userObjectId}&subEntityId={subEntityId}&sessionId={sessionId}&theme={theme}&mkt={locale}&ringId={ringId}&PlannerRouteHint={tid}",
        "removeUrl": "https://tasks.teams.microsoft.com/teamsui/{tid}/Home/PlannerFrame?page=13&auth_pvr=OrgId&auth_upn={userPrincipalName}&groupId={groupId}&planId=@{variables('PlanID')}&channelId={channelId}&entityId={entityId}&tid={tid}&userObjectId={userObjectId}&subEntityId={subEntityId}&sessionId={sessionId}&theme={theme}&mkt={locale}&ringId={ringId}&PlannerRouteHint={tid}",
        "websiteUrl": "https://tasks.office.com/{tid}/Home/PlanViews/@{variables('PlanID')}?Type=PlanLink&Channel=TeamsTab"
    }
}

Results

After running this Flow, a Plan will be added to the General tab of the specified team:

You can download the working flow from my Github samples repository if you prefer.

References

Create planner plans – Microsoft Graph

The post Creating a Planner Plan and adding it as a tab to the General channel of a Teams team using Power Automate & Microsoft Graph appeared first on michelcarlo.

❌