How to find {sitesId} to pass to MS Graph API call?

Summary

SharePoint related MS Graph API call requires {sitesid}, for example for the following API call we need {sitesId}

Create permission – Microsoft Graph v1.0 | Microsoft Docs

POST /sites/{sitesId}/permissions

Solution

Login to your SharePoint site. Go to the Graph Explorer, https://aka.ms/GE, enter the following assuming tenant as gov963094 and site as AdminProvisionApp.

https://graph.microsoft.com/v1.0/sites/gov963094.sharepoint.com:/sites/AdminProvisionApp?$select=id

You will get answer something like following.

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#sites(id)/$entity",
    "id": "gov963094.sharepoint.com,2e0ad342-19b2-4116-b6a5-2dc4867cb498,0efde304-9646-43d8-8eee-5b1a55ab17f1"
}

What you get back in the id is in this format:

{hostname},{spsite.id},{spweb.id}

Posted in MS Graph, SharePoint | Leave a comment

How to add custom banner to alert “SharePoint 2010 workflow retirement” to site users and owners?

Summary

The SharePoint 2010 workflow will retire. Microsoft announced it, see the following link.

SharePoint 2010 workflow retirement

For my customer, even after multiple messages to the Admins and Owners there was not an immediate action taken by the owners. To alert ‘SharePoint 2010 workflow retirement’ to all the identified sites my customer wants to add a banner similar to the following.

Banner for site with SharePoint 2010 Workflow

Solution

Prerequisite

  1. You should have the PnP PowerShell installed.
  2. You should have the SPFx development environment to create the .sppkg SPFx package.
  3. You should have configure and consented for PnP PowerShell on your tenant. Please follow this article.

Step # 1 : Create and install the SPFX application customizer for the modern site or page

Please click here to go to the GitHub Repo for the SPFx Application Customizer Extension.

Step # 2 : Add the JavaScript Link for the classic page or site

The JSLink file will allow to get the messages on the classic site or page.

https://github.com/pankajsurti/sp2010-alert-banner-app-extention/blob/master/DeploymentScript/AddSP2010BannerMessage.js

Create a folder c:\SP2010RetirementBanner copy the above JSLink file.

Step # 3 : Using the PnP PowerShell script add the banner for the list of sites in CSV file.

Copy the Process-AddRemoveBanner.ps1 in c:\SP2010RetirementBanner.

Create site2process.csv file in c:\SP2010RetirementBanner folder with the header as Url. Add your tenant’s site URL per line.

From c:\ SP2010RetirementBanner, run the following PowerShell command using

https://github.com/pankajsurti/sp2010-alert-banner-app-extention/blob/master/DeploymentScript/Process-AddRemoveBanner.ps1

# make sure the PS1 and js files are in the same directory i.e. c:\SP2010RetirementBanner

.\Process-AddRemoveBanner -ActionType "Add"

Step # 4 : If SP2010 workflow are removed, using the PnP PowerShell script Remove the banner for the list of sites in CSV file.

Run the following PowerShell command using

https://github.com/pankajsurti/sp2010-alert-banner-app-extention/blob/master/DeploymentScript/Process-AddRemoveBanner.ps1

# make sure the PS1 and js files are in the same directory i.e. c:\SP2010RetirementBanner

.\Process-AddRemoveBanner -ActionType "Remove"

Conclusion

This approach is only an awareness to the end users to think about the issue of the SP2010 workflow will retire soon so they can migrate to modern workflow using Power Automate.

Posted in PnP.PowerShell, SharePoint, SharePoint 2010, SharePoint 2013 | Leave a comment

Error loading debug manifests (debugManifestsFile)

Summary

I was creating a simple hello world application customizer using the following documentation.

Build your first SharePoint Framework Extension (Hello World part 1)

After following the steps and I tried to debug I got the following error.

When I searched for the solution on the web I saw Vesa mentioned with a tip that the web server may not be running. I did run “gulp server” and it should run the local web server.

I did more search and I got some suggested posts to delete the browser cache, log out from the SPO site.

Nothing worked.

Resolution

I went back to the documentation step by step, I have missed the following step.

gulp trust-dev-cert

For more details follow Trusting the self-signed developer certificate

Trusting the self-signed developer certificate

Posted in SharePoint, SharePoint 2010, SharePoint 2013 | Leave a comment

How to associate full screen Power Apps Canvas App with SharePoint List?

Summary

To customize a SharePoint list or library form by using Power Apps is well documented. You can visit this link to see details. But the issue with this approach is the form does not work as the full screen mode app. You may want to create a blank canvas app in full screen tablet mode.

If you want to associate your existing full screen canvas app with the SharePoint list, please read further…

Step By Step Solution

The solution is very simple, you still need to create a custom form as mentioned in the above link. You will change the SharePointIntegration Controls OnNew, OneEdit and OnView properties to launch your full screen canvas app. You would use the Launch method.

Step # 1 Get the Launch URL for your Full Screen Canvas app. Follow here

Step # 2 In your customize app go to SharePointIntegration Control. Modify OnNew with the code as defined below.

Note: there are four query string passed to the launch.

hidenavbar -> is to hide the navigation bar for your full screen app.

SelectedListItemID -> This will be used in the full screen app to navigate used to NewForm , EditForm or ViewForm

Env and AppVer -> These are optional if you want to pass some environment or version information. You can skip if you like.

SharePointIntegration Control’s OnNew property
//NewForm(SharePointForm1)
Launch(
    "/providers/Microsoft.PowerApps/apps/002a5c25-0b35-4d7d-89c7-653f8c0d1ea6",
    "hidenavbar",
    "true",
    "SelectedListItemID",
    "-1",
    "Env",
    varEnvironment,
    "AppVer",
    varAppVersion
);
RequestHide();

Step # 3 In your customize app go to SharePointIntegration Control. Modify OnEdit with the code as defined below.

Everything is same as the Step # 2 except the SelectedListitemID property is different.

SharePointIntegration control’s OnEdit property.
//EditForm(SharePointForm1)
Launch(
    "/providers/Microsoft.PowerApps/apps/002a5c25-0b35-4d7d-89c7-653f8c0d1ea6",
    "hidenavbar",
    "true",
    "SelectedListItemID",
    SharePointIntegration.SelectedListItemID,

    "EditMode",
    "yes",
    "Env",
    varEnvironment,
    "AppVer",
    varAppVersion    
);
RequestHide();

**** NOTE for OnView event ****
Repeat the above code for the OnView with "EditMode" as 'no' or just don't pass it, the default can be coded as 'no'

Step # 4 Modify the OnStart Event of you Full Screen App.

OnStart event for the Full Screen Canvas App
// Read all query string parameters
Set (
    varSelectedListItemID,
    Value(Param("SelectedListItemID"))
);


Set(
    varEditMode,
    Coalesce(
        Param("EditMode"),
        "No"
    )
);
// These variables are optional, you can use to display the version and env.
Set(
    varAppVersion,
    Coalesce(
        Param("AppVer"),
        "17.0"
    )
);
Set(
    varEnvironment,
    Coalesce(
        Param("Env"),
        "Development"
    )
);

Step # 5 Act on the value of the SelectedListItemID property in the full screen canvas app.

/// You need to change your DataSource
// if the ID is greater than zero and editmode is yes then
//      get the record for that ID
If (
    varSelectedListItemID > 0 && Lower(vaEditMode) = "yes",
    Set(
        varCurrentlySelectedRecord,
        LookUp(
            [[[ YOUR DB SOURCE ]]],
            ID = varSelectedListItemID
        )
    );
    If ( 
        Lower(vaEditMode) = "yes",
        EditForm([[[ YOUR Edit form ]]]);
        Navigate(
            [[[ YOUR ADD/EDIT SCREEN],
            ScreenTransition.Cover
        );
        , // NOTE: This is the else part, assume this means View.
        ViewForm([[[ YOUR Edit form ]]]);
        Navigate(
            [[[ YOUR View SCREEN],
            ScreenTransition.Cover
        );
    );
);
// if the ID is -1 that means the user want to create the record.
//   
If(
    varSelectedListItemID = -1,
    Set(
        varCurrentlySelectedRecord,
        Defaults([[[ YOUR DB SOURCE ]]])
    );
    Set(
        varEntryType,
        "New"
    );
    ResetForm(AESForm);
    Navigate(
        AddEditScreen,
        ScreenTransition.Cover
    );
    
);

Conclusion

The above few steps you can associate the full screen PowerApps to the customizes SharePoint List. The technique is simple the customized form will launch the full screen PowerApps.

I hope this is helpful to you. Please post any comments you may have.

Posted in Power Apps, SharePoint | Leave a comment

How to validate the Date control in Power Apps to only allow selection of Tuesday and Thursday?

Summary

I needed to restrict the date selection in the Power Apps form to only allow Tuesday and Thursday.

Step By Step Solution

I assume you know how to create Power Apps form app.

Step # 1 I the BorderColor property of the Date control (in my case DateValue2) put the following formula. The Weekday function will provide the number for Tue and Thu.

// if parent error is blank or
//    selected date is Tue or Thu the border color is normal
If(
    Coalesce(
        (Weekday(
            DateValue2.SelectedDate,
            StartOfWeek.Sunday
        ) = 3) ||
        (Weekday(
            DateValue2.SelectedDate,
            StartOfWeek.Sunday
        ) = 5),
        IsBlank(Parent.Error)

    ),
    Parent.BorderColor,
    Color.Red
)
BorderColor

Step # 2 In the Text property of the ErrorMessage Control of the DataCard add the following formula.

Coalesce(
    Parent.Error,
    If(
        ((Weekday(
            DateValue2.SelectedDate,
            StartOfWeek.Sunday
        ) <> 5) && (Weekday(
            DateValue2.SelectedDate,
            StartOfWeek.Sunday
        ) <> 3)),
        "Date must be for Tuesday or Thursday only"
    )
)
Text property

Conclusion

Currently, the out of the box date control does not provide any validation, this is an alternative approach to validate and restrict the days. I hope it is useful to you for your scenario.

Posted in Power Apps | Leave a comment

How to get List-Field’s information such as display name and static name map?

Summary

During the development of PowerShell Script or Power Automate Flow with REST calls you will need a Static Names of the List. The Display name of the list is not same as static name.

Please read here for more information about the Display Name Vs Static Name.

Step By Step Solution

To simplify let’s create a simple Manually Triggered flow. Using the REST API make a call to the get Fields information in JSON. Map using the Select action to get only required field properties. After that apply the Create HTML action to create nice tabular data to see the map.

Flow to extract the Static Name information
https://github.com/pankajsurti/PowerAutomateSamples/blob/main/Export-ListFields-Information_20210704172208.zip

You can download the sample Power Automate from the above URL or by clicking here.

Conclusion

I use this flow to get the information of the list to get the static names. I hope it is useful for you as well.

Posted in Power Automate | Leave a comment

How to get a list of all SharePoint list names that were Customized with PowerApps?

Summary

The SharePoint List can be customized. It is as shown here. But question is how to find out all the list names which are customized for PowerApps?

Answer

It is very simple, I saw multiple places and I want to documented here.

Using the PnP.PowerShell connect to the site using Connect-PnPOnline.

Execute the following command to get the PowerApps customized list names.

Get-PnPList -Includes RootFolder.Properties | ? { $_.Hidden -eq $false } | ? {$_.RootFolder.Properties.FieldValues.Keys.Contains('PowerAppFormProperties')}

Conclusion

Posted in Uncategorized | Leave a comment

How to limit number of checkbox selections in a gallery?

Summary

This is text version of the video by Daniel Christian.

#1 Add a Gallery control Gallery1

#2 Add a Check Box control in the Gallary

#3 Remove the border of the checkbox

#4 Add a Label control name it “CountLabel”. Add Text property formula.

// The formula will get all items in the galley and filter by checked checkboxes.
CountRows(Filter(Gallery1.AllItems,Checkbox1.value))

#5 Add DisplayMode formula as

If(Self.Value || (Value(CountLabel.Text) = 0), DisplayMode.Edit, Disabled)
Posted in Power Apps | Leave a comment

How to take an action in Power Automate only when certain field’s value have changed?

Summary

Here is the scenario, there is a list named “OrderList” with the following five fields. The end users change any of these fields except Order Status. The Order Status field is changed externally.

Field NameField Type
OrderIDNumber
Order Name Single line of text
Order StatusChoice (New, Approved, Shipped, Completed)
QuantityNumber
Order DescriptionMultiple lines of text
OrderList fields

The need here is when the Order Status change from one state to other the Power Automate Flow has some business logic. The question is how to check only the Order Status has changed from old value to new value. For example, Approved to Shipped status has multiple business actions and emails to be sent.

The solution to such need is to enable the “versions” in SharePoint List.

Step By Step Solution

Note: Please make sure you have enabled versions for your SharePoint List.

Step # 1 Create “When an item is created or modified” trigger flow

In this step select Site Address and the List Name.

Flow Trigger

Step # 2 Make REST call using HTTP to get top 2 versions of the item

Make a REST call using Send HTTP Method to get last two versions
# copy the following in Uri, make sure you change list name
_api/web/lists/GetByTitle('OrderList')/Items(@{triggerOutputs()?['body/ID']})/versions?$top=2

# copy the following values in Headers

{
  "accept": "application/json;odata=nometadata"
}

The above call will provide the results in the following format. The value JSON array has the data we need to extract the old and new values for the order status. The first value is the New value and second item in the array is an old value of the Order Status. e.g. the below data clearly shows that the Order Status was changed from New to Approved.

{
  "value": [
    {

      ... removed other data for the brevity
      "VersionId": 3584,
      "VersionLabel": "7.0",
      "ID": 1,
      "OrderName": "Laptop",
      "OrderStatus": "Approved",
      "Quantity": 11,
    },
    {

      ... removed other data for the brevity
      "VersionId": 3072,
      "VersionLabel": "6.0",
      "ID": 1,
      "OrderName": "Laptop",
      "OrderStatus": "New",
      "Quantity": 11,
    }
  ]
}

Step # 3 Extract the field values using Select operation

Us Select to extract only the OrderStatus field’s last top 2 versions we need.
# use the following formula in the From.
outputs('REST-GetTop2Versions')?['body']?['value']
# use the following formula in the Map
item()?['OrderStatus']

Step # 4 Store the OrderStaus’s New and Old value to variables

Storing Order Status New and Old values

# for New OrderStatus value us the following formula
first(body('Select'))?['OrderStatus']


# for Old OrderStatus value us the following formula
last(body('Select'))?['OrderStatus']



Step # 5 Using the New and Old variables do the comparison to take business action.

The final step is now up to your business actions. Basically you can use the above two old and new variables to do the comparison if the value have changed, or if values have changed.

Conclusion

There is no out of the box trigger to Tigger on the field. This is a simple ways to find out field values changing.

Posted in Uncategorized | Leave a comment

How to fix an infinite trigger loop in Power Automate?

Summary

Have you seen the following error in your Power Automate?

“Actions in this flow may result in an infinite trigger loop. Please ensure you add appropriate conditional checks to prevent this flow from triggering itself.

If your answer is yes, then please keep reading…

As you can see the warning is telling you “it may” and you need to “add appropriate condition checks”.

So to demonstrate that, I am going to create a scenario to get this warning and address it. I will create a simple custom list (named InfiniteLoop) with a default ‘Title’ field. Then I will create a flow with a trigger “When an item is created or modified”. In this flow, I will use a random number generator function rand to generate a random number from 1 to 75. The flow will append the generated random number to the Title field and call Update item.

After all that, it will show me a warning in the Flow checker as seen below.

# code for the compose is
concat ( ' ' , rand(1,75))

# code for the Update 'Title' is

concat ( triggerOutputs()?['body/Title'], outputs('Compose'))

Step By Step Solution

There are multiple ways to solve this infinite loop issue.

You need to add a trigger condition to your flow so it only fires when condition is met and does not fire back again after update item in your flow.

Solution # 1 : Utilize ‘Modified By’ field as the trigger condition.

Basically, what you want here is to set a trigger condition to check “Modified By” Email is NOT equals to a user’s email(flow author’s email). In my scenario BobK created the flow.

You can simply copy paste the following formula to the Trigger Condition, and change the email address appropriately.

# First modify by check email is null, 
#             if yes, return true
#             if no,  convert to lower case and compare to flow author
# Make sure to change the email address after copy and paste

@if(equals(triggerOutputs()?['body/Editor/Email'],null), true, not(equals(toLower(triggerOutputs()?['body/Editor/Email']),'bobk@gov963094.onmicrosoft.com')))
Settings Dialog for “When an item is created or modified” trigger.

NOTE: Please make a note, if the Flow Author user makes a change to the list item, the flow will not trigger. This is a downside of this technique. If you are a flow author and you will not be end user to update the list items this technique will work great for you.

Solution # 2 : Create a Copy of the field to do compare.

In this technique for above summarized scenario. I will create a new field e.g. “Title_Copy”. This field will hold the copy of the data from the “Title” field. The new Title_Copy field will be hidden from the user. The copy will be made in the flow with update item.

The list showing the Title and Title_Copy fields.

The flow will have a trigger condition to check if the “Title” and “Title_Copy” are NOT equal. If they are not equal that means the user has made the change to the Title field. So allow flow trigger to fire.

If they are equal that means the change is made by the flow at the time of the update. So do not allow trigger to fire.

# To fire the trigger, check if the Title and Title_Copy are NOT equal.

@not(equals(triggerOutputs()?['body/Title'],triggerOutputs()?['body/Title_Copy']))
The flow with Title and Title_Copy

Solution # 3 : Create a Copy of the field to do compare for more than one fields.

So far ok if you were only interested in the one field user makes the modification. What if you have more than one field which your flow is interested to check whenever a user makes a modification. The above #2 technique may need to be adjusted.

Basically, you will make a master Copy filed with multi text type. This field will be hidden similar to the #2 solution. This field also will be updated in the flow.

But update will be concatenation of the all required fields your flow want to trigger on.

To be continued… (I will complete this later as I get time)

Conclusion

As you can see there are multiple ways you can avoid infinite loop. Please let me know your comments.

Posted in Power Automate | Leave a comment