Our SharepointKings team really wanted to share this because when we needed this kind of facility we did not find many articles on this topic. so we thought to dig in this and find out something.
Ok, let's get to the business straight forward. The requirement was to have History for the List. Yes, a history for the list.
So bottom line is working with versions in List programmatically.
So we thought that there is a default facility in Document Library for Version and it is very famous for versions, but we actually never came across list history. so we decided to look on the List Settings and yes we were right, we found that there is an option to have version for the List also.
To Enable the Versions, Go to List Settings and go to Version Settings and then Select Create a version each time you edit an item in this list? to true. there you go, you have just made versoning option on.
Now, Try to edit any item from that list and then Select the ECB of that Item, see you will find Version History option, Click on that and you will see all changes that you have just performed. So this is very nice for the End User.
But, What about the Developer if they have to do it by code and display the result of any previous version????
So this article focuses on this.
Let me give you a brief introduction on what all classes we will require to get this thing done.
Let's consider a scenario where you need to check all versions of all ListItems in the List.
First you take an object of the list in which you need to find our the versions of ListItems.
Considering that i am writing code in Web Part, change the code accordingly (If Needed).
SPList objList = SPContext.Current.Web.Lists["{your_list}"];
SPQuery objQuery = new SPQuery();
objQuery.Query = "<Where><Gt><FieldRef Name=\"ID\"/><Value Type=\"Counter\">0</Value></Gt></Where>";
SPListItemCollection objItemColl = objList.GetItems(objQuery);
Note that update your code accordingly in single line. here code is written in multiple lines only for readability.
Here what we have done is we got all ListItems so far for the list.
Now, we will proceed in getting the versions of each ListItem.
foreach (SPListItem objItem in objItemColl)
{
SPListItemVersionCollection objVerisionColl = objItem.Versions;
//Above Line gets all versions of the ListItem. If it returns 1, that means nothing is modified. no version //for this item.
if (objVerisionColl.Count > 1)
{
//Navigate to each version of the ListItem
foreach (SPListItemVersion objVersion in objVerisionColl)
{
int versionID = objVersion.VersionId;
//Returns incremental IDs starting from 512,1024,1536... for each version
DateTime timeofcreation = objVersion.Created;
//VersionLabel - Gets 1.0,2.0,3.0 as default versions for each iteration
string strVersionLabel = objVersion.VersionLabel;
SPListItem objLstItm = objVersion.ListItem;
}
}
}
This means If the ListItem is modified for 3 times, the above loop for that ListItem will execute 3 times and you will get the VersionId as 512,1024,1536 Likewise. VersionLabel as 3.0, 2.0, 1.0. It returns by default from latest to oldest.
So This is the way to get all versions of the ListItem. So now the question is how to get the Data of old versions.Check out the last line in the loop which actually gets the SpListItem of that Version.
So first get the SPListItem that you want and then check for all versions just like the above code and use simple technique to retrieve the data. Consider i have three columns. FirstName, LastName and Address in the List.
So all i have to do is, once i get the Version that i want to fetch take its SPListItem object and then access its fields,
string strFirstName = Convert.ToString(objLstItm["FirstName"]);
string strLastName = Convert.ToString(objLstItm["LastName"]);
string strAddress = Convert.ToString(objLstItm["Address"]);
Now you have the old version data on your hand. Play with it on your own way!!!!
28 comments:
Get Version Data
string strFirstName = Convert.ToString(objLstItm.Version[{VersionCount}]["FirstName"]);
string strFirstName = Convert.ToString(objLstItm.Version[{VersionCount}]["FirstName"]);
Thank u so much. Personally i had seen any blog on verions data of list item.
It was a great help.
Kuldeep Kadyan
While looping through items and versions like you are, only the most recent versions field values are being returned for me.
Is there a setting that needs to be set to allow you to programatically get previous versions field values?
Blake,
you can also get any previous version from mentioned method or below method.
string strValue = listItem.Versions.GetVersionFromLabel("Version Lable")["FielName"].ToString();
OR
string strValue = listItem.Versions[1]["FieldName"].ToString();
//use 1 for previous version
Can I use the same piece of code to get previous versions for a document in a document library.
sure, you can use it for doc lib also
doc lib is also inherited by base class of list.
Excellent writeup!
Excellent writeup!
Is there a way to Reject a previous version of a document ?
There is only one method called Deny which I assume will Reject the document itself.
However, I would like to Reject a specific version of a document.
Is this possible?
JD,
actually how deny will behave to your document. whether it is same as reject or not? and specifically rejecting particular version is more confusing? you can try a custom workflow if applicable but again don't make it so complected to manage.
The SharePoint UI does allow one to Reject a previous approved version of a document.
So there has to be a mechanism that will allow one to programmatically Reject a version of a file as well (at least I am hoping hard).
I do not have the luxury of a workflow as this is going to be a one time activity.
If SharePoint allows to Reject a version from the UI, then why cannot we do it through code?
Deny is the closest method that I could find to Reject functionality. But unfortunately it Rejects the latest version of a document and not the version one that you want .. :(
Any thoughts .....
JD,
we tried your scenario with below steps
1) create doc lib
2) doc lib setting --> version setting --> Require content approval for submitted items? == yes
3) doc lib setting --> version setting --> Create a version each time you edit a file in this document library? == Create major versions
other options are not relevant.
now
Upload a document
approve it
change it/upload another version
approve it
change it/upload another version
so current version is 3.0
go to version history of document
if you check ECB menu of latest version there are only 3 option
a. view
b. restore
c. reject this version
and if you check ECB menu of the previous version there are also 3 option
a. view
b. restore
c. delete
now please let me know how you able to reject previous version from front end.
Being a newbie at this i have two questions:
What Webpart are you writing this code into?
How are you displaying this information once you have collected it?
Thanks,
RD
RD,
You can use this code depend upon your requirement.
like may be in win application for admin kind of stuff or may be on webpart where you can show user the previous version depend upon some business logic.
dear all;
thanks for the post, it's great but
i tried this
Get Version Data
string strFirstName = Convert.ToString(objLstItm.Version[{VersionCount}]["FirstName"]);
i get all versions but for specific column which hard coded as string but i have lots of columns in my list, i don't know which changed, i want to get the changed column only with it's versions..
here we r able to get versions but only for certain column,
how can it be without specifing column in code and get it dynamic?
like for example, title changed in version 1 and then e-mail column changed in versioin 2?
i get only changes and not all columns because in version 1, e-mail column didn't change
i hope u got me, i need also this fast.. u hope u can help me
Thanks.
Mai Omar
Senior Solutions Developer
ITEgyptCorp
Website: http://www.itegyptcorp.com
Blog: http://maiomar.itegyptcorp.com
Omer,
we got your question.
you want previous version of selected column like not the list item old version
but the old version of the column you want whether it can be different then list item version number.
so we got your question.
its quite genuine but confusing.
we are trying to find your answer and soon try to reply back.
Its a good post. However, I have few questions:
SPListItem objLstItm = objVersion.ListItem;
I don't think this would give the values corresponding to that particular version instead, it gives item values of the most latest Version.
Omar,
Are you looking for something which allows you to capture the columns names whose values have changed? Do you want to compare between any two versions? or compare with the latest version if anything has changed? If you can provide me with these details then I'll try to post the code for your query, provided if you are still waiting for a solution.
-Venkat
Hay Venkat,
Thanks. it would be great if you post related to Omar's problem.
bool bItemChanged = false;
ArrayList alUpdatedFields = new ArrayList();
SPListItemVersionCollection objVersionColl = objItem.Versions;
if (objVersionColl != null && objVersionColl.Count > 0)
{
foreach (SPListItemVersion item in objVersionColl)
{
if (item.VersionLabel.ToString() != objItem["_UIVersionString"].ToString())
{
foreach (SPField objField in objItem.Fields)
{
if (!objField.ReadOnlyField && IsValueChanged(objField.Type, objItem[objField.InternalName], item[objField.InternalName]))
{
bItemChanged = true; alUpdatedFields.Add(objField.Title);
}
}
if (bItemChanged)
{ break;
}
}
}
}
In the above code I am looking for the previously modified version compared to the current version and adding those fields to the Array List, instead we can have an HashTable to add the Field and its value as a key value pair.
if (item.VersionLabel.ToString() != objItem["_UIVersionString"].ToString()) //This condition is used to ignore the comparison of the current version with itself. you can add your own logic to compare with the actually needed version
Here is the function to check if the value for a particular field has changed compared to other version:
private bool IsValueChanged(SPFieldType type, object FirstValue, object SecondValue)
{
if (string.IsNullOrEmpty(Convert.ToString(FirstValue)) && string.IsNullOrEmpty(Convert.ToString(SecondValue)))
{
return false;
}
else if (string.IsNullOrEmpty(Convert.ToString(FirstValue)))
{
return true;
}
else if (string.IsNullOrEmpty(Convert.ToString(SecondValue)))
{
return true;
}
switch (type)
{
case SPFieldType.DateTime:
return !Convert.ToDateTime(FirstValue).Date.Equals(Convert.ToDateTime(Convert.ToString(SecondValue)).Date);
case SPFieldType.User:
break;
case SPFieldType.Text:
case SPFieldType.Note:
return !Convert.ToString(FirstValue).ToUpper().Equals(Convert.ToString(SecondValue).ToUpper());
case SPFieldType.Boolean:
return !Convert.ToBoolean(FirstValue).Equals(Convert.ToBoolean(SecondValue));
case SPFieldType.Attachments:
break;
default:
return !FirstValue.Equals(SecondValue);
}
return false;
}
Hope this helps:
Regards,
Venkat
http://tips-in-sharepoint.blogspot.com/
http://tipsinsharepoint.wordpress.com/
Also, you can refer to my blog for this solution and also let me know if you were looking for something else:
http://tips-in-sharepoint.blogspot.com/2010/07/working-with-versions-in-sharepoint.html
http://tipsinsharepoint.wordpress.com/2010/07/28/working-with-versions-in-sharepoint-list-programmatically/
Regards,
Venkat
Venkat,
this is great help.
Omar and other user should look at this.
thanks Venkat
Thanks,
SharepointKings Team
How can I update the data of old version ?
Anonymous,
its great question...if you can change the old data then what it means to save old data and if history is editable then its not called history, right?
if you change the data it will create new version so rather then changing old it create another one.
still you can try changing it by item.systemupdate it might work.
share your experience as we had no idea weather it is possible or not or how is it behave.
Great Blog!
One more question about version:
Is it possible make a real roll back? That means, if my current version is version n, I want to set version n-1 as current version and delete the version n. Restore always creates a new version n+1.
Go ahhead with your Blog. It iss aways great help.
yes it is possible to rollback.
Hi SharePoint Kings,
can you please give me an short example how to do a rollback.
Trying to delete the current version gets me an error that I can't do so (delete the cuurent version). Trying to set version n-1 as the currrent version gets me an error that this field is read only.
what we suggest is do not delete current item.
just recover the version you required.
Post a Comment