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

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

1
public static SPListItem CopyItem(SPListItem sourceItem,string destinationListName)

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

1
2
3
4
5
6
7
8
9
10
//复制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];
     }
}

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

1
2
3
4
5
6
7
8
//复制附件
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);
}

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

1
2
3
//保存targetItem
targetItem.Update();
return targetItem;

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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,来实现类似的功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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列表项(SPListItem)到另一个列表的更多相关文章

  1. MFC CListCtrl 将一个列表的选中项添加到另一个列表

    MFC CListCtrl 将一个列表的选中项添加到另一个列表, 用VC6.0实现: 简单记录一下自己的学习历程, 和大家分享,如果对你有用,我很高兴. 1.新建一个基于对话框的工程(Dialog-B ...

  2. Flutter 实战(一):列表项内容可自定义的列表组件

    前言 本篇文的目的是熟练掌握 Flutter 组件的封装,并且使用回调函数实现主要功能. 本组件的设计灵感来源于 Element 组件库的 table 组件. 正题 定义回调函数 在此之前,必须要了解 ...

  3. Python3基础 把一个列表中内容给另外一个列表,形成两个独立的列表

    镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...

  4. 从0开始学FreeRTOS-(列表与列表项)-3

    # FreeRTOS列表&列表项的源码解读     第一次看列表与列表项的时候,感觉很像是链表,虽然我自己的链表也不太会,但是就是感觉很像. 在`FreeRTOS`中,列表与列表项使用得非常多 ...

  5. 从0开始学FreeRTOS-(列表&列表项)-6

    # FreeRTOS列表&列表项的源码解读 第一次看列表与列表项的时候,感觉很像是链表,虽然我自己的链表也不太会,但是就是感觉很像. 在FreeRTOS中,列表与列表项使用得非常多,是Free ...

  6. SharePoint REST API - 列表和列表项

    博客地址:http://blog.csdn.net/FoxDave 本篇主要讲述如何用SharePoint REST操作列表和列表项.阅读本篇时请先了解前面讲述的REST介绍和基本操作. 废话不多 ...

  7. SharePoint 2010 列表项事件接收器 ItemAdded 的使用方法

    列表项事件处理器是继承于Microsoft.SharePoint.SPItemEventReceiver的类,Microsoft.SharePoint.SPItemEventReceiver类提供了许 ...

  8. WPF中反转3D列表项

    原文:WPF中反转3D列表项 WPF中反转3D列表项                                                         周银辉记得在苹果电脑中有一个很酷的 ...

  9. IE问题——列表项图像

    等我们实现列表时,经常会遇到一种情况:需要为列表的每一项的前面添加一个列表项图像. 我们在查阅W3C时会发现,在CSS中已经为我们提供了实现方法——“list-style-type”,我们来看看它的实 ...

随机推荐

  1. 在.htaccess文件中写RewriteRule无效的问题的解决

    近来在Apache Rewrite 拟静态配置时,遇到个问题.写的如下: RewriteEngine onRewriteRule ^/t_(.*)/$ /test.php?id=$1 保存在httpd ...

  2. Android WebView的Js对象注入漏洞解决方案

    http://blog.csdn.net/leehong2005/article/details/11808557/ webview调用以下文件,就可以打印sdcard 文件名 <!DOCTYP ...

  3. Python-0 简述

    #1 应用广泛: 豆瓣 youtube 云存储相关 #2 初步学习内容:

  4. 关于python中文件导入的若干问题

    __init__文件 同一级目录下直接import导入就可以了,如果是在不同的目录下面被导入文件的文件夹下面必须有__init__.py文件,即使这个文件是空的也可以.当然这个文件也可以初始一些数据 ...

  5. gulp使用笔记

    gulp简介 gulp 是基于 Nodejs 的自动任务运行器,能自动化地完成javascript/coffee/sass/less/html/image/css等文件的的测试.检查.合并.压缩.格式 ...

  6. webstorm编辑RN代码提示功能

    需要下载一个文件. 1. 进入你想存储这个文件的目录,按住shift+鼠标右键,选择“在此处打开命令窗口” 2. 在命令窗口中输入  git clone https://github.com/virt ...

  7. linux查看负载

    LINUX下查看负载 1,查看磁盘 df -h 2,查看内存大小 free free [-m|g]按MB,GB显示内存 vmstat 3,查看cpu cat /proc/cpuinfo 只看cpu数量 ...

  8. nginx相关的一些记录

    http redirect to https: if ($http_cf_visitor ~ '"scheme":"http"'){ rewrite ^/(.* ...

  9. android开发--okhttp

    一.okhttp简单实用: 一般的get请求 一般的post请求 基于Http的文件上传 文件下载 加载图片 支持请求回调,直接返回对象.对象集合 支持session的保持 二.实用教程 1.添加an ...

  10. Ninject之旅之九:Ninject上下文绑定(附程序下载)

    摘要 既然在插件模型里,每一个服务类型可以被映射到多个实现,绑定方法不用决定要返回哪个实现.因为kernel应该返回所有的实现.然而,上下文绑定是多个绑定场景,在这个场景里,kernel需要根据给定的 ...