复制SharePoint列表项(SPListItem)到另一个列表

 

从理论上讲,有一个简单到难以置信的解决办法:SPListItem提供了一个CopyTo(destinationUrl)方法(可参考MSDN)。不幸的是,这个方法似乎用不了。至少对我的情况(一个带附件的自定义列表)是如此。总是告诉我找不到源列表项,没有读取权限,或者列表没有发布等等。从网上找到很多帖子,其他人也遇到同样的问题。最好的解决方案就是自己实现。

首先设计方法的参数和返回值类型:

public static SPListItem CopyItem(SPListItem sourceItem,string destinationListName)

内容部分首先是创建目标列表项。然后把源列表项的字段复制到目标项。

//复制sourceItem到destinationList

SPList destinationList=sourceItem.Web.Lists(destinationListName);

SPListItem targetItem=destinationList.Items.Add();

foreach(SPField f in sourceItem.Fields)

{

    if(!f.ReadOnlyField && f.InternalName!="Attachments")

    {

         targentItem[f.InternalName]=sourceItem[f.InternalName];

     }

}

代码中跳过了只读字段和附件。对于附件我们这样处理:

//复制附件

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);

}

接下来只需提交目标项至数据库并返回即可。

//保存targetItem

targetItem.Update();

return targetItem;

对该方法的调用方法大致如下:

SPListItem approvedItem=CommonFunctions.CopyItem(item,"目标列表名");

为了方便Copy,下面列出完整的代码:

public static SPListItem CopyItem(SPListItem sourceItem, string destinationListName)

{

    //复制 sourceItem 到 destinationList

    SPList destinationList = sourceItem.Web.Lists[destinationListName];

    SPListItem targetItem = destinationList.Items.Add();

    foreach (SPField f in sourceItem.Fields)

    {

          if (!f.ReadOnlyField && f.InternalName != “Attachments”)

         {

               targetItem[f.InternalName] = sourceItem[f.InternalName];

         }

     }

     //复制附件

     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);

      }

      targetItem.Update();

      return targetItem;

} 

对于需要进一步对目标项进行跟踪的情况而言。默认SharePoint的SPListItem带有一个_CopySource字段,并且还有一个对应的CopySource属性。应该是与CopyTo方法配合用的。同样不幸的是都是只读的。没法为我所用。基于这个原因Muhimbi的做法是在目标列表上新建一个自己的字段——_M_CopySource,来实现类似的功能:

SPList sourceList = MyWorkflow.List;

SPList destinationList = MyWorkflow.Web.Lists[MyWorkflow.Parameter1 as String];

SPListItem sourceItem = MyWorkflow.Item;

 

// 首先检查自定义的来源字段在目标列表中是否存在

if (destinationList.Fields.ContainsField("_M_CopySource") == false)

{

      SPField newField = destinationList.Fields.CreateNewField("Text", "_M_CopySource");

      newField.Hidden = true;

      destinationList.Fields.Add(newField);

}

 

// 检查是否存在需要更新的列表项

string camlQuery = "<Where>" +

                   "<Eq><FieldRef Name='_M_CopySource'/><Value Type='Text'>{0}</Value></Eq>" +

                   "</Where>";

camlQuery = string.Format(camlQuery, sourceItem["FileRef"]);

SPQuery query = new SPQuery();

query.Query = camlQuery;

query.RowLimit = 1;

 

// 查询列表

SPListItemCollection items = destinationList.GetItems(query);

SPListItem newItem = null;

if (items.Count == 0)

    newItem = destinationList.Items.Add();

else

    newItem = items[0];

 

// 复制字段

foreach(SPField field in sourceItem.Fields)

{

    if (newItem.Fields.ContainsField(field.InternalName) == true && 

        field.ReadOnlyField == false && field.InternalName != "Attachments")

    {

       newItem[field.InternalName] = sourceItem[field.InternalName];

    }

}

 

// 删除目标项上已有的附件

for (int i = newItem.Attachments.Count; i > 0; i-- )

{

    newItem.Attachments.Delete(newItem.Attachments[i-1]);

}

 

// 复制所有的附件

foreach (string fileName in sourceItem.Attachments)

{

    SPFile file = sourceItem.ParentList.ParentWeb.GetFile(sourceItem.Attachments.UrlPrefix + 

                                                          fileName);

    byte[] imageData = file.OpenBinary();

    newItem.Attachments.Add(fileName, imageData);

}

 

// 在目标项上记下复制的来源,以便将来对其进行更新

newItem["_M_CopySource"] = sourceItem["FileRef"]; 

newItem.Update();

他是把这段代码用在自定义工作流活动中。实现列表项的单向同步更新。如果在查询中添加上我们自己的条件,就可以实现满足特定条件的更新。确实很有用。

 

参考资料

SharePoint Listenelement (SPListItem) in eine andere Liste kopieren

Synchronise SharePoint Lists (Calendar/Tasks) using the Workflow Power Pack

How to copy SPListItem from one SPList to Another SPList

 

你可能感兴趣的:(SharePoint)