Trigger a Flow from Multiple SharePoint Libraries

In this post, I’ll show you a way that a flow can be set up to manually trigger the same from from multiple locations in SharePoint.  Here’s the back story.  I created an approval workflow for a committee’s SharePoint site, for approving meeting minutes.  Then, another committee wanted the same flow, then another and another.  I ended up creating and managing about 6 different flows that did the exact same thing, on multiple SharePoint sites.  This became painful anytime updates / tweaks needed to be made to the logic or verbiage in the flows.  I had to make all the changes six times.  When a seventh committee wanted this flow as well, that’s when I decided to try and build a more efficient way.  Somebody named Mark Boes, who had read my blog, had sent me a random email back in October, saying that after reading my post about how to create a button in a SharePoint list to trigger a flow, he came upon the realization that the ‘For selected item’ action receives the itemURL from where the button was pressed, regardless of the action Site Address.  Thanks Mark!  I thought this scenario would be a good opportunity to try this out.  Here are the steps:

1.  Create a flow, and use the SharePoint trigger For a selected item.

2.  Pick any site and list or library here.  It doesn’t matter what you pick.

sharepoint-for-selected-item-trigger

3.  We’ll be initializing seven different string variables.  The first one is for the site root, which is the part of the url that comes before the name of your site.  This isn’t dynamic, you’ll be typing your own in here, as the default value.

flow-initialize-variable-site-root

4.  Initialize a variable for the item URL.  This is buried in the trigger, here’s the syntax to get it.  Note that I’ve typed the formula there in the comments of the action as well, for easy reference.
triggerBody()?[‘entity’]?[‘ItemURL’]

flow-variable-item-url

Note:  The ItemURL itself looks something like this:

https:// wonderlaura.sharepoint.com/teams/CommitteeC/_layouts/15/Doc.aspx?sourcedoc=%7Babb5b0ad-4a30-45a2-9e4e-f253f784abec%7D&action=edit&uid=%7BABB5B0AD-4A30-45A2-9E4E-F253F784ABEC%7D&ListItemId=1&ListId=%7BC4D850F3-4E4A-4776-9980-1709B1A794EB%7D&odsp=1&env=prod
You may wonder why, in my formulas, I don’t just look for the _layouts in the URL.  Well, after I first implemented this solution, I noticed that depending on the view that I was in, or how I got to the item, the URL was structured completely differently and did not contain the _layouts.  So unfortunately, it’s not something that you can reliably depend on.  Same goes for the ListId in the URL.  It’s not always there.

5.  The next four variables just need to be initialized, but with no default value.

flow-more-variables
flow-variable-site-title

6.  Initialize one more variable, for the name of the library that the file is in.  In my solution with the committees, it’s easy because it’s just the “Documents” library for all of them.  In the associated video with this blog post, I explain why there isn’t a way to divulge the name of the current list/library just from the ItemURL.

flow-variable-document-library-name

7.  Add a Compose action, and put together the full URL to the current site, using this expression.  Note that I also put the expression in the comments section of my action, for easy reference.
substring(variables(‘varItemURL’),length(variables(‘varSiteRoot’)),indexOf(substring(variables(‘varItemURL’),length(variables(‘varSiteRoot’))),’/’))

flow-compose-site-name

8. Set a variable.  This is where we concatenate the varSiteRoot, from step 3, along with the URL to that specific site.  As I mention in the video, there are probably various ways that these formulas could have been configured to achieve what we need, this just happens to be the way I did it.
concat(variables(‘varSiteRoot’),outputs(‘site_name_url’))

flow-variable-site-url

9.   Now, we have the url of the site and the name of the library called Documents, which we keep in a variable varDocLibraryName just because it makes it simpler since we’re using it multiple times.  Now it’s time to get the file’s properties.  SharePoint action Get file properties.

flow-sharepoint-get-file-properties

10.  We have to get the filename from the file properties in step 9.  Here’s the formula.  If you’re watching the associated video (below), you’ll notice that I showed a much longer way of achieving this, but this formula is really all you need, it’s the simplest way.
body(‘Get_file_properties’)?[‘{Name}’]

flow-set-variable-filename

11. Next, the approval action can be added.  Who do you want the approval to go to?

image

When it comes to whom to assign the approval to, this widely varies.

If you would like the person triggering the flow to manually pick an approver right when they trigger the flow, at step 2 above, add an email input.  Use that value in the assigned to box above.

If you would like the approver to be the person who triggered the flow’s manager, then you can use the Get Manager action instead.

If you’d like to use a person from a person column in the library, you’ll have that data from the get file properties action at step 9.  There are many, many potential ways of getting / setting who it needs to be assigned to.

What do you want to happen after the approval?  Of course that also varies.  Send an email, and set the content approval status are two common ones.

Here’s a screenshot of the whole thing

generic-flow-full

Now, how do we trigger the flow?

In my example, I created a column called Approval.

Check out my post how to create a button in a SharePoint list to trigger a flow for the instructions to create a button in the library to kick off the flow.  In my real-world example, like I mentioned, each committee uses the Documents library on their site, where they keep the meeting minutes, so I just added this button to that Approval column in each library on each committee site.  They all kick off this exact same flow, so no need to create a separate flow for each library.

Here is the full video where I demonstrated this solution on SharePoint Power Hour:

power-hour-generic-flow

Note: Since I did this demonstrated this yesterday, I’ve actually fine tuned it a bit more as I wrote down the instructions, for example, I added the variable root site instead of manually typing the number of characters and all that.  And the second half where I get the site and group and all that, I’m going to write as a separate blog post.

48 comments

  • Thanks for doing this detailed blog. I know I’ll be setting up this type of Flow for my company.

    Merry Everything and Happy Always!

    Lisa

    • Nice flow, thank you very much for the detailed explanation.
      One thing I don’t get here is the file identifier (get file metadata). with ID only, I get constantly an error ‘file not found’.
      Do u have an idea or workaround?

      Thanks in advance.

    • To troubleshoot, try typing just a specific ID number of an actual item, directly in the flow and see if it works. Then you’ll know more about what the problem is, if that works or not.

  • thanks for this. Although I don’t need to do this is t was a good intro to using variables which I have not done before. Even with your notes, writing the string expressions to populate these variables has proven hard. Is there a good tool for checking and debugging these?

  • Thank you for sharing. This is really helpful. I would like to use it in combination with the step “update file properties”. Unfortunately I get an error: “Cannot evaluate the parameter ‘path.$.dataset’ at design-time; it is empty or has a runtime expression.” Do you have any ideas on that?

    Thomas

  • Thank you for at great video and blog post.

    Im nearly there… and i think ive finally found the missing piece. My document library is in a subsite… so i guess i missing something in step 4 that specifies the subsite? or am i completely off?

    the URL looks like this:
    …..sharepoint.com/sites/Portal_Prototype/Byggesag1/Documents/

    /byggesag1/ doesnt seems to be included in sted 4.

    I hope you guide me in the right direction.

    • In mine, I have no sub-sites. Since Microsoft has deemed that sub-sites are no longer to be used, it’s not something I thought to accommodate for in my logic. I’m not sure how you’d make it dynamic if there could randomly be sub-sites involved.

  • Pingback: Power Automate Approval to Office 365 Group Members | @WonderLaura

  • I have been using SharePoint 2016 and I am looking at moving to SharePoint Online. One of the features that is not available in SharePoint Online is the ability to create site templates. Is there a workaround for this for SharePoint Online? We are currently creating a new site for each project and using templates (sites, lists and libraries) to create a site for a new project.

    • It’s possible to create site design templates that come with predefined libraries and lists

    • You need to activate custom scripting at the SharePoint Admin Portal or run a PowerShell script to turn on custom scripting for a specific site collection. Save as a Site Template is an old action associated with Classic Experience. Site Designs are avaiable for Modern but you must have access to your 365 Tenant to deploy them.

  • Hi Laura,

    Thank you for taking time with this, it’s the simple realisation that the “For a selected item” trigger is generic, that brings the power here. I will be making extensive use of this.

    I wanted to loop back and share a different approach to getting the parameters so you can easily pick the ones you want. This formula takes the Querystring Parameters from the Item URL and turns it into a JSON string. You can then add a ParseJSON activity to use the named parameters:

    concat(‘{“‘, replace(replace(split(triggerBody()?[‘entity’]?[‘ItemURL’],’.aspx?’)[1],’=’,'”:”‘),’&’,'”,”‘),'”}’)

    For those who are new to formulas or struggle with nested functions….We basically just replace all of the querystring separators with JSON equivalents:

    & becomes “,” – used to separate one item in the JSON from the previous
    = becomes “:” – used to separate the item value from the item name

    We then top and tail the whole string with {” and “} to signify the JSON object and start and close out the item name for the first and last item. This gives us the JSON string:

    {“sourcedoc”:”%7Bf0dxxxxc-9658-xxxx-xxxx-e8831afc18f8%7D”,”action”:”default”,”uid”:”%7BF0DxxxxC-9658-4F13-ABF5-ExxxxAFC18F8%7D”,”ListItemId”:”1″,”ListId”:”%7B7D68E373-xxxx-4B04-xxxx-45C554442E76%7D”,”odsp”:”1″,”env”:”prod”}

    Which we can place as the schema string for a Parse JSON activity, producing a nice object:

    {
    “sourcedoc”: “%7Bf0dxxxxc-9658-xxxx-xxxx-e8831afc18f8%7D”,
    “action”: “default”,
    “uid”: “%7BF0DxxxxC-9658-4F13-ABF5-ExxxxAFC18F8%7D”,
    “ListItemId”: “1”,
    “ListId”: “%7B7D68E373-xxxx-4B04-xxxx-45C554442E76%7D”,
    “odsp”: “1”,
    “env”: “prod”
    }

    We can now reference each item in the JSON object by name when we need to use them:

    body(‘Parse_Parameters’)?[‘ListId’]

    We just need to remove the GUID escape characters %7B and %7D if we use those elements.

    The same sort of approach gets us the Site path too:

    split(triggerBody()?[‘entity’]?[‘ItemURL’],’/_layouts’)[0]

    Of course we can also extend that to get the root if that’s required as well; just using ‘/’ as the split character.

    Hope this helps someone else out.

    Stay safe everyone.

  • Lourenço de Azevedo Meireles Pinto da Silva

    I can´t get the items URL, When I use the following expression in step 3: triggerBody()?[‘entity’]?[‘ItemURL’]
    I get an error message saying :The expression is invalid.

    • Hi Lourenço, try deleting the quotes ‘ and then retyping them in, they look like they were reformatted in the post comments so are probably invalid characters in flow even though they look sort of correct.

  • Thanks for the info its been a great help, The site Url wasn’t working for me however I’ve found if part 4 triggerBody()?[‘entity’]?[‘ItemURL’] to sharepoint link to item this solves that issue.

  • Laura, thank you so much for this great post!
    For a selected item trigger isn’t available anymore, do you know what trigger would be a good replacement for?

  • Hi Laura,

    Is it possible to trigger the workflow based up on any update on the lists instead of button

    • Yes. The flow’s trigger would be when an item in SharePoint is created or modified. But then you couldn’t do this solution for triggering it from multiple libraries, because that other trigger needs to know the specific list/library *in* the trigger settings.

  • Hi Laura,
    Thanks for a great post! I was able to use this concept for one of my flows and being able to use a single flow across multiple sites is a great idea. I have added additional functionality in building dynamic destination paths and the button to be visible based on content approval status etc. Many thanks for your detailed posts and knowledge sharing! Keep up the great work!

  • Rich Capenerhurst

    Hi Laura,

    Thanks so much for this post. I have the same named file in the documents library across multiple sites. I need to copy each file to another SharePoint archive folder whenever that individual file is modified. Could I use this method to achieve that?

    Thanks
    Rich

  • Thank you so much for this, it is working like a charm! I’m able to kick off the flow from all of our working doc libraries with no issues. The problem I’m currently running into is that I can’t get the “Set Approval Status” step to work at all. I keep getting a bad gateway error:

    {“status”:500,”message”:”The current state of the item is Draft and the following action Approve cannot be implemented\”

    Email notification back to the user who triggers the flow works just fine.

    • Hi, it seems like you may be using the setting on the library for versioning, where you create drafts and then a published version of each file. That’s in the versioning settings of the library.

  • Hi Lara,

    Super smart flow! I’m trying to figure out how I can log the output of the approval, since it seems I’m unable to update the list item using this approach. (It loses the list properties when I put in the variable). Do you have any suggestions?

    • Ooh good question. But I don’t know. I usually use multiple flows. The first flow creates the approval, but doesn’t wait, then it creates an item in a list on that site, with the approval ID in a field in the list. Then, each task list has its own workflow that triggers on create and waits for approval, using that approval ID. Obviously that is much more work because of the multiple flows involved. One flow kicks them off but separate flows needed for each list (of waiting items).

  • Hi Laura,
    Thank you very much for this…. I’m running into an issue where the triggerBody() function is not working at all, even copied as is. Is there a prerequisite that you need to have some other flow triggered by a button somewhere for this one to render successfully?

  • Is it possible to do something similar to this but for multiple libraries in one site? I have multiple document libraries within a Team Site but want to run the same workflow on all the libraries, currently have recreated the workflow for each one but as you said this is highly time consuming.

    • Hi Lorraine, most likely it can be done, I just haven’t done it. I do know that from the trigger, you can obtain the GUID of the current list with this syntax:
      trigger()?[‘inputs’]?[‘parameters’]?[‘table’]
      Which gives you something to work with possibly as a variable.

    • It definitely is possible using the GUID as Laura says. I’ve done that from quite a few sites. For some reason, the dynamic binding of the Flow to the Button in the library view takes a few seconds, which is annoying, but it does work.

    • Hi, I’m rather new to Flows. @Glen do you mind sharing how you do dynamic Library Name with the GUID you receive back?

    • Hi Martin,

      Happy to help. If you see my comment from 28th April 2020:

      https://wonderlaura.com/2019/12/20/trigger-a-flow-from-multiple-sharepoint-libraries/#comment-73378

      Add a “Parse JSON” activity to the flow and use the following to generate the JSON Schema:

      {“sourcedoc”:”%7Bf0dxxxxc-9658-xxxx-xxxx-e8831afc18f8%7D”,”action”:”default”,”uid”:”%7BF0DxxxxC-9658-4F13-ABF5-ExxxxAFC18F8%7D”,”ListItemId”:”1″,”ListId”:”%7B7D68E373-xxxx-4B04-xxxx-45C554442E76%7D”,”odsp”:”1″,”env”:”prod”}

      Just be a little careful with the quote characters as when posting in the comments here, they get encoded using a different character set so don’t translate over properly. Just find and replace them in Notepad to be sure.

      Once you have that, you can reference the ListId produced by the Parse JSON activity. That is the Library GUID. You can place it instead of a Library name in subsequent steps of your flow. The hardest thing is developing the rest of the flow when using dynamic binding. What I usually do is hard code the flow pointing to a specific library I develop against until I know it’s right. I then go back and change the Library Name to the ListId property and you should be fine from there.

      HTH.

      Glen

  • Hi Laura,
    this looks great.
    I used site and library variable in Update Item action.

    it added item* as compulsory field.

    error says item/column name/value is no longer present in operation schema. It should be removed before workflow is resaved

  • This is not working when uploaded file is a PDF. Get file properties is not returning proper values. Anybody faced this issue? Any resolution?

  • Hi Laura,

    Nice Work Thank you for this Post. I want to know is it possible trigger “for a selected Item flow ” for users having read only access to document Library. I have a requirement to run approval Flow for documents with read access only.

    • I don’t know I haven’t tried it lately. I’d assume that would work. In the run-only users settings of a flow, it lets you set up *who* you want it to run as (admin or end user), which is helpful if you need it to write back to a list/library where the person kicking it off has read-only access.

  • Hi Laura,

    Thank you for sharing this. I was wondering what if my Document Library names are different (but all in the same site collection). I can’t seem to find how to get the Document Library the right way. At the moment I use the itemURL value (from the ‘For selected file’ trigger) to extract the ListID, but this breaks for PDF document as it has a different format of itemURL.

    I have over 30 document libraries where I need to create approval workflow in this site 🙁

  • Thank you for this post. Seeing this post, gave me insight and confidence to create a flow that run on a List where all the Libraries URLs are listed. I placed the site name and Library name in the respective variables and use the variable for various steps. For Update library step, I needed to use the variable of array type using value(s) in a JSON format. Something I found online as well. Appreciate your inspiring posts.

  • Lakshmi Harika Velidi

    I would like to create a power automate flow for sharepoint library where it sends an email before 3days of due date and there is already a template in place for this but it only notifies the person who created the flow, but i want to send notification to the owner of the file or document.

  • Can you share the json placed in the library of edit column

  • Hi Laura,

    Thank you so much for the detailed flow and steps on how to set up a button to trigger it. Everything works up until the compose action.

    I received the following error and this is the first time I am using formulas so I have no idea what I need to do to resolve this. Would be greatly appreciated if you are able to assist.

    InvalidTemplate. The ‘start index’ for function ‘substring’ must be equal to or greater than zero and must be less than ‘0’ which is the length of the string.https://aka.ms/logicexpressions#substring

    Thanks
    Graeme

Leave a Reply