从理论上讲,有一个简单到难以置信的解决办法: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. 数据挖掘之KNN算法(C#实现)

    在十大经典数据挖掘算法中,KNN算法算得上是最为简单的一种.该算法是一种惰性学习法(lazy learner),与决策树.朴素贝叶斯这些急切学习法(eager learner)有所区别.惰性学习法仅仅 ...

  2. php 构造函数格式,具体该怎么写?应该注意什么呢?

    在PHP里,如果你没有手写构造函数,则php在实例化这个对象的时候,会自动为类成员以及类方法进行初始化,分配内存等工作,但是有些时候不能满足我们的要求,比如我们要在对象实例化的时候传递参数,那么就需要 ...

  3. Request.ServerVariables

    APPL_MD_PATH-->APPL_PHYSICAL_PATH-->C:\Users\TomZhang\Desktop\GAP\后台修改\UMS\UMSSite\AUTH_TYPE-- ...

  4. Windows下python virtualenv使用,镜像源设置,批量安装,安装scipy,numpy

    镜像源设置 在C:\Users\Administrator\下建立pip文件夹,然后在里面创建了一个pip.ini 内容为: [global]index-url = https://pypi.tuna ...

  5. 【转载】Understand the serialVersionUID

    If you have ever implemented Serializable interface, you must encounter this warning message The ser ...

  6. xampp3.2下mysql中文乱码终极解决方案

    xmapp3.2.2中mysql已经被替换成了Mariadb,网上那些显示char语句已经失灵. 另外本文主要介绍的是手动在mysql中写入中文乱码问题 那么我们将采用如下三个步骤解决乱码问题 1.打 ...

  7. mysqldump的使用

    mysqldump按导入:mysqldump -u用户名 -p密码 -h主机 数据库 < 路径eg:mysql -uroot -p1234 db1 < c:\a.txtmysqldump导 ...

  8. Jsoup使用随记

    这段时间工作比较空闲,在网上找资料学习的时候看到数据抓取这一块,来了兴趣 用jsoup实现数据抓取着实方便,唯一美中不足的是官方API是英文版的,对我这样英语水平不好的程序员来说着实困扰,只能一点点的 ...

  9. 大冰--寻人启事--one

    看得懂的,都不是命运,说得清的,都不叫爱情. 忘得了的,都不是遗憾,听得见的,都不是伤心. 躲的开的,都不是缘分,猜得透的,都不叫人生.

  10. jQuery-表单流程导航

    前言:以前做过一个项目,里面牵涉到流程相关的业务,需要用到流程页面导航的效果,完整的工作流相关的项目以前也做过,需要用到第三方插件,当然这里记录的业务需求没这个麻烦,仅仅需要能有一个页面导航的标题栏, ...