在SharePoint中将列表项从一个列表复制到另一个列表

16
在Sharepoint中如何将列表项从一个列表复制到另一个列表?例如从“List A”复制到“List B”(两者都在站点根目录下)。
我希望在向“List A”添加新列表项时进行复制。
我尝试在ItemAdded事件接收器中使用SPListItem的CopyTo()方法,但无法弄清要复制到哪个URL。

请参见https://dev59.com/nVLTa4cB1Zd3GeqPd9nx。 - SteveC
11个回答

18

这是我使用的代码。将SPlistItem和目标列表的名称作为Sharepoint中可见的名称(而不是URL)传递给它。唯一的限制是两个列表必须在同一个站点中:

private SPListItem CopyItem(SPListItem sourceItem, string destinationListName) {
        //Copy sourceItem to destinationList
        SPList destinationList = sourceItem.Web.Lists[destinationListName];
        SPListItem targetItem = destinationList.Items.Add();
        foreach (SPField f in sourceItem.Fields) {
            //Copy all except attachments.
            if (!f.ReadOnlyField && f.InternalName != "Attachments"
                && null != sourceItem[f.InternalName])
            {
                targetItem[f.InternalName] = sourceItem[f.InternalName];
            }
        }
        //Copy attachments
        foreach (string fileName in sourceItem.Attachments) {
            SPFile file = sourceItem.ParentList.ParentWeb.GetFile(sourceItem.Attachments.UrlPrefix + fileName);
            byte[] imageData = file.OpenBinary();
            targetItem.Attachments.Add(fileName, imageData);
        }

        return targetItem;
    }

1
那么物品版本呢? - Ievgen
@Sylvain Perron - 这个解决方案对我很有用。但是如何复制源项目的元内容,例如创建时间、修改时间等? - Joseph Jojo John

5

正如Lars所说,移动项目并保留版本和正确的用户信息可能有些棘手。我以前也做过类似的事情,如果您需要一些代码示例,请通过评论告诉我,我可以为您提供一些指导。

CopyTo方法(如果您决定使用该方法)需要一个绝对Uri,例如:http://host/site/web/list/filename.doc

因此,如果您在事件接收器中执行此操作,则需要连接包含所需元素的字符串。类似以下内容(请注意,还可以通过其他方式完成):

string dest= 
 siteCollection.Url + "/" + site.Name + list.Name + item.File.Name;

1
+1 for CopyTo。@raklos 和你的问题一样 https://dev59.com/xHNA5IYBdhLWcg3wL6sc - Alex Angas
我从未能够使 CopyTo 在普通列表项中工作。它可以用于文档库,但不能用于博客文章、任务等列表。 - Daniel
这很棒。但有没有办法将该文档作为列表附件?我想将一个列表项的附件复制到另一个列表项中,这可行吗? - Mihir

1

请确保在SPFile上调用CopyTo(url)方法,而不是在SPListItem上调用。 例如:

ItemUpdated(SPItemEventProperties properties)
{ 
  //...
  string url = properties.Web.Site.Url + "/" + properties.Web.Name + "Lists/ListName/" + properties.ListItem.File.Name;
  //properties.ListItem.File.MoveTo(url);
  properties.ListItem.File.CopyTo(url);
  //...
}

1
private void CopyAttachmentsToList(SPListItem srcItem, SPListItem tgtItem)
{
    try
    {
        //get source item attachments from the folder
        SPFolder srcAttachmentsFolder =
            srcItem.Web.Folders["Lists"].SubFolders[srcItem.ParentList.Title].SubFolders["Attachments"].SubFolders[srcItem.ID.ToString()];

        //Add items to the target item
        foreach (SPFile file in srcAttachmentsFolder.Files)
        {
            byte[] binFile = file.OpenBinary();
            tgtItem.Update();
            tgtItem.Attachments.AddNow(file.Name, binFile);
            tgtItem.Update();
        }
    }
    catch
    {
        //exception message goes here
    }
    finally
    {
        srcItem.Web.Dispose();
    }
}

不要忘记添加这一行代码,tgtItem.Update();,否则会出现错误。

1

1
在SharePoint中复制和移动文件、项目和文件夹可能会很棘手,如果您想保留所有元数据、时间戳、作者信息和版本历史记录。看一下CopyMove for SharePoint - 它还有一个Web服务API。

有趣的是,我现在面临这样一种情况,需要编写一个移动服务来克服SharePoint中CopyMove的限制;)多么具有讽刺意味。 - user220583

1
这是一个 PowerShell 版本的 Sylvian 的等效版本,它允许跨站点复制。他的代码也可以类似地进行修改...
param([string]$sourceWebUrl, [string]$sourceListName, [string]$destWebUrl, [string]$destListName)

$sourceWeb = get-spweb $sourceWebUrl;
$sourceList = $sourceWeb.Lists[$sourceListName];
$destWeb = get-spweb $destWebUrl;
$destList = $destWeb.Lists[$destListName];
$sourceList.Items |%{
$destItem = $destList.Items.Add();
$sourceItem = $_;
$sourceItem.Fields |%{
    $f = $_;
    if($f.ReadOnlyField -eq $false -and $f.InternalName -ne "Attachments" -and $sourceItem[$f.InternalName] -ne $null){
        $destItem[$f.InternalName] = $sourceItem[$f.InternalName];
    }
}
$destItem.Update();
}

使用时,复制并粘贴到一个文件 copy-listitems.ps1 中,并使用Sharepoint PowerShell命令行运行...


0

使用C#服务器端代码将一个SharePoint列表或库中的列表项复制到另一个SharePoint列表或库中

//Itecollection是来自源列表的数据集合

 public void CopyItemsFromOneListToAnotherList(SPListItemCollection itemCollection)
 {  
 using (SPSite site = new SPSite(siteUrl))
 {
  using (SPWeb web = site.OpenWeb())
  {
     //Get destination list/library
     //destListName - Destination list/library name
   SPList destList = web.Lists.TryGetList(destListName);

   foreach (SPListItem sourceItem in itemCollection)
   {
    //Add new Item to list
    SPListItem destItem = destList.Items.Add();

    foreach (SPField field in sourceItem.Fields)
    {
     if (!field.ReadOnlyField && !field.Hidden && field.InternalName != "Attachments")
     {
      if (destItem.Fields.ContainsField(field.InternalName))
      {
       //Copy item to  destination library
         destItem[field.InternalName] = sourceItem[field.InternalName];
      }
     }
    }
    //Update item in destination  library or list
    destItem.Update();
    Console.WriteLine("Copied " + sourceItem["ID"] + "to destination list/library");
   }
  }
 }

 }

0
如何复制字段并保存版本:
public static SPListItem CopyItem(SPListItem sourceItem, SPList destinationList)
            {
                SPListItem targetItem = destinationList.AddItem();

                //loop over the soureitem, restore it
                for (int i = sourceItem.Versions.Count - 1; i >= 0; i--)
                {
                    //set the values into the archive 
                    foreach (SPField sourceField in sourceItem.Fields)
                    {
                        SPListItemVersion version = sourceItem.Versions[i];

                        if ((!sourceField.ReadOnlyField) && (sourceField.InternalName != "Attachments"))
                        {
                            SetFields(targetItem, sourceField, version);
                        }
                    }

                    //update the archive item and 
                    //loop over the the next version
                    targetItem.Update();
                }

                foreach (string fileName in sourceItem.Attachments)
                {
                    SPFile file = sourceItem.ParentList.ParentWeb.GetFile(sourceItem.Attachments.UrlPrefix + fileName);
                    targetItem.Attachments.Add(fileName, file.OpenBinary());
                }

                targetItem.SystemUpdate();
                return targetItem;
            }

            private static bool SetFields(SPListItem targetItem, SPField sourceField, SPListItemVersion version)
            {
                try
                {
                    targetItem[sourceField.InternalName] = version.ListItem[sourceField.InternalName];
                    return true;
                }
                catch (System.ArgumentException)//field not filled
                {
                    return false;
                }
                catch (SPException)//field not filled
                {
                    return false;
                }
            }

0

所以,这些列表具有完全相同或类似的列吗?无论哪种方式,您都可以创建一个简单的工作流,在“列表A”中创建项目时自动运行。由于所涉及的工作流相对简单,我建议使用免费的SharePoint Designer来创建它,因为您可以轻松地将两个列表的列匹配起来。下面的步骤应该能帮助您入门。

创建工作流 - SharePoint Designer


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接