Power Automate – How to move SharePoint Online list items to folders

Let’s say you have a SharePoint list with folders organized by continent and you have as well a choice column with the continent name in this. You want to move automatically all the list items with the chosen continent to the specific continent folder.

Capture1-768x502

The first idea would be to use a Power Automate Flow to do that, but there is no out-of-the-box action that moves list items to folders. At the moment of writing this post, there is an action to move files but nothing for list items. Even thinking about using SharePoint Rest API with the ‘Send an HTTP request to SharePoint’ connector there is no endpoint to move list items to a folder.

This is not clear in the Microsoft documentation, but actually, the same Rest API endpoint and action that is available for files can be used for list items by using the item file property. In this post, it will be shown how to use SharePoint Rest API to move items with a Flow, so as soon as an item is created or edited, it will be moved to the right location.

Basically, this Flow will do after being triggered:

1.   Get current list root folder path

2.   Get current item file name and the current path

3.   Build a new file path

4.   Check if the path is actually new and if so move the item

To better understand the following steps, knowledge on SharePoint Rest API and Flow expressions is helpful.

To start building the flow, the trigger used is ‘When an item is created or modified’.

In this example, variables are used to store the list title, destination folder name and the site Url. Because the same values will be used in different connectors, it is a better practice to not let them hard-coded in the actions. For example, if this flow is exported to another environment or copied to be used in a different list, the changes to the flow will be minimal, only the initial variables and the trigger, instead of updating a bunch of connectors with hard-coded values.

Capture-768x815

Next step is to get the list folder Url using the SharePoint Rest API, using the ‘Send an HTTP Request to SharePoint’ action with the GET method. The action was renamed to ‘GetRootFolder’ so it is easier to access its output later in expressions. All the variables actions in this example are renamed as well, just for easier maintenance.
getrootfolder-768x301

After this action, a new variable is initialized to store the list root folder Url with the following formula (use expressions to access the JSON content that is returned by the SharePoint Rest API, with the body function and the action name you can access the content):

body(‘GetRootFolder’)[‘d’][‘ServerRelativeUrl’]

rootfolder-768x210

Next action is to get the current list item File Server relative Url using SharePoint rest API like it was done with the list Root folder. In this case, it is needed to explicitly tell the Rest endpoint to load the ‘FileRef’ and ‘FileLeafRef’ properties.

getitem

The following variables are used to build the new list item folder Url, so the below formulas are used to assign values to the proper variables:

  • Item file name (Set with current file name only, used to build final destination path): body(‘GetItem’)[‘d’][‘FileLeafRef’]
  • Item Url (Set with current item server relative Url, using the expression): body(‘GetItem’)[‘d’][‘FileRef’]
  • New item Url (Root Folder/New Folder/Item File Name): concat(variables(‘RootFolder’),‘/’,variables(‘MoveToFolderName’),‘/’,variables(‘ItemFileName’))

itemvariables-768x766

Then, the SharePoint ‘Send an HTTP connector to SharePoint’ is used again, to call the Files REST endpoint and move the item to the new location (yes, the same endpoint used for files).

It is validated if the File new folder path is different then the current one:

moveitem3-1024x231

If it is, then a call to the API for the File/moveTo method is done in order to do the move:

moveitem2-768x343

This time a POST request is sent because we actually will request a change in this call to the endpoint, which will take care of the item move (also renamed the action to ‘MoveItem’).

After this last action is called, the item is moved to the proper folder.

The final flow will look like this:

CaptureFinal-1

With this flow, regardless of where the items are saved, they will be moved to the proper folder after being created/edited.

18 comments

  1. Apenas para complementar: da para usar a api “_api/SP.MoveCopyUtil.MoveFileByPath()”. No corpo da requisição da para passar o seguinte JSON:

    {
    “srcPath”: {
    “__metadata”: {
    “type”: “SP.ResourcePath”
    },
    “DecodedUrl”: “https://seutenant.sharepoint.com/sites/seusite/Lists/sualista/21_.000”
    },
    “destPath”: {
    “__metadata”: {
    “type”: “SP.ResourcePath”
    },
    “DecodedUrl”: “https://seutenant.sharepoint.com/sites/seusite/Lists/sualista/NOVA_PASTA/21_.000”
    },
    “options”: {
    “__metadata”: {
    “type”: “SP.MoveCopyOptions”
    },
    “RetainEditorAndModifiedOnMove”: true,
    “ShouldBypassSharedLocks”: true
    }
    }

  2. Hi,

    Thanks you for the detailed post, its exactly what I’m looking for. I’m just having the following error messages on the Initialize variable – ItemFileName & Initialize variable – ItemURL

    Correct to include a valid reference to ‘GetItem’ for the input parameter(s) of action ‘Initialize_variable_-_ItemFileName’.

    Correct to include a valid reference to ‘GetItem’ for the input parameter(s) of action ‘Initialize_variable_-_ItemURL’.

    Any help would be great. Thanks!

  3. Thanks for this sample, however the getrootfolder action is now gone in power automate, may I know what is the new one? I couldn’t follow this sample anymore.

    1. It’s the ‘Send an HTTP Request to SharePoint’ action…I just renamed it to make the logic clearer..

  4. Hi Michel, thank you for the post. Is it possible to move the list item to a different list instead? The reason being I do not want to use the “Get Item” and “Create Item” actions to copy the item as this requires the fields to be manually mapped. In the future, if a new field is added, I do not want an individual to have to go in and add the new field to the “Create Item” action. I am able to use the method you describe above to move the item from List A, however the item is not being moved to the correct destination. Can you help with the Uri I should be using to move the list item into another list? Thank you in advance for any help.

    1. Hi Jonathan,

      There’s no way to move list items to a different list with a single API call…But you can use the rest endpoints and some tricks to get it done:

      1) Retrieve the custom fields names on the list:
      _api/web/lists/GetByTitle(‘Your List title’)/fields?$filter=CanBeDeleted eq true
      2) Get the current list item value:
      _api/web/lists/GetByTitle(‘Your List title’)/Items(Your Item ID – Number)
      3) Use some advanced JSON manipulation to get the fields you would copy and create a new JSON String with the content
      4) Then add it to the second list using the items endpoint and the POST method:
      _api/web/lists/GetByTitle(‘Your Second List title’)/Items

  5. Thank you for sharing these steps! I was able to combine them with some info on another site in order to move a file into a folder structure 3 levels deep. The one thing that was causing an issue for me was in the last MoveItem step – I had to zoom in a lot on your screenshot in order to tell whether it was a comma or a period in front of =flags=1… If anyone else is curious, it’s a comma! Now the flow works for me and I’m really excited. Thanks again!!

  6. Hi Michel, greetings. I need some guidance. One of my teams (relatively new) have moved some records from one list to another using some .NET code provided by the vendor who transitioned the SharePoint to us before they quit. We have not tested it or used it until a week back, when we wanted to move some records (which also contained some attachments) to another library. It was more like moving historical data to another library while maintaining new records in the current library. When we executed the script, the records have moved to the destination, while the attachments were not moved. This was also not reported in the error log. As this action was done to free up some space, our team “manually” deleted the records from the site collection recycle bin. When we tested in the new list, we can see only the records but not the attachments. Do we have a way to restore the “attachments” as they are now completely missing for all the records that were moved to the new destination? Could you provide us some guidance on how can we retrieve the attachments? I would be happy to get connected with you via your Forum/Blog. Thanks in advance for your time to read this and also any support you may provide us that can help us retrieve the attachments which are very important.

    1. Hey Ragavan,
      Were the files deleted even from the second stage recycle bin? If they weren’t you can try restoring them from there.
      Otherwise, if you are using SharePoint Online I recommend that you open a support ticket with Microsoft, they may be able to restore the full site collection (it depends on when the changes were made)…

  7. Hi there,

    Great blog post. Just wondering, is it possible to use the action “For a selected item” instead and also in my case, I just want to move the item to a folder called archived, that is on the same list. Is it possible for the above to be shortened?

    Basically I am just looking for a way where it easy for someone to archive a item in a sharepoint list into a folder.

    Cheers

    1. Hi Daniel,

      Yes, on the example above, you will need a few replacements:
      1) Use the for a selected item trigger
      2) In the HTTP action where you get the item data, use the ID retrieved from your new trigger
      3) Where we set the variable ‘MoveToFolderName’, put your ‘Archive’ folder name hardcoded there as it is fixed. You can keep it in the variable so it’s simpler to change to something dynamic later if needed.

      Hope this helps

Leave a Reply

Your email address will not be published. Required fields are marked *