复制SharePoint列表项(SPListItem)到另一个列表
从理论上讲,有一个简单到难以置信的解决办法: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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步