Tuesday, March 6, 2012

How to: Copy File Attachment from Custom List To Document Library


In the article, I want to write event receiver when custom list is Candidate and Client (option in code) which list item created with file attach or item updated attachment file, so on document list “HumanCapitalDocument” will copy automatic.

Download Example and List Template then base on list template create


Custom list with name is: Candidate and Client
Document Library name is: HumanCapitalDocument

Open Visual studio 2010 | New Project | Empty Sharepoint Project | name is EventReceiverCopyFile

Choose “deploy as a farm solution”
Create Event Receiver: you can reference at here
Right click Project | Add new item | Event Receiver template | name is CopyAttachFileToDocs
Dialog appear, choose Custom List in DropDownList as follows:
After create Event Receiver with handle above, code generated as follows:
Right Click to CopyAttachFileToDoc  | Properties | set properties Handle ItemAdded is true and Handle ItemUpdated  is true. MoreOver set properties Handle ItemAdding is false and Handle ItemUpdating is false then delete 2 method ItemAdding and ItemUpdating. Result as follows: 
Copy method EventCopyFileWhenItemCreatedOrUpdated(properties);  to 2 event ItemUpdated and ItemAdded as follows: 
Code here:
public override void ItemUpdated(SPItemEventProperties properties)
        {
            EventCopyFileWhenItemCreatedOrUpdated(properties);
            base.ItemUpdated(properties);
        }

        /// <summary>
        /// An item was added
        /// </summary>
public override void ItemAdded(SPItemEventProperties properties)
        {
            EventCopyFileWhenItemCreatedOrUpdated(properties);
            base.ItemAdded(properties);
        }
Copy this code and paste to here
Code here
private void EventCopyFileWhenItemCreatedOrUpdated(SPItemEventProperties properties)
        {
            if (properties.ListTitle == "Candidate" || properties.ListTitle == "Client")
            {
                SPListItem sourceItem = properties.ListItem;              
                SPFolder mylibrary = properties.Web.Folders["HumanCapitalDocument"];
                // Set AllowUnsafeUpdates = true to avoid security error
                properties.Web.AllowUnsafeUpdates = true;
                //get the folder with the attachments for the source item
                SPFolder sourceItemAttachmentsFolder =
                   sourceItem.Web.Folders["Lists"].SubFolders[sourceItem.ParentList.Title].SubFolders["Attachments"].SubFolders[sourceItem.ID.ToString()];
                //Loop over the attachments, and add them to the target item               
                foreach (SPFile file in sourceItemAttachmentsFolder.Files)
                {
                    if (CheckFileNameExist(file.Name,properties) == false)
                    {
                        byte[] binFile = file.OpenBinary();
                        mylibrary.Files.Add(System.IO.Path.GetFileName(file.Url), binFile);
                    }
                }
            }
        }
Continue copy code and pate here
Code here
private bool CheckFileNameExist(string fileNameInFileAttach, SPItemEventProperties properties)
        {
            bool flag = false;

            SPList myDocumentLibrary = properties.Web.Lists["HumanCapitalDocument"];
            SPQuery spQuery = new SPQuery();
            SPListItemCollection items = myDocumentLibrary.GetItems(spQuery);
            foreach (SPListItem item in items)
            {
                if (fileNameInFileAttach == item["Name"].ToString())
                {
                    flag = true;
                    break;
                }
            }
            return flag;
        }
Full code:
using System;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;

namespace EventReceiverCopyFile.CopyAttachFileToDoc
{
    /// <summary>
    /// List Item Events
    /// </summary>
    public class CopyAttachFileToDoc : SPItemEventReceiver
    {      
       /// <summary>
       /// An item was added
       /// </summary>
       public override void ItemAdded(SPItemEventProperties properties)
       {
           EventCopyFileWhenItemCreatedOrUpdated(properties);
           base.ItemAdded(properties);
       }

       /// <summary>
       /// An item was updated
       /// </summary>
       public override void ItemUpdated(SPItemEventProperties properties)
       {
           EventCopyFileWhenItemCreatedOrUpdated(properties);
           base.ItemAdded(properties);
       }

       private void EventCopyFileWhenItemCreatedOrUpdated(SPItemEventProperties properties)
       {
           if (properties.ListTitle == "Candidate" || properties.ListTitle == "Client")
           {
               SPListItem sourceItem = properties.ListItem;
               ////////////////////////////////////////////////////////////////////////////////////////
               SPFolder mylibrary = properties.Web.Folders["HumanCapitalDocument"];
               // Set AllowUnsafeUpdates = true to avoid security error
               properties.Web.AllowUnsafeUpdates = true;
               //get the folder with the attachments for the source item
               SPFolder sourceItemAttachmentsFolder =
                  sourceItem.Web.Folders["Lists"].SubFolders[sourceItem.ParentList.Title].SubFolders["Attachments"].SubFolders[sourceItem.ID.ToString()];
               //Loop over the attachments, and add them to the target item               
               foreach (SPFile file in sourceItemAttachmentsFolder.Files)
               {
                   if (CheckFileNameExist(file.Name, properties) == false)
                   {
                       byte[] binFile = file.OpenBinary();
                       mylibrary.Files.Add(System.IO.Path.GetFileName(file.Url), binFile);
                   }
               }
           }
       }
       private bool CheckFileNameExist(string fileNameInFileAttach, SPItemEventProperties properties)
       {
           bool flag = false;

           SPList myDocumentLibrary = properties.Web.Lists["HumanCapitalDocument"];
           SPQuery spQuery = new SPQuery();
           SPListItemCollection items = myDocumentLibrary.GetItems(spQuery);
           foreach (SPListItem item in items)
           {
               if (fileNameInFileAttach == item["Name"].ToString())
               {
                   flag = true;
                   break;
               }
           }
           return flag;
       }
    }
}

Build and deploy project
Open your sharepoint site | Click to Document list “HumanCapitalDocument”, you don’t see any file
Case Create new item:
Open Custom List Candidate:  create new Item and attach your file and save it
Back to Document list “HumanCapitalDocument”, you see file copied to there
Similar you create new item and attach your file in List Client, result file attach copied to Document list “HumanCapitalDocument”
Case Edit Item:
Edit item contain file attach in list Candidate and plus attach your file
Result after edit plus attach file, in Document list “HumanCapitalDocument” is copied

4 comments:

  1. Hi, how to do the same with InfoPath forms?

    ReplyDelete
    Replies
    1. Hi, thanks for your comment. Do you mean attachment is infopath form and will copy to form library ? Thanks

      Delete
    2. I did not try to infopath form attachment, but did you download my example and deploy it. Then you can try to with infopath form attachment, you need to change document library to form library. if you meet any problem, please put the comment here. i will help you to solve it. Thanks.

      Delete