zoukankan      html  css  js  c++  java
  • 复制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

  • 相关阅读:
    七牛云上传文件
    微博三方登录
    异步任务 --- django-celery
    阿里云短信服务
    Redis五大数据结构和使用方法
    千万不要买我们家的鞋子!
    Firebug控制台详解
    【转】android 按home键返回到桌面后,再按桌面应用图标又重新打开该应用的解决方法
    【转】android中webview使用的一些细节
    JSONException: Value of type java.lang.String cannot be converted to JSONObject
  • 原文地址:https://www.cnblogs.com/Sunmoonfire/p/1791424.html
Copyright © 2011-2022 走看看