View SharePoint item version history in PowerApps

Sometimes when you’re building a PowerApp with SharePoint as your datasource, you want your users to only use the PowerApp and not to go to SharePoint directly. In this scenario it may come in handy to provide the user with the option to view the version history as well, but how do you do that?

In this blog, I will explain how by using PowerApps in combination with SharePoint and Microsoft Flow.

Setting up your datasource in SharePoint

First of all, we need to have a SharePoint list with versioning enabled (obviously). I added some test items to make sure I would get a result in my PowerApps:

Setting up your basic app in PowerApps

Next, we need to create a PowerApp that will show all SharePoint items and an option to retrieve the version history of a specific item. I used a gallery that shows the data from my SharePoint list for this:

Retieving the version history with Microsoft Flow

Now we need to make sure that clicking the history button will provide us with the version history of that specific item. To do this, we must create a Flow that is triggered from PowerApps by going to Action > Flows > Create a new flow.

You will get redirected to Flow where we get to configure our Flow.

Identify list item

The first thing we need to do is to ask PowerApps to give us the list item ID. You can do this by adding a ‘Initialize variable‘ action, give the variable a name (e.g. ID) and selecting the ‘Ask in PowerApps‘ value from Dynamic Content.

PowerApps will show the name of your Flow action as a parameter, so I always rename these actions so that I can identify them easily. Make sure you rename the action before adding the ‘Ask in PowerApps’ value!

Version history storage

Next, we need to create an empty variable that stores the entire version history. Logical thought is that we must use an array variable, but since Microsoft Flow cannot pass array variables to PowerApps, we need to use a string variable which we transform back into a collection in PowerApps. More on this later.

Get version history

To get the version history of an item, we need to perform an API call to SharePoint. The endpoint for this is:

<TENANT>/sites/<SITE>/_api/web/lists/GetByTitle('<LISTNAME>')/items(<ID>)/Versions

You can do this by adding the ‘Send an HTTP request to SharePoint‘ action and configuring it as follows:

Make sure to enter/select the correct Site Address and Listname in your Uri. The ID parameter can be selected from the Dynamic Content.

Process each version history item

This API call will return the entire version history to us. To process each version history item separately, we need to add and configure an ‘Apply to each‘ control. This isn’t as straight-forward as selecting the Body value from the Dynamic Content unfortunately. We need to manually enter the correct value from the Expressions tab:

body('Send_an_HTTP_request_to_SharePoint_to_get_version_history')['d']['results']

Please note that the Send_an_HTTP_request_to_SharePoint_to_get_version_history part of your expression may vary based on the name of your Send an HTTP request to SharePoint action:

Storing the version history

Inside our Apply to each action, we need to add an ‘Append to string variable‘ action that will write the output of each version history item to our versionHistory variable.

In my example, I wanted the following version history properties to show in my PowerApp:

  • Date
  • Version
  • Editor (display name)

These three properties need to be put into the Append to string variable action, separated by semicolons so that we can split can later in our PowerApp. The values that you need are:

  • Created
  • VersionLabel
  • Editor > LookupValue

This also isn’t as straight-forward as selecting the values from the Dynamic Content, so we need to work with the expressions tab again. In the correct order:

  • items(‘Apply_to_each_version’)[‘Created’]
  • items(‘Apply_to_each_version’)[‘VersionLabel’]
  • items(‘Apply_to_each_version’)[‘Editor’][‘LookupValue’]

Where the Apply_to_each_version part of your expression may (again) vary, based on the name of your Apply to each control.

At the and of your string, put a pipe symbol (‘|’) so that we can divide each version history item from each other in our PowerApp later:

Passing the version history to PowerApps

Now that we’ve stored the entire version history into the versionHistory variable, we need to make sure this variable gets passed back to our PowerApp. You can do this by adding a ‘Respond to PowerApps‘ action, selecting the ‘Add an output‘ option and add a Text output that contains the versionHistory variable:

That’s it; your entire Flow should look like this now:

Transforming data in PowerApps

We now have a Flow that returns the entire version history in a single string, so we need to transform this into a collection so that we can use it in a gallery in our PowerApp.

The following actions are all performed when clicking the history button using the OnSelect() property:

Retrieve string from Microsoft Flow

First thing we need to do is to get the output from our Flow into a variable in PowerApps. You can do this by using the Set() function around your <FLOWNAME>.Run() action that runs your Flow. More on this can be found in my previous blog post.

Set(
    varHistory,
    Versionhistorydemo.Run(ThisItem.ID).history
)

Split version history items

Next, we need convert this string into a temporary collection by using the ClearCollect() function. In our Flow, we added a pipe separator to divide each version history item from each other so we can split on this character using the Split() function:

ClearCollect(
    colHistoryTemp,
    Split(
        varHistory,
        "|"
    )
)

Split version history item columns

After we’ve split the string into a temporary collection, we need to split it once more to divide the collection into columns. For this we need a combination of the ForAll(), Collect(), First(), Last(), FirstN() and Split() functions:

ForAll(
    colHistoryTemp,
    Collect(
        colHistory,
        {
            Date: DateTimeValue(
                First(
                    Split(
                        Result,
                        ";"
                    ).Result
                ).Result,
                "nl-NL"
            ),
            Version: Last(
                FirstN(
                    Split(
                        Result,
                        ";"
                    ).Result,
                    2
                ).Result
            ).Result,
            Editor: Last(
                Split(
                    Result,
                    ";"
                ).Result
            ).Result
        }
    )
)

Dividing this into smaller pieces:

  • ForAll() processes all items inside the colHistoryTemp collection
  • Collect() fills the colHistory collection with the columns Date, Version and Editor and its corresponding values
  • Each row of the colHistoryTemp collection will be split using the Split() function on the semicolon separator.
  • According to the position of the value we need, we must use the First(), Last() of FirstN() function:
    • Date is the first property that is stored in the row, so we can use the First() function here. Because the value is passed as a string, we need to convert it into a date value by using the DateTimeValue() function. “nl-NL” is the locale that is used to display the date value.
    • Version is the second property that is stored in the row, so we need to get the first two properties by using the FirstN() function. By passing 2 as second parameter, we tell PowerApps we need the first two properties. From this result, we need the last property by using the Last() function.
    • Editor is the last property that is stored in the row, so we can use the Last() function here.

Sorting version history

Now that we have our final collection filled and divided into columns, we can sort the collection on Date (or another property) by using the Sort() function:

Sort(
    colHistory,
    Date,
    Descending
)

Cleaning up

After our final collection is complete, we can clear our temporary collection by using the Clear() function:

Clear(colHistoryTemp)

I’m also clearing both collections at the start of the OnSelect() event to avoid unwanted values.

Showing your version history

With the version history collection filled, we can now show the data in our PowerApp. I used a new screen with similar design to show the version history in a gallery, but you can also show the data on the same screen. It’s up to you!

Please note that the API call will take some time. To make it a bit more clear to the end-user what is happening and they’re not just staring to a screen where nothing happens, you can configure some kind of loading screen while the Flow is running. You can read about this in my previous blog post.

68 Replies to “View SharePoint item version history in PowerApps”

  1. Hi, great tutorial, everything works. Regarding to DSGT question, I dont need full information about changes and what was replaced. But atlest information what was changed.
    I want to add
    items(‘Apply_to_each’)[‘context’], but I dont know which name I should use instaed of context.
    Is it possible to make it?

    0
    0
    1. If you only want to know what changed, you might want to use the Get changes for an item or a file (properties only) action in Power Automate. Otherwise, you have to manually compare versions, which can be a quite complex configuration

      0
      0
  2. Hello, I’m new in developing using Power Apps, and this guide is incredibly helpful for the project I want to create. I just want to for the section “Transforming data in PowerApps”, where do I put all those codes into my Power Apps? So far, I have put the Retrieve string from Microsoft Flow in one of my buttons, but for others. I have no idea.
    Thanks in advance.

    0
    0
    1. The entire code (Set(), ClearCollect() and ForAll()) should be put into the OnSelect of your button. After that, you can use the Sort() formula in your gallery. The Clear() formula can be put after the ForAll() formula on your button as well.

      0
      0
  3. Hi,

    Great tutorial you have composed, however I have ran into an issue with the ClearCollect(
    colHistoryTemp, – ClearCollect is showing an Operator issue & colHistoryTemp is showing as Name isn’t recognized. Is there a fix I need to employ? I have tried using other operators with no joy so far, I’m using UK Locales and everything else so far has seemed to work with no hiccups!

    0
    0
    1. Did you copy-paste the entire ClearCollect formula? Sometimes, the quotes gets messed up so please try to manually change the quotes to the correct symbols if that is the case. Otherwise, you need to troubleshoot the error further. On which characters does the formula break?

      0
      0
    2. Hi Rik,

      Many thanks for the reply! I was able to get the most of the formula to pick up using a ; symbol to break up the lines – I thought I had cracked it, however it looks like the ForAll section now has a bit of trouble:

      ForAll(
      colHistoryTemp,
      Collect(
      colHistory,
      {
      Date: DateTimeValue(
      First(
      Split(
      Result,
      “;”
      ).Result,
      “en-GB”
      ),
      Version:
      The open brackets for ForAll & Collect have errors as well as everything inbetween First( & Version: is all underscored red as though it’s errored – apologies for the delay in response!

      0
      0
    3. Apologies for the late reply. If I look at the text, it still seems like the double quotes are not consequently the same everywhere. E.g. the opening and closing quotes of the ; are different, as well as the en-GB string

      0
      0
  4. Hi Rik,

    This is very usefull.

    Can we go further and extract more detailed informations? I would like to show all modified fields for each version. Juste like when we go in Sharepoint list and show version history.

    I’ve been trying to work with the body itself but once I understood its structure, there is no “modified” value in there. But there is a link with a specific ID for every version. I believe we can use that.

    “Fields”:{
    “__deferred”:{
    “uri”:”https://[tenant].sharepoint.com/sites/[sitename]/_api/SP.ListItemVersion[unique identifier]/Fields”}
    },

    I am not sure how to proceed. Probably another http request flow, maybe we could run it in the same flow.

    NB: We can now use index() instead of last(firstN())

    0
    0
    1. A single version does not have a modified property, simply because you cannot modify a version. The modified date of the item from that specific version is the Created property of your version. Sounds silly and complex, but that’s the way it is 🙂

      0
      0
    2. Hello Rik,
      Thank you for your reply.

      My goal is to make something just like when we look at version history of a sharepoint list item.

      It list versions, and the fields with values that changed on that version.

      This solution actually show only the list of versions and dates. I want to show what has been modified, which values changed.

      0
      0
    3. That is possible, but for that, you need to pull each version information including its metadata and comparing it with the previous version (again with all metadata). This is very complex and error prone. These kind of things I would suggest to let SharePoint just take care of it for you. So just point your users to SharePoint if they want this kind of information

      0
      1
  5. Hi, I am trying capture version history in powerapp.
    I have followed the above steps, I am having error at
    ClearCollect -> expect operator at this point in the formula
    and
    colHistoryTemp -> not recognized

    0
    0
    1. Looks like you’ve misplaced an operator somewhere in your formula. Are you using an English locale or another locale that doesn’t accept the comma?

      0
      0
  6. Hi Rick great post. I’m applying your script, but I facing an issue trying to add the OData__x005f_CheckinComment Field in the script. The Rest API is returning the same checkin comment (last comment) for all versions.

    I Tried to change the API to _api/Web/GetFileByServerRelativePath(decodedurl=’FILEPATH_WITHEXTENSION’)/Versions. With this script, I’m able to found all checkin comments for each version, but isn’t possible to get the [Editor] (don’t have).

    The issue is on the API (when I put the API directly in the browser, I can see the repeated checkin comments). In the flow/power apps all worked fine.

    Do you have an idea what the reason for the checkin comment repeating for each version?

    0
    0
    1. Unfortunately, I don’t know why this is happening. It’s been a while, but if I reminder correctly, I think I struggled with the same thing at the time and didn’t find any solution

      0
      2
  7. I get the error “Name isn’t valid. ‘Result’ isn’t recognized” in the Split function.

    Does anyone have an idea how to solve this?

    0
    0
    1. Do you happen to know which Result is being referred to? In this example there a multiple Result parameters which doesn’t make it easy to troubleshoot unfortunately. Basically it means that somewhere along the road, it gets an empty result so it does not populate the Result as it should be. So I think you should break up the formula in pieces (you can use variables or collections) for this and see where the outcome is empty. From there, you can further troubleshoot the issue

      0
      0
    2. If you’re still after this… Replace ‘Result’, with ‘Value’.

      The ClearCollect for colHistoryTemp is splitting the varHistory string into a one column collection called ‘Value’.

      3
      0
  8. You might replace ” ‘ ” with ” ‘ ” in items(‘Apply_to_each_version’)[‘Created’].
    It worked for me.

    0
    1
  9. I’m stuck at the items(‘Apply_to_each_version’)[‘Created’] step:
    I cannot get past the error. I cannot figure out how in the expressions tab, to set it up.
    I keep getting “the expression invalid”
    Do I need to create variables? what do I use in the expressions tab to be able to use the items(Apply to each_version)?

    0
    0
    1. When you get a ‘the expression is invalid’ error, it often means that it is not formatted correctly. Are you sure you have closed all the brackets correctly and using the correct (single) quote characters? Sometimes, copy-pasting quotes from a blog to your flow may result in an invalid character.

      0
      0
  10. I was trying to use the below function on button “OnSelect” to get the output from Flow into a variable in PowerApps but end with seeing this error

    Name isnt valid, ThisItem isnt recognized.

    Set(
    varHistory,
    VersionHistory.Run(ThisItem.ID).history
    )

    0
    0
    1. You need to make sure to add the Set() formula to one of the buttons within your gallery row. ThisItem will pick the current item (row) from your gallery and the .ID attribute means it will pick the ID propery of that specific row. That will be passed to your flow to get the version history.

      0
      0
  11. Thank you for this! It works great for me. However, I have a content column (enhanced rich text enabled) and wants to the different version of content. It does show the text but it doesn’t show images and hyperlink.
    Any idea how I can make it work?

    0
    0
    1. I’m not really sure what you’re trying to achieve. If you revert to a previous version, all contents should be as it was before (except if you changed the column type in-between versions)

      0
      0
  12. I previously had this working but had to recreate and am now getting an error.

    When setting this variable:
    Set(varHistory,
    RunName.Run(ThisItem.ID).versionHistory);

    The error is underlining “versionHistory” and states:
    “Name isn’t valid. ‘versionHistory’ isn’t recognized.”

    In the Flow “versionHistory” is the name of the string variable used in the Apply to each.

    Any ideas what is happening?




    0



    0
    0
    0
  13. Thanks for the reply! Yeah I noticed that mistake when I tried to test the flow I ended up creating a new flow instead. Now everything is working as intended; Quick question though is it possible to get the version history content from Sharepoint? As of now it is only showing the different versions of an item but not the actual content of the version.

    1
    0
    1. I’m assuming that is possible, but I haven’t played around with that. I think you can play around with the metadata a bit. In my post I only pull the Created, VersionLabel and Editor properties, but I think you can pull the other information as well. There is also the option to use the ‘Get changes for an item or a file’ action, which allows to to pull all changes since a specific version.

      0
      0
  14. Good day I followed your tutorial however when I call the flow to Powerapps it is giving an error to Versionhistorydemo.Run “invalid number of parameters received 1, expected 3”.

    0
    0
    1. You probably configured too many ‘Ask in Power Apps’ parameters. Even even you delete them in your flow, your Power App keeps asking for them. This is a very annoying bug that is rumored to be fixed soon. You can either delete your flow and create it again or just pass dummy data to the parameters that are not being used.

      1
      0
  15. Fantastic tutorial! Many thanks.
    Is there a method you would recommend for having this run when the form is initiated?
    Would the form OnView work for example?

    0
    0
  16. Hello,

    When I separately enter each of the

    items(‘Apply_to_each_version’)[‘Created’]
    items(‘Apply_to_each_version’)[‘VersionLabel’]
    items(‘Apply_to_each_version’)[‘Editor’][‘LookupValue’]

    into the “append to string variable” expression tab inside the apply to each loop, it says “the expression is invalid” when I press OK. Please advise on how I can fix this.

    0
    0
    1. You cannot separate expressions from out the expressions tab itself. You need to add each expression separately en then create a new line and add the next expression

      0
      4
  17. Hi Rik,
    Your posts have been so helping in trying to figure out how to grab the sharepoint list version history! I tried several other solutions before finally stumbling on yours, and boy am I ever a happy camper! Thank you!!

    I do have a question with regards to the number of properties to show. In your example here, you’ve chosen 3 properties, but If I have several more, how do I adjust the First(), FirstN() and Last()? I tried to play around with a with different options, but none seem to be quite right. Are you able to help me with this? I’m very much a novice when it comes to power automate, so I was heavily reliant on this amazing solution you’ve share with us.

    Thank you so much!

    I start this part like so:
    ForAll(
    colHistoryTemp,
    Collect(
    colHistory,
    {
    WorkStatus: First(
    Split(
    Result,
    “;”
    ).Result
    ).Result,
    PlannedYear: Last(
    FirstN(
    Split(
    Result,
    “;”
    ).Result,
    2
    ).Result
    ).Result,
    Discipline: Last(
    FirstN(
    Split(
    Result,
    “;”
    ).Result,
    3
    ).Result
    ).Result,
    System: Last(
    FirstN(
    Split(
    Result,
    “;”
    ).Result,
    4
    ).Result
    ).Result,
    Equipment: Last(
    FirstN(
    Split(
    Result,
    “;”
    ).Result,
    5
    ).Result
    ).Result,
    EquipmentType: Last(
    FirstN(
    Split(
    Result,
    “;”
    ).Result,
    6
    ).Result
    ).Result,
    WorkGroup: Last(
    FirstN(
    Split(
    Result,
    “;”
    ).Result,
    7
    ).Result
    ).Result,
    Facility: Last(
    FirstN(
    Split(
    Result,
    “;”
    ).Result,
    8
    ).Result
    ).Result,
    Station: Last(
    FirstN(
    Split(
    Result,
    “;”
    ).Result,
    9
    ).Result
    ).Result,
    StnUnit: Last(
    FirstN(
    Split(
    Result,
    “;”
    ).Result,
    10
    ).Result
    ).Result,
    Description:Last(
    FirstN(
    Split(
    Result,
    “;”
    ).Result,
    11
    ).Result
    ).Result,

    and so on and so forth, and end it like this:

    CreatedBy: Last(
    FirstN(
    Split(
    Result,
    “;”
    ).Result,
    75
    ).Result
    ).Result,
    Modified: DateTimeValue(
    First(
    Split(
    Result,
    “;”
    ).Result
    ).Result,
    “en-us”
    ),
    ModifiedBy: Last(
    FirstN(
    Split(
    Result,
    “;”
    ).Result,
    77
    ).Result
    ).Result,
    Version: Last(
    Split(
    Result,
    “;”
    ).Result
    ).Result
    }
    )
    );

    0
    0
    1. Splitting arrays is a bit of a hassle, I know. Basically, you need to know where your object is stored in terms of location inside the array. If your object is the first one in the array, you use First(). If your object is the last one in your array, you use Last(). If your object is somewhere in between, you use Last(FirstN()). For example: if your object is the 5th object of 8 objects in your array, you call it by calling the last object of your first 5 objects, like so: Last(FirstN(Split(Result,”;’).Result,5).Result).Result. I hope this helps you out, otherwise, let me know!

      0
      0
  18. Hi, thanks for the excellent step by step, I was able to reproduce it here successfully! I would like to know how to get the exact data change for each version as well as we can see in the SharePoint “Version history”. Do you know how to do that?

    1
    0
    1. It’s been a while and it seems I don’t have the exact Power App running anymore in my tenant. But when you run the /versions API call, you should be returned with an XML that contains the entire version history including the values of each field per version. I guess should build something that checks each field of a specific version with the same field of the previous version. If that value has changed, you can write the field and its value back into your history variable to show in your Power App. I hope this is specific enough for you. Otherwise, I’ll have to rebuild the Power App and flow and figure it out myself exactly

      1
      0
    2. Hi Rik De Koning,

      Thanks for your answer! I was just wondering if we have something ready from SharePoint, since we already can see that “Version history” working on SharePoint. But thanks for the tip, I am going to try something from here!

      0
      0
  19. Hi, I’m a super beginner here. What do you mean by “Tenant” here:

    /sites//_api/web/lists/GetByTitle(”)/items()/Versions

    0
    0
  20. Thanks for this clear step by step guide. Trying to piece this together and test it along with getting the other valid fields to pull from a custom list took a little trial and error. Luckily the flow error message returns a full list of valid field names if you pass it an invalid field name.
    Was able to get lookup field data as well.

    One thing I learned, when using “QuickEdit”, was that for each field edited on a given a list item, a new version version is created. Makes doing a compare with a previous version more of a pain.

    Thanks again great post.

    0
    0
  21. I was able to successfully implement this and get a response back in Power Apps almost instantly. Strangely enough though, even though in Power Automate it shows that my ‘Append to String Variable’ shows three versions of my list item, the ‘versionHistory’ that is sent to Power Apps only has the latest version. Any idea why that may be happening?

    0
    0
    1. Please disregard my comment. I didn’t add a pipe at the beginning of each the ‘Append to String Variable’ which was causing the issue.

      0
      0
  22. There is some proprieties to data of the version?
    I use a text column with versioning to store the comments to that item.
    Now i want to show these text changes in the power apps.

    0
    0
    1. This will get the version history from SharePoint directly. No need to store it anywhere. If you do want to store it somewhere, I recommend using a multiple lines of text column without formatting (plain text)

      0
      0
  23. Good day,


    Set(
    varHistory,
    Versionhistorydemo.Run(ThisItem.ID).history
    )”
    Gives me an error”Incompatible type.We can’t evaluate you formula because the context varible types are incompatible with the types of values in other places in your app”

    0
    0
    1. Are you sure you don’t have your varHistory variable defined elsewhere in your PowerApp? And is your versionHistory variable in your flow a string variable?

      0
      0
    2. I’m also having this issue.

      varHistory isn’t defined anywhere else.
      my variable in flow is a string

      0
      0
    3. When the parameter type in Power App matches the variable type in Power Automate, you shouldn’t be getting this error. Please make sure they’re both of the same type. What does your flow run give as output for your history output?

      0
      0
    4. I am having a similar issue but seeing the error “The function ‘Run’ has some invalid arguments. Name isn’t valid. This identifier is not recognised.

      Set(
      varHistory,
      VersionHistory.Run(ThisItem.ID).history
      )

      0
      0
    5. Did you name your Respond to Power Apps parameter ‘history’? (without quotes) It looks like your flow cannot find the parameter, so I’m guessing you used another name for it

      0
      0
    6. I did, the parameter is called history. The intelli-sense picks it up so I selected it. The ID in my flow is called ID. Typing ThisItem.ID intelli-sense does not detect it.

      0
      0
    7. Thanks Rik. I managed to find the problem. I wasn’t using a gallery so didn’t need ThisItem. Replaced ThisItem with the field i needed and its working.

      Great blog, thanks for your help!

      0
      0
  24. Good day,
    That example is very good I want to know if it would be possible to make it View SharePoint View Entries(Append Comments) which captures comments by different uses in PowerApps

    0
    0
  25. Have been trying to find something to get this done for ages and now using notepad++ to find more of the list item fields can get every version with all the data. Fantastic write up thanks.

    As an add on to this, it would be amazing to be able to filter the results to only show the field that changed in each version (similar to what the version frame shows in the actual list) I am sure this can be done with some long winded coding if MS cant figure out how to export that frame result easily.

    Excellent Work

    0
    0

Leave a Reply

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

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

The reCAPTCHA verification period has expired. Please reload the page.

This site uses Akismet to reduce spam. Learn how your comment data is processed.