Monday, August 5, 2013

Copy SharePoint list items from one list to another and retain full version history and attachments.

Here’s some ‘rough n ready’ code to perform a copy of all list items from one list to another. It will retain all version history, dates, authors, editors, etc. It will also allow you to copy fields from the source list to the target list where the target list field has changed it’s name (must be of the same data type though). In addition, any file attachments for list items are also migrated. Note that file attachments are not versioned. Make sure the destination list has versioning turned on if the source list has versioning enabled.

What doesn’t this do? it doesn’t copy views (personal or public) and it doesn’t copy any permissions. It is also not very robust code. (it’s just a proof of concept at the moment, but feel free to clean it up!)

anyhow.. this is not production worthy code, but it does work. thought it may be useful to someone down the track. Let me know if you use it! 8)

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;

namespace MigrateListItemsAndVersions
{
    class Program
    {

        // ****** Setup parameters *******
        static string siteURL = "http://server/site/";
        static string source = "sourcelistname";
        static string dest = "destinationlistname";
        // this is a mapping dictionary to be used when the fields are different names in the target list. Only list the fields that have changed (must be same type to work!!).
        static Dictionary<string, string> fieldMapping = new Dictionary<string, string>
            {
                {"oldcolname","newcolname"}
            };
        // ****** Setup parameters *******


       
        static void Main(string[] args)
        {

            using (SPSite site = new SPSite(siteURL))
            {
                using (SPWeb web = site.OpenWeb())
                {
                    web.AllowUnsafeUpdates = true;
                    SPList sourceList = web.Lists[source];
                    SPList destList = web.Lists[dest];
                    foreach (SPListItem sourceItem in sourceList.Items)
                    {
                        CopyItem(sourceItem, destList);
                    }
                }
            }
        }

        public static SPListItem CopyItem(SPListItem sourceItem, SPList destinationList)
        {
            SPListItem targetItem = destinationList.Items.Add();
      
            //loop over the soureitem, restore it
            for (int i = sourceItem.Versions.Count - 1; i >= 0; i--)
            {
              
                //set the values into the target list
                foreach (SPField sourceField in sourceItem.Fields)
                {
                    SPListItemVersion version = sourceItem.Versions[i];

                    if ((!sourceField.ReadOnlyField) && (sourceField.InternalName != "Attachments"))
                    {
                        targetItem[Mapper(sourceField.Title)] = version[sourceField.Title];
                    }
                    else if (sourceField.Title == "Created" ||
                        sourceField.Title == "Created By" ||
                        sourceField.Title == "Modified" ||
                        sourceField.Title == "Modified By") {
                            targetItem[sourceField.Title] = version[sourceField.Title];
                    }
                }

                //update the target item and loop over the the next version

                targetItem.Web.AllowUnsafeUpdates = true;
                targetItem.Update();
                targetItem.Web.AllowUnsafeUpdates = false;
            }

            // now check for attachments (not versioned) and copy
            foreach (string fileName in sourceItem.Attachments)
            {
                SPFile file = sourceItem.ParentList.ParentWeb.GetFile(sourceItem.Attachments.UrlPrefix + fileName);
                targetItem.Attachments.Add(fileName, file.OpenBinary());
            }

            targetItem.Web.AllowUnsafeUpdates = true;
            // perform a systemupdate so that a new version is not created
            targetItem.SystemUpdate();
            targetItem.Web.AllowUnsafeUpdates = false;
            return targetItem;
        }

        // updates the output fieldname if the destination list has different fields (must be the same type though!)
        public static string Mapper(string fieldNameIn)
        {
            // if not in the mapping dictionary then use the infieldname as the field to write to.
            string fieldNameOut = fieldNameIn;
            if (fieldMapping.ContainsKey(fieldNameIn)) fieldNameOut = fieldMapping[fieldNameIn];
            return fieldNameOut;
        }
    }
}

No comments:

Post a Comment