Did you ever wanted to get a report on version history stored in SharePoint (list and/or library)! If so you are at the right place. Content management made easier by SharePoint! SharePoint 2010 includes a great feature called Version Control by providing one centralized location for files. Version control provides the functionality to save multiple instances (versions) of the same document and you can easily configure versioning control for a document library by going to Library Settings > General Settings > Versioning Settings. You can also set up retention policies, check documents in and out, create a document version history (major/minor) that you can access, manage, and modify easily with your web browser.

Recently one of the clients asked me to provide the list of documents that are modified by a particular user (Let's say UserXYZ) in a document library. Sounds pretty simple, right? The first thought that came to my mind was to

  1. Create a view in the document library
  2. Set up a filter on the view where "Modified By" is equal to UserXYZ as shown in the Figure 1
  3. Export the view to Excel

But I was quick to realize that it's not the right solution. Out-of-Box SharePoint document library/list views can only filter items based on the most recent version of file/document! Out-of-box views can't iterate through the previous versions of the file. What a limitation!

Let's look at the following scenario where we have a document in a document library (versioning enabled) which is modified by UserXYZ. Say after sometime another user called UserABC came in and modified the same document. So now we have 2 versions of the same document with the most recent version being modified by UserABC. Now I would like to have the list/report of documents that are modified by UserXYZ. If I create view with "Modified By" is equal to UserXYZ (refer to Figure 1), the view doesn't return any items because Out-of-box views can't look into the version history of the item/file. So even though UserXYZ modified the document, it would never show up in the view because it's not the most recent version. Alright...What to do now, call Microsoft? Just kidding! Here comes the hulk called PowerShell to rescue us! Hulk? Yeah.. It's really powerful, I love it.

So I've decided to write a PowerShell Script to iterate through all the versions of all the items in a given document library or a list. The following PowerShell script would provide you the list of items which are modified byUserXYZ.

<span class="kw3">if</span><span class="br0">(</span><span class="br0">(</span><span class="kw1">Get-PSSnapin</span> <span class="sy0">|</span> <span class="kw3">Where</span> <span class="br0">{</span><a><span class="kw6">$_</span></a>.Name <span class="kw4">-eq</span> <span class="st0">"Microsoft.SharePoint.PowerShell"</span><span class="br0">}</span><span class="br0">)</span> <span class="kw4">-eq</span> <span class="re0">$null</span><span class="br0">)</span> 
<span class="br0">{</span>
 <span class="kw1">Add-PSSnapin</span> Microsoft.SharePoint.PowerShell;
<span class="br0">}</span>
<span class="re0">$SPWeb</span> <span class="sy0">=</span> Get<span class="sy0">-</span>SPWeb http:<span class="sy0">//</span>sp2010<span class="sy0">/</span>sites<span class="sy0">/</span>test<span class="sy0">/</span> <span class="co1">#Change the SharePoint site name here#</span>
<span class="re0">$List</span> <span class="sy0">=</span> <span class="re0">$SPWeb</span>.Lists<span class="br0">[</span><span class="st0">"Documents"</span><span class="br0">]</span> <span class="co1">#Change the document library name here#</span>
<span class="re0">$ItemsColl</span> <span class="sy0">=</span> <span class="re0">$List</span>.Items
<span class="kw1">Write-Host</span> <span class="st0">"************************************************************"</span> <span class="kw5">-ForegroundColor</span> Green
<span class="kw1">Write-Host</span> <span class="st0">"The following report provides you the list of documents that are modified by UserXYZ"</span> <span class="kw5">-ForegroundColor</span> Green
<span class="kw1">Write-Host</span> <span class="st0">"------------------------------------------------------------"</span> <span class="kw5">-ForegroundColor</span> Green
<span class="kw3">foreach</span> <span class="br0">(</span><span class="re0">$item</span> <span class="kw3">in</span> <span class="re0">$ItemsColl</span><span class="br0">)</span> 
<span class="br0">{</span>
 <span class="kw3">foreach</span><span class="br0">(</span><span class="re0">$Ver</span> <span class="kw3">in</span> <span class="re0">$item</span>.Versions<span class="br0">)</span>
 <span class="br0">{</span>
 <span class="kw3">if</span> <span class="br0">(</span><span class="re0">$Ver</span>.CreatedBy.User.DisplayName <span class="kw4">-eq</span> <span class="st0">"UserXYZ"</span><span class="br0">)</span> <span class="co1">#Change the user name here#</span>
 <span class="br0">{</span>
 <span class="kw1">Write-Host</span> <span class="re0">$item</span>.Name <span class="st0">"'s version"</span> <span class="re0">$Ver</span>.VersionLabel <span class="st0">"has been Modified by"</span> <span class="re0">$Ver</span>.CreatedBy.User.DisplayName <span class="st0">":: URL ->"</span> <span class="re0">$item</span>.Url <span class="kw5">-ForegroundColor</span> Green 
 <span class="br0">}</span>
 <span class="br0">}</span>
<span class="br0">}</span>
<span class="kw1">Write-Host</span> <span class="st0">"------------------------------------------------------------"</span> <span class="kw5">-ForegroundColor</span> Green
<span class="kw1">Write-Host</span> <span class="st0">"************************************************************"</span> <span class="kw5">-ForegroundColor</span> Green
<span class="re0">$SPWeb</span>.Dispose<span class="br0">(</span><span class="br0">)</span>

Remember to change SharePoint site name, Document library name and user name according to your environment setup. Once you run the above script you would see output/result in the following format.

<span class="sy0">********************************************************************</span>
The following report provides you the list of documents that are modified by UserXYZ
<span class="sy0">---------------------------------------------------------------------</span>
Sampledoc.txt <span class="st0">'s version 2.4 has been Modified by UserXYZ :: URL -> Documents/ Sampledoc.txt
testdoc.txt '</span>s version <span class="nu0">0.2</span> has been Modified by UserXYZ :: URL <span class="sy0">-></span> Documents<span class="sy0">/</span> testdoc.txt
<span class="sy0">---------------------------------------------------------------------</span>
<span class="sy0">********************************************************************</span>

Wasn't that cool! OK, what if you are required to get the list of documents which are modified by UserXYZ in an entire site? Let's make it happen by tweaking the script to make it more powerful. By the way I am bored of using UserXYZ. To add some more flavor to our script let's create a report which provides you the list of documents which are modified by System Account. This kind of requirement may surface during the migration from MOSS 2007 to SharePoint 2010 or when you move documents from one environment to other. If you don't have the same user in both the environments, some of the documents may show the "Modified By" as System Account.

The following PowerShell Script would iterate through each item's version history of all the lists and document libraries in a given SharePoint site to identify the documents that are modified by System Account.

<span class="kw3">if</span><span class="br0">(</span><span class="br0">(</span><span class="kw1">Get-PSSnapin</span> <span class="sy0">|</span> <span class="kw3">Where</span> <span class="br0">{</span><a><span class="kw6">$_</span></a>.Name <span class="kw4">-eq</span> <span class="st0">"Microsoft.SharePoint.PowerShell"</span><span class="br0">}</span><span class="br0">)</span> <span class="kw4">-eq</span> <span class="re0">$null</span><span class="br0">)</span> 
<span class="br0">{</span>
 <span class="kw1">Add-PSSnapin</span> Microsoft.SharePoint.PowerShell;
<span class="br0">}</span>
<span class="kw1">Write-Host</span> <span class="st0">"***********************************************************************"</span>
<span class="kw1">Write-Host</span> <span class="st0">"***** The following report provides you the list of documents that are modified by System Account ***"</span> <span class="kw5">-ForegroundColor</span> Green
<span class="kw1">Write-Host</span> <span class="st0">"***********************************************************************"</span>
<span class="re0">$SPWeb</span> <span class="sy0">=</span> Get<span class="sy0">-</span>SPWeb http:<span class="sy0">//</span>sp2010<span class="sy0">/</span>sites<span class="sy0">/</span>PShell<span class="sy0">/</span> <span class="co1">#Change the SharePoint site name here#</span>
<span class="kw3">foreach</span><span class="br0">(</span><span class="re0">$List</span> <span class="kw3">in</span> <span class="re0">$SPWeb</span>.Lists<span class="br0">)</span>
 <span class="br0">{</span>
 <span class="re0">$ItemsColl</span> <span class="sy0">=</span> <span class="re0">$List</span>.Items
 <span class="kw3">foreach</span> <span class="br0">(</span><span class="re0">$item</span> <span class="kw3">in</span> <span class="re0">$ItemsColl</span><span class="br0">)</span> 
 <span class="br0">{</span>
 <span class="kw3">foreach</span><span class="br0">(</span><span class="re0">$prevVer</span> <span class="kw3">in</span> <span class="re0">$item</span>.Versions<span class="br0">)</span>
 <span class="br0">{</span>
 <span class="kw3">if</span> <span class="br0">(</span><span class="re0">$prevVer</span>.CreatedBy.User.DisplayName <span class="kw4">-eq</span> <span class="st0">"System Account"</span><span class="br0">)</span> 
 <span class="br0">{</span>
 <span class="kw1">Write-Host</span> <span class="re0">$item</span>.Name <span class="st0">"'s version"</span> <span class="re0">$prevVer</span>.VersionLabel <span class="st0">";"</span> <span class="st0">"URL-->"</span> <span class="re0">$item</span>.Url <span class="kw5">-ForegroundColor</span> Green
 <span class="br0">}</span>
 <span class="br0">}</span>
 <span class="br0">}</span>
 <span class="br0">}</span>
<span class="kw1">Write-Host</span> <span class="st0">"******************* DONE **********************"</span> 
<span class="re0">$SPWeb</span>.Dispose<span class="br0">(</span><span class="br0">)</span>

In recent times I've received lot of requests asking for a way to download the version history of SharePoint items in a given document library or list (which is shown in the Version history dialog box for each item through SharePoint User interface).To get there modify one of the above scripts by replacing

<span class="kw3">if</span><span class="br0">(</span><span class="re0">$Ver</span>.CreatedBy.User.DisplayName <span class="kw4">-eq</span> <span class="st0">"UserXYZ"</span><span class="br0">)</span> <span class="co1">#Change the user name here#</span>
 <span class="br0">{</span>
 <span class="kw1">Write-Host</span> <span class="re0">$item</span>.Name <span class="st0">"'s version"</span> <span class="re0">$Ver</span>.VersionLabel <span class="st0">"has been Modified by"</span> <span class="re0">$Ver</span>.CreatedBy.User.DisplayName <span class="st0">":: URL ->"</span> <span class="re0">$item</span>.Url <span class="kw5">-ForegroundColor</span> Green 
 <span class="br0">}</span>

With the following

<span class="kw1">Write-Host</span> <span class="re0">$item</span>.Name <span class="st0">":: version:"</span> <span class="re0">$Ver</span>.VersionLabel <span class="st0">":: Modified by:"</span> <span class="re0">$Ver</span>.CreatedBy.User.DisplayName <span class="st0">":: URL ->"</span> <span class="re0">$item</span>.Url <span class="kw5">-ForegroundColor</span> Green

Also you can export the output of PoweShell script to Excel by using Export-Csv Cmdlet.You should be good to go. That's it for now and I hope you've enjoyed the blog post! Feel free to email me if you have any questions.

You can download the attached file to access PoweShell Scripts.