Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

Ok so I have a request from a user and I'm not sure how I can achieve this...I'm thinking workflows but not sure.

Basically what she wants is to have a Document Library where she can upload documents. Each document will have a file name like this "ClientA - Customization.docx". Now you can imagine that a she will upload many documents that will have an identical name so what we want to do is number the files automatically. So if she uploads the first document, SharePoint will add a number after the name so the file will be called "ClientA - Customization - 1.docx" and then if she uploads a second document and it will be called "ClientA - Customization - 2.docx".

So basically SharePoint needs to check if the name of the current document exists in the list and if it does add a number next to it, but the number must be 1 greater than the current highest document so it will just increase.

Is there any way to do this? I looked into workflows but couldn't really get anywhere since I could not find an action to change the file name. Any ideas?

Thank you!!!

EDIT: I have gotten this far by posting on forums and adding my own code but I can't seem to get it working, is he code ok? Basically it does not rename anything that I upload to the document library so maybe my event receiver is not attached? At the bottom is also the code I am using in a console app to attach the EventReceiver to my Document Library.

//--This code is in the EventReceiver 
public override void ItemAdded(SPItemEventProperties properties)
    {
        base.ItemAdded(properties);
        SPListItem item = properties.ListItem;

        if (item["Name"] == null)
            return; //or better yet, log 

        string oldFileName = item["Name"].ToString();

        int positionOfPeriod = oldFileName.LastIndexOf(".");
        string tempFileName = oldFileName.Substring(0, positionOfPeriod);

        SPQuery query = BuildArbitraryQuery(properties.List, "Name", tempFileName, true);
        int count = properties.List.GetItems(query).Count;
        String fileName, fileExtension;

        if (positionOfPeriod == -1)
        {
            fileName = oldFileName;
            fileExtension = "";
        }
        else
        {
            fileName = oldFileName.Substring(0, positionOfPeriod);
            fileExtension = oldFileName.Substring(positionOfPeriod);
        }

        string newFileName = fileName + "-xx" + count.ToString() + fileExtension;

        item["Name"] = newFileName;

        Console.WriteLine("New File Name: " + newFileName);

        try
        {
            properties.Web.AllowUnsafeUpdates = true;
            EventFiringEnabled = false;

            item.Update();
        }
        finally
        {
            properties.Web.AllowUnsafeUpdates = false;
            EventFiringEnabled = true;
        } 

    }
public static SPQuery BuildArbitraryQuery(SPList list, string columnDocumentName, string value, bool deepSearch)
    {
        if (list == null)
            throw new ArgumentNullException("You cannot pass a null list to Helper.BuildArbitraryQuery.");

        if (!list.Fields.ContainsField(columnDocumentName))
            throw new ArgumentException("The SharePoint List \"" + list.Title + "\" does not contain the Field \"" + columnDocumentName + "\".");

        string internalName = list.Fields[columnDocumentName].InternalName;
        SPQuery query = new SPQuery();
        query.Query = "<Where><Eq><FieldRef Name=\"" + internalName + "\"/><Value Type=\"Text\">" + value + "</Value></Eq></Where>";

        if (deepSearch)
            query.ViewAttributes += "Scope='RecursiveAll'";

        return query; 
    }
//this is the code in the console app to add the EventReceiver to the doc library
using (SPSite site = new SPSite("http://servername:port/teams/dps/"))
        {
            using (SPWeb web = site.OpenWeb())
            {
                SPList list = web.Lists["Requests"];

                SPEventReceiverDefinition def = list.EventReceivers.Add();
                def.Assembly = "DocumentLibrary_ClassLib, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=611205b34d18f14d";
                def.Class = "DocumentLibrary_ClassLib.EventReceiver";
                def.Type = SPEventReceiverType.ItemAdded;
                def.Update();

                Console.WriteLine("Registered");
                Console.Read();
            }
        }

*I really want this working so I am giving my reputation points away to someone that can help me get it working, pleeeaase :)

share|improve this question
    
anyone else have any ideas? The code should work but when I create a new document from SharePoint or upload one it will not change the name, what could I be doing wrong? Please help with this! –  Tudor Aug 22 '12 at 19:18

4 Answers 4

a couple of things that I'd consider:

You're looking at the ItemAdded event receiver. In the case where you've added a second item with the same name this has already overwritten the existing item.

You should maybe look at the ItemAdding even receiver and look for an upcoming conflict rather than trying mop up after you've replaced the existing file.

share|improve this answer
    
Agreed use the same code as it looks right. Furthermore, after you register the itemadding event I would attach the debugger and step though the code to ensure this event reciever is running. It'll also help you find bugs if any exist. –  onzur Aug 24 '12 at 4:51
    
Ok, stupid question, how do I attach the debugger so I can see if the event receiver is running? In Visual Studio I am using the console app to attach the event receiver, should I put a break point in the console app or in the event receiver? Or how can I debug this? Sorry I haven't used VS much before and this is kind of confusing to me. Thanks again! –  Tudor Aug 24 '12 at 18:00
    
Hey Tudor, sorry for the extremely late reply. Follow this link Make sure to do this on the server running SharePoint. You should have Visual Studio on the same server. Put a breakpoint in the event. This works for the ItemAdding event. Let me know if you need more assistance. –  onzur Aug 27 '12 at 14:22
    
If you're uploading the file via the web UI you need to attach to the w3wp process, if your console app is uploading the file after attaching the event receiver then attach to that. Put the breakpoint in the event. –  GavinB Aug 27 '12 at 20:52
    
Thanks! So I attached to the w3wp process but I have about 5 of them in the list, does it matter which one? The ID doesn't really mean anything to me so I'm not sure how to find out which one to attach too. I've tried 3 of the 5 and put a break point in ItemAdding Event on the first line but nothing happens, if I hover over the breakpoint I get that "The breakpoint will not currently be hit. No symbols have been loaded for this document." I tried using Document -> New Document on SharePoint to create a new document and saved it but that did not change anything, any idea what I am doing wrong? –  Tudor Aug 27 '12 at 21:24

Hi another alternative is to create your own custom upload control field, this would cut out event receivers totally and get around the issues you have.

Setting up a custom field control to do this would be pretty straight forward (Infact for example creating a upload control for blogs which isn't OOTB without enterprise)

This is a good resource if you haven't done them before:

http://msdn.microsoft.com/en-us/library/bb684919%28v=office.12%29.aspx

http://sriramkunapuli.com/2011/05/18/file-upload-custom-site-field-control-sharepoint-2010-part-2/

I hope this helps.

share|improve this answer
    
I've looked into the links and researched a bit on my own but I don't really understand how this would work and how the document name would be changed? Any help understanding the process? –  Tudor Aug 21 '12 at 22:33

A few ideas...

One alternative is the content organizer. You can enable the duplicate files settings which will automatically have a unique characters appended at the end of the file, but you can't change the behavior. Then you could have a workflow rename that document accordingly.

Your other options are to look at SPD extended activities, and use a combination of renaming and copying items (to prevent the risk of duplicate names).Also an EventReceiver would do the trick pretty nicely.

If you don't want to crack open visual studio, you could actually create a custom uploadpage (with a custom list form) and insert your own JavaScript validation. You can use the webservices to verify whats in the list and force the user to select the correct name (or change it) there. The downside is you need to include explicit link to the form you want users to use, and probably not direct them back to the library after they have uploaded the form.

share|improve this answer
    
Well I decided to try the event receiver method but I am a bit stuck, I pasted my code in the original post...any ideas what I am doing wrong? :) –  Tudor Aug 16 '12 at 23:42

ItemAdded event should do this The below would give you an idea

Here it's a bit of code that you can use in ItemAdded:

To get the file:

 SPFile spf = properties.ListItem.File;
 string url = properties.AfterUrl;

This url should be like:

sharepointlist/filename (for example: books/mybook.doc)

Then change the string and make a new url (for example: books/ ID_mybook.doc), and called it "newurl".

After that use the following code:

string newurl = myNewUrlString;
DisableEventFiring();
spf.MoveTo(newurl);

spf.Update();
EnableEventFiring();
share|improve this answer
    
Ok so heres what I did but its not working, nothing is happening in the list. In my event receiver I have this –  Tudor Aug 16 '12 at 18:34
    
public override void ItemAdded(SPItemEventProperties properties) { SPFile spf = properties.ListItem.File; string url = properties.AfterUrl; int positionOfSlash = url.LastIndexOf("/"); string pathBeforeFileName = url.Substring(0, positionOfSlash); string newFileName = createNewFileName(url.Substring(positionOfSlash)); string myNewUrl = pathBeforeFileName + newFileName; DisableEventFiring(); spf.MoveTo(myNewUrl); spf.Update(); EnableEventFiring(); } –  Tudor Aug 16 '12 at 18:35
    
static string createNewFileName(string oldFileName) { int positionOfPeriod = oldFileName.LastIndexOf("."); string fileName = oldFileName.Substring(0, positionOfPeriod); string fileExtension = oldFileName.Substring(positionOfPeriod); string newFileName = fileName + "-xx" + fileExtension; return newFileName; } **sorry about the many comments and code formatting but I can't figure out how to format it in the comments. What do you think? –  Tudor Aug 16 '12 at 18:36
    
I pasted the code in my initial post since the formatting is better. –  Tudor Aug 16 '12 at 23:41

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.