Sunday, December 4, 2011

SharePoint reading version programatically

Scenario:
Recently doing a new project we needed to display version information of a list but we decided to make it more generic to support both document library and lists. There were lot of learning , I would say.. so I thought of sharing as always

Lesson Learned:
1. List version information + current version information can easily be retrieved using 'SPListItemVersionCollection' class

2. List version doesn't support version comment

3. SPListItemVersionCollection class is sorted by version number

4. Library version information can retrieved using 'SPFileVersionCollection' class but this will not return current version information.

5. Library version does support a version comment if same name file is uploaded. No comment is supported if 'Edit Properties' feature is used.

6. For Library , SPFileVersionCollection class is not guaranteed to be sorted by version number. So additional headache need to be taken to sort them.

7. For Library , Title column information/changes are stored in "vti_title" column.

About Helper Class Code:
Helper class below supports

1. Retrieving versions information for list/library

2. Retrieving all the changes for one particular field only

3. Support returning all versions / only versions which have changes for a particular field.

Helper Class Code:

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Web;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;

namespace SKN
{
public static class SharePointHelper
{
/// <summary>
/// Adds columns to the table.
/// </summary>
/// <param name="dtVersions">Version History Columns.</param>
public static void AddColumns (DataTable dtVersions)
{
dtVersions.Columns.Add("Source");
dtVersions.Columns.Add("Item");
dtVersions.Columns.Add("ColumnOldValue");
dtVersions.Columns.Add("ColumnValue");

dtVersions.Columns.Add("Version");
dtVersions.Columns.Add("Modified");
dtVersions.Columns.Add("Modified By");
dtVersions.Columns.Add("Comments");
}

/// <summary>
/// Redirection method for list\library
/// </summary>
/// <param name="dtVersions"></param>
/// <param name="web"></param>
/// <param name="listName"></param>
/// <param name="fieldName"></param>
/// <param name="showOnlyChanges">Show only rows which have changes</param>
/// <returns></returns>
public static DataTable GetAllVersions (SPWeb web, string listName, string fieldName, bool showOnlyChanges)
{
DataTable dtVersions = new DataTable();
AddColumns(dtVersions);

SPList spList = web.Lists[listName];
{
if (spList.BaseTemplate == SPListTemplateType.DocumentLibrary)
{
return GetAllLibraryVersions(dtVersions, web, listName, fieldName, showOnlyChanges);
}
else
{
return GetAllListVersions(dtVersions, web, listName, fieldName, showOnlyChanges);
}
}
}

/// <summary>
/// Show all versions of a list
/// </summary>
/// <param name="dtVersions"></param>
/// <param name="web"></param>
/// <param name="listName"></param>
/// <param name="columnName"></param>
/// <param name="showOnlyChanges">Show only rows which have changes</param>
/// <returns></returns>
public static DataTable GetAllListVersions (DataTable dtVersions, SPWeb web, string listName, string columnName, bool showOnlyChanges)
{
SPList spList = web.Lists[listName];
SPListItemCollection listItemColl = spList.Items;

// for each item
foreach (SPListItem listItem in listItemColl)
{
string columnOldValue = "NULL";
bool relavantRow = true;

SPListItemVersionCollection versionColl = listItem.Versions;
for (int i = versionColl.Count - 1; i >= 0; i--)
{
try
{
DataRow dr = dtVersions.NewRow();
dr["Source"] = listName;
dr["Item"] = listItem.Title;

dr["Version"] = versionColl[i].VersionLabel;
dr["Modified By"] = versionColl[i].CreatedBy.User.Name;
dr["Modified"] = GetDateDisplay(web, versionColl[i].Created);

dr["Comments"] = string.Empty;

dr["ColumnOldValue"] = columnOldValue;

if (null != versionColl[i][columnName])
{
dr["ColumnValue"] = versionColl[i][columnName];
}
else
{
dr["ColumnValue"] = "NULL";
}
if (showOnlyChanges)
{
relavantRow = !string.Equals(columnOldValue, dr["ColumnValue"].ToString(), StringComparison.InvariantCultureIgnoreCase);
}
columnOldValue = dr["ColumnValue"].ToString();

if (relavantRow)
{
dtVersions.Rows.InsertAt(dr, 0);
}
}
catch
{
}
}
}

return dtVersions;
}

/// <summary>
/// Show all versions of a document library
/// </summary>
/// <param name="dtVersions"></param>
/// <param name="web"></param>
/// <param name="listName"></param>
/// <param name="columnName"></param>
/// <param name="showOnlyChanges">Show only rows which have changes</param>
/// <returns></returns>
public static DataTable GetAllLibraryVersions (DataTable dtVersions, SPWeb web, string listName, string columnName, bool showOnlyChanges)
{
SPList spList = web.Lists[listName];
SPListItemCollection listItemColl = spList.Items;

foreach (SPListItem doc in listItemColl)
{
string columnOldValue = "NULL";
bool relavantRow = true;
string updatedColumnName = columnName;

if (columnName.Equals("Title"))
{
updatedColumnName = "vti_title";
}

SPFileVersionCollection versionColl = doc.File.Versions;
Dictionary<int, string> myDict = new Dictionary<int, string>();

for (int i = 0; i < versionColl.Count; i++)
{
myDict.Add(i,versionColl[i].VersionLabel);
}

var sortedDict = (from entry in myDict orderby entry.Value ascending select entry).ToDictionary(pair => pair.Key, pair => pair.Value);

foreach(var k in sortedDict)
{
try
{
DataRow dr = dtVersions.NewRow();
dr["Source"] = doc.File.ParentFolder;
dr["Item"] = doc.File.Name;
dr["Version"] = versionColl[k.Key].VersionLabel;
dr["Modified By"] = versionColl[k.Key].Properties["vti_modifiedby"];
dr["Modified"] = GetDateDisplay(web, versionColl[k.Key].Properties["vti_timelastmodified"]);

dr["ColumnOldValue"] = columnOldValue;

if (null != versionColl[k.Key].Properties[updatedColumnName])
{
dr["ColumnValue"] = versionColl[k.Key].Properties[updatedColumnName].ToString();
}
else
{
dr["ColumnValue"] = "NULL";
}

if (showOnlyChanges)
{
relavantRow = !string.Equals(columnOldValue, dr["ColumnValue"].ToString(), StringComparison.InvariantCultureIgnoreCase);
}

columnOldValue = dr["ColumnValue"].ToString();

if (null != versionColl[k.Key].Properties["vti_sourcecontrolcheckincomment"])
{
dr["Comments"] = versionColl[k.Key].Properties["vti_sourcecontrolcheckincomment"];
}

if (relavantRow)
{
dtVersions.Rows.InsertAt(dr, 0);
}
}
catch
{
}
}

DataRow drLatestVersion = dtVersions.NewRow();
drLatestVersion["Source"] = doc.File.ParentFolder;
drLatestVersion["Item"] = doc.File.Name;
drLatestVersion["Modified By"] = doc.File.ModifiedBy;
drLatestVersion["Modified"] = DateTime.Parse(doc["Modified"].ToString()).GetDateTimeFormats()[43];

if (null != doc["Version"])
{
drLatestVersion["Version"] = doc["Version"];
}

if (null != doc["_CheckinComment"])
{
drLatestVersion["Comments"] = doc["_CheckinComment"].ToString().Split('#')[1];
}

// Old Value from stored variable
drLatestVersion["ColumnOldValue"] = columnOldValue;

// Checking for new value
if (null != doc[columnName])
{
drLatestVersion["ColumnValue"] = doc[columnName].ToString();
}
else
{
drLatestVersion["ColumnValue"] = "NULL";
}

if (showOnlyChanges )
{
relavantRow = !string.Equals(columnOldValue, drLatestVersion["ColumnValue"].ToString(), StringComparison.InvariantCultureIgnoreCase);
}

columnOldValue = drLatestVersion["ColumnValue"].ToString();

if (relavantRow)
{
dtVersions.Rows.InsertAt(drLatestVersion, 0);
}
}

return dtVersions;
}

public static string GetDateDisplay (SPWeb web, object p)
{
return SPUtility.FormatDate(web, DateTime.Parse(p.ToString()), SPDateFormat.DateTime).ToString();
}
}
}

1 comments:

MalcolmBradley July 1, 2013 at 9:12 AM  

Nice Posting. SharePoint is very easy to use. This covers a very complicated atmosphere in the system.