Link to home
Start Free TrialLog in
Avatar of prakashacharya
prakashacharya

asked on

SharePoint 2013 Event Receiver: Copy list items

3 lists: A, B, C
As soon as item is added in list A, i would like to copy items from list B to C.
User generated image
Avatar of prakashacharya
prakashacharya

ASKER

please help
Avatar of Jamie McAllister
Your screenshot looks like either SharePoint 2013 or Office 365? Which is it?

Assuming you have an on-premises install of SharePoint 2013 and can install full trust solutions your event receiver shouldn't be too difficult. There are links on how to create an event receiver and some advice for the sort of task you're doing here;

https://social.technet.microsoft.com/Forums/en-US/ebecdc48-e163-4200-b63c-7d3746f5b139/copy-list-items-from-parent-site-to-my-subsite-using-event-receiver-in-sharepoint-2010

It should also be possible to do this with a no-code solution i.e a workflow. A bit of guidance here;

http://sharepoint.stackexchange.com/questions/93441/move-items-from-one-list-to-another-list-using-sharepoint-designer-2010
Screen shot is from SharePoint 2013 on-prem.
Then you're good to go. Have a look at the link detailing writing event receivers. Let me know if anything needs clarification.
I looked at the article. I am able to copy from Master to Checklist while running event receiver from Master. But, how do I copy from Master to Checklist when event viewer is triggered from NewHire?

targetItem["Title"] = properties.ListItem.Name; // This is going to copy title from the list where ER is ran
Can you please share a sample code if possible?
Totally thrown together example below. I haven't had time to write this properly or even compile it, but it should put you on the right track. Make sure you make lots of improvements though, this code sucks.

In event receiver, use properties of existing item to determine SubOrg value

string subOrgValue = properties.BeforeProperties["SubOrg"].ToString()

Open in new window



Execute a CAML query against the Master list to return the IDs of the items with that SubOrg

Iterate through the IDs to move them to checklist


using (SPSite site = new SPSite("MasterListURL"))
        {
            using (SPWeb web = site.OpenWeb("MasterListURL"))
            {
                SPList masterList = web.Lists["MasterList"];

                try
                {
                    var query = new SPQuery();
                    query.Query = "<Where><Eq><FieldRef Name='SubOrg' /><Value Type='Text'>" + subOrgValue +
                                              "</Value></Eq></Where><ViewFields><FieldRef Name='ID' /></ViewFields>";

                    SPListItemCollection col = masterList.GetItems(query);
                    if (col.Count > 0)
                    {
                        //Create List items in checkList
                        foreach (SPListItem item in col)
                        {
                            masterList.GetItemById(int.Parse(item["ID"].ToString())).CopyTo("checkListUrl");
                            masterList.GetItemById(int.Parse(item["ID"].ToString())).Delete();
                        }
                    }
                }
                catch (System.Exception)
                { }
            }
        }

                

Open in new window

using System;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;

namespace HRChecklist.HRChecklist
{
    /// <summary>
    /// List Item Events
    /// </summary>
    public class HRChecklist : SPItemEventReceiver
    {
        /// <summary>
        /// An item was added.
        /// </summary>
        public override void ItemAdded(SPItemEventProperties properties)
        {
            base.ItemAdded(properties);
            string subOrgValue = properties.BeforeProperties["SubOrg"].ToString();
            //string subOrgValue = properties.BeforeProperties["SubOrg"].ToString()
            //string subOrgValue = properties.BeforeProperties["SubOrg"].ToString()
            using (SPSite site = new SPSite("http://win-egv4m91iu0v/Lists/Master"))
            {
                using (SPWeb web = site.OpenWeb("http://win-egv4m91iu0v/Lists/Master"))
                {
                    SPList masterList = web.Lists["Master"];

                    try
                    {
                        var query = new SPQuery();
                        query.Query = "<Where><Eq><FieldRef Name='SubOrg' /><Value Type='Text'>" + subOrgValue +
                                                  "</Value></Eq></Where><ViewFields><FieldRef Name='ID' /></ViewFields>";

                        SPListItemCollection col = masterList.GetItems(query);
                        if (col.Count > 0)
                        {
                            //Create List items in checkList
                            foreach (SPListItem item in col)
                            {
                                masterList.GetItemById(int.Parse(item["ID"].ToString())).CopyTo("http://win-egv4m91iu0v/Lists/Checklist");
                                masterList.GetItemById(int.Parse(item["ID"].ToString())).Delete();
                            }
                        }
                    }
                    catch (System.Exception)
                    { }
                }
            }

                
        }


    }
}

Open in new window


<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Receivers ListUrl="Lists/NewHire">
      <Receiver>
        <Name>HRChecklistItemAdded</Name>
        <Type>ItemAdded</Type>
        <Assembly>$SharePoint.Project.AssemblyFullName$</Assembly>
        <Class>HRChecklist.HRChecklist.HRChecklist</Class>
        <SequenceNumber>10000</SequenceNumber>
      </Receiver>
  </Receivers>
</Elements>

Open in new window

Am I doing something wrong there?
It looks ostensibly correct, though like I said my code is a hack and can be improved (even more than you have).

I'm not sure you can use BeforeProperties in an ItemAdded as it's new and doesn't have a before. Try AfterProperties there.

Also it may complain about making modifications in the ForEach to the SPListItemCollection items. Might have to copy the IDs out of the foreach and then execute the moves.

Compiles OK? How's it behaving in your dev environment?
very close :) got this error.
User generated image
Strange error for that line.

Does that string match the list title?

Another thing to try would be list guid. You can get that from the url in the list settings page.
Thanks for your great help. I am able to copy. Last thing that I would like to do is in Checklist Task, there is a column called "Related Items". I would like to add the item from NewHire to that column.

using System;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;

namespace HR101.HR101
{
    /// <summary>
    /// List Item Events
    /// </summary>
    public class HR101 : SPItemEventReceiver
    {
        /// <summary>
        /// An item was added.
        /// </summary>
        public override void ItemAdded(SPItemEventProperties properties)
        {
            try
            {
                //base.ItemAdded(properties);
                string subOrgValue = properties.AfterProperties["SubOrg"].ToString();
                SPSite mySourceSite = new SPSite("http://win-egv4m91iu0v/");
                SPWeb mySourceWeb = mySourceSite.OpenWeb();
                SPList mySourceList = mySourceWeb.Lists["Master"];
                var query = new SPQuery();
                query.Query = "<Where><Eq><FieldRef Name='SubOrg' /><Value Type='Text'>" + subOrgValue +
                                          "</Value></Eq></Where><ViewFields><FieldRef Name='ID' /></ViewFields>";

                SPListItemCollection col = mySourceList.GetItems(query);
                if (col.Count > 0)
                {
                    foreach (SPListItem mySourceListItem in col)
                    {
                        string SourceTaskName = mySourceListItem["Task Name"].ToString();
                        SPSite myDestinationSite = new SPSite("http://win-egv4m91iu0v");
                        SPWeb myDestinationWeb = myDestinationSite.OpenWeb();
                        SPList myDestinationList = myDestinationWeb.Lists["Checklist"];
                        SPListItem myDestinationListItem = myDestinationList.Items.Add();

                        myDestinationListItem["Task Name"] = SourceTaskName;
                        myDestinationWeb.AllowUnsafeUpdates = true;
                        myDestinationListItem.Update();
                        myDestinationWeb.AllowUnsafeUpdates = false;

                    }
                }
            }
            catch (System.Exception)
            { }

        }


    }
}

Open in new window

Related items field is a funny one.

There's a JSOM code sample here, which can easily be converted to C#

http://blogs.msdn.com/b/mbakirov/archive/2015/03/22/10601913.aspx
need you help. please
Please have a crack at it, and I can assist if necessary. I'm at a very busy stage on a project.
ASKER CERTIFIED SOLUTION
Avatar of Jamie McAllister
Jamie McAllister
Flag of Switzerland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Here is what I did:
 int id = properties.ListItemId;
                
//Get Webid and Listid from powershell
                //string itemurl = properties.ListItem.Url;
                //string listid = "9D9871AF-E7DD-421C-B59B-1F10B1B3224A";
                //string webid = "b18b2ce6-9907-4be8-8c99-7987f9724467";

Open in new window


myDestinationListItem["Related Items"] = "[{\"ItemId\":"+id+",\"WebId\":\"b18b2ce6-9907-4be8-8c99-7987f9724467\",\"ListId\":\"9D9871AF-E7DD-421C-B59B-1F10B1B3224A\"}]";

Open in new window


Its all working now.

Thank you Jamie for your great help.
Well done prakashacharya! I'm really glad you got a resolution.
@ Jamie,

the solution is working perfectly fine. But just curious, whether i am doing it in wrong way and creating a lot of memory overload. I am not sure. but can you please help me find out if i am doing not in a good way. i am curious about memory leak or not disposing objects or closing connection. Below is my code.

using System;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;

namespace HR101.HR101
{
    /// <summary>
    /// List Item Events
    /// </summary>
    public class HR101 : SPItemEventReceiver
    {
        /// <summary>
        /// An item was added.
        /// </summary>
        public override void ItemAdded(SPItemEventProperties properties)
        {
            try
            {
                SPFieldLookup SiteValue = properties.ListItem.Fields["Site"] as SPFieldLookup;
                SPFieldLookupValue taskIdVal2 = null;
                object obj2 = properties.ListItem["Site"];
                if (SiteValue != null)
                    taskIdVal2 = SiteValue.GetFieldValue(obj2.ToString()) as SPFieldLookupValue;
                string site = taskIdVal2.LookupValue;

                SPFieldLookup OrganizationValue = properties.ListItem.Fields["Organization"] as SPFieldLookup;
                SPFieldLookupValue taskIdVal1 = null;
                object obj1 = properties.ListItem["Organization"];
                if (OrganizationValue != null)
                    taskIdVal1 = OrganizationValue.GetFieldValue(obj1.ToString()) as SPFieldLookupValue;
                string Organization = taskIdVal1.LookupValue;

                SPFieldLookup SubOrganizationValue = properties.ListItem.Fields["Sub Organization"] as SPFieldLookup;
                SPFieldLookupValue taskIdVal3 = null;
                object obj3 = properties.ListItem["Sub Organization"];
                if (SubOrganizationValue != null)
                    taskIdVal3 = SubOrganizationValue.GetFieldValue(obj3.ToString()) as SPFieldLookupValue;
                string SubOrganization = taskIdVal3.LookupValue;                              

                int id = properties.ListItemId;

                SPSite mySourceSite = new SPSite("http://win-egv4m91iu0v/");
                SPWeb mySourceWeb = mySourceSite.OpenWeb();
                SPList mySourceList = mySourceWeb.Lists["Master"];

                var query = new SPQuery();
                query.Query = "<Where><And><Eq><FieldRef Name='Site' /><Value Type='Lookup'>" + site + "</Value></Eq><And><Eq><FieldRef Name='Organization' /><Value Type='Lookup'>" + Organization + "</Value></Eq><Eq><FieldRef Name='Sub_x0020_Organization' /><Value Type='Lookup'>" + SubOrganization + "</Value></Eq></And></And></Where>";
                SPListItemCollection col = mySourceList.GetItems(query);
                if (col.Count > 0)
                {
                    foreach (SPListItem mySourceListItem in col)
                    {
                        SPFieldLookupValue cat = new SPFieldLookupValue(mySourceListItem["Category"].ToString());
                        int lookedUpItemID = cat.LookupId;
                        string Category = cat.LookupValue;
                        string SourceTaskName = mySourceListItem["Title"].ToString();
                        string reportsTo = mySourceListItem["Assigned To"].ToString();
                        int days = Int32.Parse(mySourceListItem["Task Duration"].ToString());
                        DateTime dt = DateTime.Now;
                        dt = dt.AddDays(days);
                        SPSite myDestinationSite = new SPSite("http://win-egv4m91iu0v");
                        SPWeb myDestinationWeb = myDestinationSite.OpenWeb();
                        SPList myDestinationList = myDestinationWeb.Lists["Checklist"];
                        SPListItem myDestinationListItem = myDestinationList.Items.Add();
                        string desc="";
                        if (mySourceListItem["Description"] != null)
                        {
                            desc=mySourceListItem["Description"].ToString();
                        }
                        myDestinationListItem["Description"] = desc;
                        myDestinationListItem["Task Name"] = SourceTaskName;
                        myDestinationListItem["Related Items"] = "[{\"ItemId\":"+id+",\"WebId\":\"b18b7ce6-9907-4be8-8c99-7987f9724467\",\"ListId\":\"9D9871AF-E7DD-421C-B59B-1F10B1B3224A\"}]";
                        myDestinationListItem["Site"] =site;
                        myDestinationListItem["Organization"] =Organization;
                        myDestinationListItem["Sub Organization"] = SubOrganization;
                        myDestinationListItem["Assigned To"] = reportsTo;
                        myDestinationListItem["Category"] = Category;
                        myDestinationListItem["Due Date"] = dt;
                        if (mySourceListItem.Attachments.Count > 0)
                        {
                            foreach (string attachmentName in mySourceListItem.Attachments)
                            {
                                SPFile file = mySourceListItem.ParentList.ParentWeb.GetFile(mySourceListItem.Attachments.UrlPrefix + attachmentName);
                                byte[] data = file.OpenBinary();
                                myDestinationListItem.Attachments.Add(attachmentName, data);
                            }
                            myDestinationListItem.Update();                            
                        }         
                        myDestinationWeb.AllowUnsafeUpdates = true;
                        myDestinationListItem.Update();
                        myDestinationWeb.AllowUnsafeUpdates = false;

                    }
                }
            }
            catch (System.Exception)
            { }
            finally
            {
                 
            }

        }


    }
}

Open in new window

Hi prakashacharya,

Yes, there's an issue in the instantiation of SPSite and SPWeb objects. They're at risk of not being disposed and causing memory leaks. Do it this way and they will be disposed of reliably;

using(SPSite oSPsite = new SPSite("http://server"))
{
  using(SPWeb oSPWeb = oSPSite.OpenWeb())
   {
       str = oSPWeb.Title;
       str = oSPWeb.Url;
   }
}  

Open in new window