Updating document metadata with URL only

Oct 15, 2014 at 3:45 PM
I have an array looping through various documents and copying them to another library. After copying each file, I want to update a text column called "Moved" to say 'Yes'. I've had some success doing this with a REST call but it doesn't seem to work consistently. I'd like to try using SPServices instead, since it always works great.

What I need to do is - using ONLY the relative URL for the document - update the file's "Moved" column value. I don't have the ID for the document, and the file could be from one of several libraries (so I won't know the library name or GUID). I think UpdateListItem might work, but I haven't been able to figure out the syntax for it.

Am I barking up the wrong tree here, or is SPServices the right way to go?
Coordinator
Oct 15, 2014 at 4:11 PM
You'll need to know the source library (listName) and the ID to do the update, so you should collect it in the copy process.

M.
Oct 15, 2014 at 4:22 PM
I was afraid of that. Does SPServices have a way to get the library name for each file based on the relative URL? All I have during the copy process is the original URL, but maybe I could get the library name in the first part of my function, then pass it to the second part?
Oct 16, 2014 at 2:32 AM
Re: does SPServices have an operation for getting info from a URL

There is an operation that returns information about an item based on its URL, but it's not yet supported by SPServices: https://spservices.codeplex.com/workitem/10241
In that Issue you will find a link where you can find a working copy of the operation.

/Paul
Oct 16, 2014 at 2:19 PM
Neat! At first glance, that appears to be exactly what I need. I"ll play around with this and see if it works for me. Either way, thanks Paul!
Oct 17, 2014 at 2:11 PM
Paul - I'm having an issue getting your script to work, but I'm pretty sure it's something I'm doing wrong (I'm still pretty new at this). Here's my function where I call your utility. I have your script saved to a JS file that's being loaded in my master page along with jQuery and SPServices. What I'm seeing in the console is the error "The object or method 'SPGetListItemInfoByUrl' is not supported". I also tried putting your entire script into my own (just pasted it all at the bottom) but still got the same error. I think I'm messing up the call to it.
function updateFile(itemUrl) {

var libraryName;
var itemID;

  $.SPGetListItemInfoByUrl(itemUrl)
   .done(function(urlInfo){
     libraryName = urlInfo.strListID;
     itemID = urlInfo.strItemID;
  });

 
  $().SPServices({
      operation: "UpdateListItems", 
      async: false, 
      batchCmd: Update,
      listName: libraryName,
      ID: itemID,
      valuepairs: [['Moved', 'Yes']],
                    
      completefunc: function(xData, Status) { 
            //alert( xData.responseText );
            if (Status == "Error") {
               alert ("There was an error updating the file.");
            } else {
               alert("The item was updated successfully.");
            }
      }
  });

}
Oct 18, 2014 at 1:11 AM
A few things:
  1. The utility depends on both jQuery and SPServices, so you need to include it in the master page right after those two
  2. Wrap my utility code in the following:
    (function($){
    // paste my utility code here
})(jQuery);
  1. The utility uses promises, so you need to put your UpdateListItems call inside the promise callback.
I'll try to look a little closer next time I'm at a computer.
Oct 20, 2014 at 2:00 PM
Edited Oct 20, 2014 at 3:32 PM
I don't currently have a promise callback in the script - I'm just calling the CopyFile function, then the UpdateFile function on the next line. I'll read up on promises and see if I can figure out how to add one.

Regarding item #2, do I still need to wrap it if it's located in a separate file?

Thanks for all the help - I appreciate it!

UPDATE: If it helps, here's my entire script in JSFiddle. The update function gets called right after the copy function (see line 117 or 129) and then I'm trying to use your utility at line 312. It was all kind of bashed together, so sorry if it's a little messy.
Oct 21, 2014 at 2:56 AM
yes, you still need to do #2... or copy and paste the code from that GIST to a placed in your code (ex. prior to your updateFile() function.

Looks like you want this to run synchronous, based on your asysnc: false use above... if so, then you need to do the same with $.SPGetListItemInfoByUrl... I also noticed an error on your UpdatelistItems call - You did no thave quotes around the batchCmd value....

Try this:

Note: This code below has a few alert()'s to give you some hints on where it may be going wrong.
    // Copy and paste this: https://gist.github.com/purtuga/9036747 - here
    
    function updateFile(itemUrl) {

      var libraryName;
      var itemID;

      if (!$.SPGetListItemInfoByUrl {
        alert("$.SPGetListItemInfoByUrl NOT LOADED!");
      }
      $.SPGetListItemInfoByUrl({
          url: itemUrl,
          async: false
        })
       .done(function(urlInfo){
         if (!urlInfo.resultsFound){
            alert("Unable to determine information for url: " + itemUrl);
         }
         libraryName = urlInfo.strListID;
         itemID = urlInfo.strItemID;
      });

     
      $().SPServices({
          operation: "UpdateListItems", 
          async: false, 
          batchCmd: "Update",
          listName: libraryName,
          ID: itemID,
          valuepairs: [['Moved', 'Yes']],
          completefunc: function(xData, Status) { 
                //alert( xData.responseText );
                if (Status == "Error") {
                   alert ("There was an error updating the file.");
                } else {
                   alert("The item was updated successfully.");
                }
          }
      });

    }
Hope this helps.
Oct 21, 2014 at 6:25 PM
I think it's got me going in the right direction. The utility appears to be loading, but my libraryName and itemID variables are both coming back as 'undefined'. The SPServices bit is returning the success alert, however, even though the file wasn't actually updated.

I'm a lot closer than I was a couple days ago.
Oct 21, 2014 at 6:48 PM

Re: Successful alert

You're only checking that the XML message (the udpate) was successful sent to the server... Your not actually checking if the server (SharePoint) produced an error... which most likely it did. to do that, you need to look at what's inside of xData.responseXML (see this issue which has a method that can help with error checking).

Re: variables undefined

Does this alert fire?
alert("Unable to determine information for url: " + itemUrl);
If so, what does the URL look like? and is it a link that points to a location (document library or List item) that is in the same site as the one being used in to update the list items (same as the value of webURL)?

Here is a post on the utility I created - http://paultavares.wordpress.com/2014/02/18/how-to-get-information-about-a-sharepoint-list-item-using-its-url/ - It details a few cases where I found this service to not be able to resolve.
Oct 21, 2014 at 6:56 PM
The alert isn't firing. I added an alert just above the SPServices call that shows me the value for both variables, and that's the one undefined values for both.

I'll look at both of those links and see what I can figure out. Sorry - I'm still learning this stuff as I go.
Oct 21, 2014 at 7:08 PM
ok.. if the alert is not firing, then it seems as if information about the URL did come back...

Can you add this to the .done() method, before the setting of the variables:
alert("URL INFO: " + JSON.stringify(urlInfo));
if strItemID and strListID are not set, then add this as well:
alert("XML: " + arguments[1].responseText);
Oct 22, 2014 at 2:01 AM
Ok - I added both alerts right before the 2 lines setting the variables. Neither alert popped up. I got the one stating the item was updated successfully, then the last one in the script stating that the files have been copied successfully. It almost seems to be jumping right over the part calling your utility.
Oct 22, 2014 at 5:05 PM
Jacob,
I just tried the method in one of my site (SP2010) and it worked... I called SPGetListItemInfoByUrl() with a fully qualified URL (http://...../folder/sub/folder/file.aspx) and it worked as advertised...
Not sure what's going on with your implementation... Sounds like you are going to have to do some "real" :-) debugging... like setting breakpoints and inspecting your application flow.
Sorry I'm not able to help any further.
Oct 22, 2014 at 5:44 PM
No problem - I pretty much know it's something I'm doing wrong, just not sure what. I'm using the server-relative URL, but that should still work right?
Oct 23, 2014 at 12:22 AM
For the file? I don't remember now - but maybe not... Can you test with a hard-coded string that is a valid absolute URL to the file?
Oct 24, 2014 at 4:54 PM
Yep, that was it. Apparently it requires a full URL and won't work with just the relative one. I added a line that appends the "http://site.com" bit onto the front of the relative URL variable, and now it's working like a charm.

Awesome work, Paul - thanks!
Oct 24, 2014 at 11:25 PM
Cool. Good luck with the rest of the project.