Tuesday, November 24, 2009

How To: Copy list items across site collections in SharePoint

Technorati Tags: ,,,

The other day I demonstrated some code on how to copy files from one document library to another in another site collection. However, the code does not work with lists and list items. Dealing with folders and items within folders is completely different with SharePoint lists. In fact, it seems needlessly complicated. The sample code below takes a source site collection url, destination site collection url, list name (must exist in both source and destination site collection, the string of the UniqueId guid of the starting folder, and the folder’s url.

The difficult part was getting the folder url to work when creating a new folder in a SharePoint list. You must use the SPListItemCollection.Add method passing in an empty string, SPFileSystemObjectTyp.Folder, and the folder url.  In order to make this work with sub folders you must construct a folder url in the form of “grandparent.folder.name +/ + parent.folder.name … + / + folder.name”. There is nothing on the SPFolder object that can give you this “container” path. So I had to do some substring(ing).

The other problem was getting at the child items of a folder in a SharePoint list. When using a document library the files collection of the SPFolder works great, unfortunately, this does not exist with SharePoint lists. So you have to make use of the SPQuery object to bring back the child items within the folder. Finally, you can use linq to filter out the list items from the folders. All in all it works great and will create an identical copy of the folder structure from one list to the other across site collections.

 

public static void CopyListFolderToAnotherSiteCollection(string sourceUrl, string destinationUrl,
          string listName, string uniqueFolderID, string newFolderUrl)
      {
          SPListItem newItem = null;

          using (SPSite sourceSite = new SPSite(sourceUrl))
          {
              using (SPWeb sourceWeb = sourceSite.OpenWeb())
              {

                  SPList sourceList = sourceWeb.Lists[listName];
                  SPFolder sourceFolder = sourceWeb.GetFolder(new Guid(uniqueFolderID));
                  SPQuery q = new SPQuery();
                  q.Folder = sourceFolder;
                  SPListItemCollection sourceItems = sourceList.GetItems(q);
                  using (SPSite destSite = new SPSite(destinationUrl))
                  {
                      using (SPWeb destWeb = destSite.OpenWeb())
                      {
                          SPList destList = destWeb.Lists[listName];

                          SPListItem destItem = destList.Items.
                              Add(string.Empty, SPFileSystemObjectType.Folder, newFolderUrl);

                          destItem.Update();
                          SPFolder destFolder = destWeb.GetFolder(destItem.UniqueId);

                          List<SPListItem> listItems = (from l in sourceItems.OfType<SPListItem>()
                                         where l[SPBuiltInFieldId.ContentType].ToString() != "Folder" select l).ToList();

                          List<SPListItem> folderItems = (from l in sourceItems.OfType<SPListItem>()
                                                        where l[SPBuiltInFieldId.ContentType].ToString() == "Folder"
                                                        select l).ToList();

                          foreach (SPListItem sourceItem in listItems)
                          {
                              newItem = destList.Items.Add(destFolder.ServerRelativeUrl,
                                                                                  SPFileSystemObjectType.File,null);
                              newItem["Title"] = sourceItem["Title"];
                              newItem[SPBuiltInFieldId.ContentType] = sourceItem[SPBuiltInFieldId.ContentType];
                              newItem.Update();
                          }

                          foreach (SPListItem f in folderItems)
                          {
                              SPFolder folder = f.Folder;
                              int index = folder.ServerRelativeUrl.IndexOf(sourceList.RootFolder.Url);
                              string folderUrl = folder.ServerRelativeUrl.Substring(index + sourceList.RootFolder.Url.Length + 1);
                              CopyListFolderToAnotherSiteCollection(sourceUrl, destinationUrl,
                                                           listName, folder.UniqueId.ToString(), folderUrl);
                          }

                      }
                  }
              }
          }
      }

1 comment:

Anonymous said...

Could you give an example of what will will the parameter values, like is you want to copy "SourceList" from site 1 to site 2 and source list contains folders at the root level and those folders contain more sub folders and then list items in those sub folders. what will be the starting parameter values for the routine.

Post a Comment