Geeks With Blogs

News Contact Me anne.bougie@gmail.com

Post Categories

Annie Bougie
I started this series to show how to copy different kinds of lists in SharePoint. Each type of list has its own challenges. In this article I will also demonstrate how to copy custom fields and keep the same internal name. It’s kind of annoying that you can’t create a field with the internal name you specify, but I found a pretty easy workaround. You create the field using AddFieldAsXml on the list Fields collection, and you use the internal name as the display name. This creates the field with the correct internal name. Then just change the Title property of the field to what you want displayed. Problem solved.

Copying a document library is similar to copying a generic list, except that you also need to copy the document file attached to the list item. You also need to determine the template that was used to create the original list, and use that template to create the new list. That way, when users add a new document, it is of the right document type. Another gotcha in copying document libraries, is that there is a subfolder structure that needs to be copied recursively to get everything in its correct place.

Here's the code. I copied it out of my project, which has everything in its own method, so I apologize if some of my capitalization or field names are not correct. Also, there is a function referenced, CopyFieldValues. If you need to know how to do this, refer to Part 1 of this series. Document libraries can have field values just like other lists, so you'll need to copy those too if you want a complete copy of the list.

// get the document template to use when creating the new list
SPDocTemplate docTemplate;
SPDocTemplateCollection templates = destinationWeb.DocTemplates;
XDocument templateSchema = XDocument.Parse(templates.SchemaXml);
IEnumerable<XElement> paths = templateSchema.Descendants("DocumentTemplateFile");

string sourceUrl = sourceDocumentTemplateUrl.Substring(sourceDocumentTemplateUrl.IndexOf("/") + 1);
XElement path = paths.Where(p => p.Attribute("TargetName").Value == sourceUrl).Single();
XElement docTemplate = path.Parent.Parent;
int type = Convert.ToInt32(docTemplate.Attribute("Type").Value);

SPDocTemplate destTemplate = null;
foreach (SPDocTemplate template in templates)
{
   if (template.Type == type)
      docTemplate = template;
}

Guid newListID = destinationWeb.Lists.Add(sourceList.Title,
                     sourceList.Description,
                     destinationWeb.ListTemplates["Document Library"], docTemplate);

SPList destinationList = destinationWeb.Lists[newListID];

// add any custom fields that were created
foreach (SPField field in SourceList.Fields)
{
   if (!DestinationList.Fields.ContainsField(field.InternalName))
   {
      // create field with correct internal name
      XDocument fieldXdoc = XDocument.Parse(field.SchemaXml);
      XElement fieldElement = fieldXdoc.Element("Field");
      XAttribute displayName = fieldElement.Attribute("DisplayName");
      displayName.Value = field.InternalName;
      string fieldName = DestinationList.Fields.AddFieldAsXml(fieldXdoc.ToString());
      SPField newfield = DestinationList.Fields.GetField(fieldName);
      newfield.Title = field.Title;
   }
}

Here is the code for CopyDocumentLibraryItems, which needs to be recursive to get all the items in all the subfolders:

      protected virtual void CopyDocumentLibraryItems(SPFolder sourceFolder, SPFolder destFolder)
      {
         // get a list of items in the source folder
         SPListItemCollection items = ((SPDocumentLibrary)SourceList).GetItemsInFolder(SourceList.DefaultView, sourceFolder);

         foreach (SPListItem item in items)
         {
            SPFileSystemObjectType myType = item.FileSystemObjectType;
            string relativeDestinationUrl = "{0}/{1}";
            if (myType == SPFileSystemObjectType.File)
            {
               SPFile fi = item.File;
               byte[] filebytes = fi.OpenBinary();
               relativeDestinationUrl = string.Format(relativeDestinationUrl, destFolder.Url, fi.Name);
               SPFile newFile = destFolder.Files.Add(relativeDestinationUrl, filebytes, true);
               SPListItem newItem = newFile.Item;
               CopyFieldValues(item, newItem);
               newItem.UpdateOverwriteVersion();
            }
            else
            {
               relativeDestinationUrl = string.Format(relativeDestinationUrl, destFolder.Url, item.Folder.Name);
               SPFolder destSubFolder = destFolder.SubFolders.Add(relativeDestinationUrl);
               SPFolder sourceSubFolder = item.Folder;
               // copy everything in sub folder
               CopyDocumentLibraryItems(sourceSubFolder, destSubFolder);
            }
         }
      }

Technorati Tags:
Posted on Sunday, March 15, 2009 8:14 AM | Back to top


Comments on this post: Part 2: Copy a SharePoint List Programmatically

# re: Part 2: Copy a SharePoint List Programmatically
Requesting Gravatar...
Where is part 1?????

Please provide the Url of that... :)
Left by ssss on May 14, 2009 7:19 PM

# re: Part 2: Copy a SharePoint List Programmatically
Requesting Gravatar...
Hallo Anne,

Iám trying to sync Pages from one farm server to other farm server. Do you have source code how to sync page library from one server to other.

Please help.

Kind regards,

Dejan Dujak
Left by Dejan Dujak on Jun 04, 2009 2:18 AM

# re: Part 2: Copy a SharePoint List Programmatically
Requesting Gravatar...
@Dejan Dujak
you should call sharepoint's webservices:
http://msdn.microsoft.com/en-us/library/copy.aspx
Left by myro on Sep 01, 2009 12:50 AM

# re: Part 2: Copy a SharePoint List Programmatically
Requesting Gravatar...
When I did something very similar, I found that the CreatedBy, ModifiedBy, TimeCreated, and TimeLastModified fields of the new document were overwritten with the current user and current time. Using the overloaded function Files.Add(url, byte[], SpUser createdBy, SPUser modifiedBy, DateTime timeCreated, DateTime timlastModified) correctly set TimeCreated and TimeLastModified, but the two user fields were ignored, so I added this after Files.Add():

SPListItem NewItem = NewFile.Item;
NewItem["Created"] = SrcItem.File.TimeCreated.ToLocalTime();
NewItem["Modified"] = SrcItem.File.TimeLastModified.ToLocalTime();
NewItem.Update();

The call to Files.Add() will throw an exception if the user represented by either createdBy or lastModifiedBy no longer exists. You can see my solution at http://vspug.com/cwogle/2010/01/07/copying-a-newlyweds-sharepoint-document/
Left by Chris on Jan 25, 2010 4:17 AM

# re: Part 2: Copy a SharePoint List Programmatically
Requesting Gravatar...
Hi,
I want to sync data between two web site in different web server.
Do you have source code how to sync Document library from one server to other.

Please help me out

Thanks
Tanaji Chavan
Left by TAnaji Chavan on Apr 05, 2010 11:28 PM

# re: Part 2: Copy a SharePoint List Programmatically
Requesting Gravatar...
Very nice article... Where is part1 please? :)
Left by Rias on May 11, 2010 9:17 PM

# re: Part 2: Copy a SharePoint List Programmatically
Requesting Gravatar...
Here is first part :

http://geekswithblogs.net/AnneBougie/archive/2009/01/23/copy-a-sharepoint-list.aspx
Left by Gaurav on Aug 11, 2014 10:13 PM

# re: Part 2: Copy a SharePoint List Programmatically
Requesting Gravatar...
nice post.....thanks for sharing
http://www.allformtemplates.com/annotated-bibliography-examples-formatstemplates/
Left by sambhav on Jul 13, 2017 6:28 PM

Your comment:
 (will show your gravatar)


Copyright © Annie Bougie | Powered by: GeeksWithBlogs.net