Run Power Automate for a selected folder in SharePoint

Power Automate integrates nicely with SharePoint document libraries. One feature is that a Power Automate flow can be launched for a specific document, but it does not offer a trigger for a selected folder. This blog shows you in detail how to achieve that.

For a selected file

For documents, a flow is written with the trigger “For a selected file”, and the SharePoint site and library are specified in the trigger. To run the flow, you navigate to a file in the library, select the file and then open the Actions menu to click the desired flow.

That’s how it works for documents. But what if you want to run a flow on a specific folder? There is no Power Automate trigger “For a selected folder”. But I’m writing this because I found a way to run a workflow for a selected folder!!

A common scenario

My company uses a defined folder structure in our SharePoint library to organise the documents for our client projects . I have written a workflow that generates the correct folders and populates them with document templates. Now I would like to run this workflow when we start a new project with a client. I would like to select the client folder and start the workflow, so a new project folder is created inside the client folder.

Let’s write the flow that runs for the selected folder

I start with the trigger “For a selected file”. When we inspect the flow run for this trigger, we can see the output of the trigger. Click on “Show raw outputs” to display the side panel.

The output starts with a lot of lines in the headers section that are not of interest to us right now. We need only the section at the bottom that starts with “body”. The body contains the text field that I configured as the input parameter of the trigger. That is followed by an “entity” that contains the itemURL and the fileName.

The fileName contains the name of the selected file or folder. The itemURL contains valuable information about what kind of item was selected, file or folder. You can select and copy the itemURL content and paste it into a text editor for easier inspection.

Here is the structure of the output for a file:

https://tenant.sharepoint.com/sites/<SiteName>/_layouts/15/Doc.aspx?sourcedoc=<GUID>&action=default&uid=<GUID>&ListItemId=207345&ListId=<GUID>&odsp=1&env=prod

And here is the output for a folder:

https://tenant.sharepoint.com/sites/<SiteName>/<Library Name>/Forms/AllItems.aspx?id=%2Fsites%2F<SiteName>%2F<LibraryName>%2F<FolderName>%2F<SubFolderName>&viewid=<GUID>

We can clearly see differences:

  • A selected file URL contains the library (ListID) as a GUID parameter, the document is identified with the sourcedoc GUID parameter and the URL contains the system view _layouts/15/Doc.aspx
  • a selected folder URL contains the library name written out, the view name in the URL, and the viewid as a parameter

Flow logic

We can use these differences to determine if the selected item is a folder or a file, and then take corresponding action in the flow. My flow starts with the trigger “For a selected file”. The next action is a condition that checks if thes selected item is a document or not.

I’m checking for the existence of the text “/Doc.aspx” in the itemURL. There are different ways to approach this. I have decided to use the function indexOf(<where to look>, <what to look for>), which returns a positive number representing the position of the text if it is found in the string. If the text is not found, the value -1 is returned.

indexOf(triggerBody()?['entity']?['itemUrl'],'Doc.aspx?')

When writing this formula, you don’t need to know the syntax for the first parameter. You can click on the button Dynamic values and pick the itemURL from the list.

Type the search term manually. Make sure that you put the search text inside a pair of single quotes. (One of my pet peeves with the Power Platform tools is that there are so many differences between the formula languages for Power Automate and Power Apps. I’ve been bitten more than once, using single or double quotes in the wrong scenario.)

The comparison for my condition is “greater than 0”. The indexOf() function will return a zero if the search text is found at the beginning of the string, because it’s a zero index notation, but the text we’re looking for is always further along and its position will never be zero.

So, if the indexOf is greater than 0, we’re dealing with a document, otherwise we’re dealing with a folder.

In this particular workflow, I use a “Terminate” statement in the Yes branch of the condition, so the rest of the flow only runs if the selected item is not a document.

This is it. We can now run a workflow on a selected folder.

Further processing

You will need to develop your own approach for what you want to do next, based on your needs and business logic. In the following I’ll describe how to extract the path to the selected folder, so it can be used in an HTTP statement to create a sub folder.

The itemURL for a folder contains the full folder hierarchy up to the selected folder. The forward slash symbol “/” is written with the URL Encoding “%2F” and any space characters in the path will be showing as “%20”. You could use the replace() function to make the path more readable. A full list of URL Encoding can be found at the WWW3Schools site.

You can use other text functions to extract the path to the current folder for further processing, for example:

Get the position of the beginning of the path, starting from “/sites” – find the text “=id” and increase the result by the length of the string “=id”, which is three characters long.

add(indexOf(triggerBody()?['entity']?['itemUrl'],'=id'),3)

Get the position of the “&viewid” which marks the end of the path:

indexOf(triggerBody()?['entity']?['itemUrl'],'&viewid')

With a start and an end position, you can then extract a substring, for example the full path starting with “/sites” and ending with the selected folder:


substring(indexOf(triggerBody()?['entity']?['itemUrl'],
add(indexOf(triggerBody()?['entity']?['itemUrl'],'=id'),3),
indexOf(triggerBody()?['entity']?['itemUrl'],'&viewid')
)

Explore the other string functions like nthIndexOf() or lastIndexOf() to nail down specific places in the path.

My tip: start with writing separate Compose actions for each of these exploratory index functions. Run the flow and you can see what number is returned by the Compose actions. When you are happy with the resulting numbers, you can construct a more complex all-in-one formula to return your desired string.

Create a subfolder with HTTP

With the folder path extracted, you can now use it in other actions that require an exact folder location or in a SharePoint HTTP action to create a new folder inside the currently selected one. The screenshot below uses a Compose statement with the path components that follow the “/sites/sitename/library/”

That’s my workflow. Let me know in the comments if you found this useful and in what scenario you want to use this approach.

Enjoy.

Cover Photo by Sear Greyson on Unsplash

2 comments

  1. I wonder if a `Get item` after the trigger would give you the right info about the selected item to determine whether it’s a file or a folder? There’s a property called `FSObjType`, which is 1 for folders, 0 or null for everything else. The Content Type for a folder is also `Folder` – unless you’ve created a custom Content Type inheriting from Folder.

    Like

    • Hi Marc, thanks for your feedback. That’s an excellent idea. ‘Get item’ won’t work, however, since it only returns list items, but ‘Get file (Properties only)’ is perfect. It returns the Content Type Name, which is ‘Folder’ for a folder, and, as a bonus it also contains the properties ‘Path’ (which leads to the parent folder) and ‘FullPath’, which contains the full path to the folder. I’ll rewrite my flow and post the update next week.

      Liked by 1 person

Leave a comment