Getting Your Feet Wet Writing Code For SharePoint – Part 2 of 5

Originally posted on: http://geekswithblogs.net/SoYouKnow/archive/2009/08/12/getting-your-feet-wet-writing-code-for-sharepoint-ndash-part-again.aspx

In part 1 of this five part blog series we learned how to find a specific SharePoint list on a farm.  In this post we will modify that code from part 1 to iterate through and store data for a particular view of that list in the proper column order. 

So let’s get started!  If you haven’t already, read the previous blog post and get up to speed with the code we’ve written so far.  Specifically the method we wrote to retrieve the SharePoint List.  Got it?  Good…

A Word About Performance

Before we continue forward I must make a public service announcement about performance.  In the previous blog post I left off with the method returning the SPList.  You may have been tempted to take that code and run with it, iterating through the list as follows:

 // Loop through entries using indexer as demonstrated in SDK           
 for (int i = 0; i < oList.Items.Count; i++)             
{                
     // Get specific list item                 
    SPListItem item = oList.Items[i];            
  
    // Do something with the Item                
    StoreItemData(item);             
}

Now if you did the above it would work, and apparently this is even how the examples are written in the SDK, but DON’T do it!  Eric Shupps has a tremendous presentation on “Developing High Performance Applications for Microsoft Office SharePoint Server 2007”.  If you have not had a chance to see it, you really have to.  Probably the best SharePoint development presentation I’ve ever seen!  Well.. the only one.. but still!   If I remember correctly, by using the above method to retrieve an item in a list, every time you execute “SPListItem item = oList.Items[i]” the entire table containing list data is searched for the one list entry.  The ENTIRE table.  That table includes list data for every list for every site and site collection in that content database.  So, even if your list only has 100 entries, the table could have millions of entries and every time you execute the above line of code it searches through the millions of entries in the table to find your one.  Let that sink in for  a moment.  That’s pretty huge.

You can increase your performance by using an in-memory item collection and further increase it by writing a CAML query to populate the item collection.  For the purposes of this application we will be using just the former, especially since we are trying to keep this application generic for any SharePoint List in your farm.  Again, check out out Eric’s presentation to get a much better understanding.  Thanks Eric for letting me leech off of your knowledge.  Hopefully I have not miss-quoted you here.

Back To Your Regularly Scheduled Blog Post

Okay.. enough about performance, let’s get back to the issue at hand.  We have code that finds a specific SharePoint List.  How do we get just the entries for a particular view in that list and also get those entries in an in-memory item collection so we won’t get yelled at?

We need to do the following in order to accomplish this:

  • Determine the GUID for our desired view
  • Get SPView from SPList using GUID
  • Get collection of items for list and view as well as list of fields for view
  • Iterate through the entries for the list in the view in the proper column order

Determine the GUID for our desired view

The first thing we need to do is determine the GUID for the view of the the SPList we want.  You may be wondering why I’m bothering with a view when I could just write a CAML query to get the list entries that I want in the column order I desire?  Good point, however, I am writing this application to be used for any view on any SharePoint List on a farm.  Writing a CAML query would mean I’d be limited to using SPLists that happen to have the same information.

Anyway, the SPList Object has a method GetView() that takes a GUID as a parameter and returns an SPView.  This is what we want here.  So, we need to find that GUID.  How do you find the GUID for a view?  There are a couple of utilities you can use that I’ve been too lazy to download.  So, I can’t help you with those.  I can, however, tell you how to find the GUID for a view in SharePoint pretty easily:

  • Go to the List settings for the SharePoint List

image

  • At the bottom of the List Settings screen is where you will see a list of all your views

image

  • Click on the View that you want to find the GUID for.  When you click on the View it opens up the “Edit View” screen.  Now look in your URL.  You see what’s there?  Yes, ‘a lot of garbage’ is correct.  Part of that garbage is the GUID for your view.  Here is an example URL from doing this process:

http://mrackleyspdev/_layouts/ViewEdit.aspx?List=%7BF4EBF829%2DAFB6%2D4B18%2D982E%2DE0F0A25DE595%7D&View=%7B7674ABF8%2DC71D%2D49FB%2DA9A3%2D7FD45993EDEC%7D&Source=%252F%255Flayouts%252Flistedit%252Easpx%253FList%253D%25257BF4EBF829%25252DAFB6%25252D4B18%25252D982E%25252DE0F0A25DE595%25257D

Like I said, looks like a lot of garbage doesn’t it?  If you read through this information you see the query string variable “View”.  All of that information for that Query String variable is your view GUID.  So, for the above example, the GUID is %7B7674ABF8%2DC71D%2D49FB%2DA9A3%2D7FD45993EDEC%7D

Don’t get to happy.  We aren’t done yet.  The GUID is URL encoded.  We need to remove the URL encoded brackets from the front and end of the GUID (%7B and %7D) and also convert all of the %2D’s back to dashes.  So, after we manual decode the GUID it becomes:  7674ABF8-C71D-49FB-A9A3-7FD45993EDEC

You may think that’s a lot of work to go through to find a GUID and if you are doing it 20 times a day I’d say you are correct.  For the one or two times I’ve had to do it though, it’s worked great.  So, don’t give me any of your lip, or actually suggest some of those utilities I know exist out there but am too lazy to download and install. 

Get SPView from SPList using GUID

Now you are probably wanting to get the SPView from your SPList using the GetView() method.  Wait a second… Not so fast cowboy (not you Eric, your doing fine).  We have our GUID String, however the GetView() method takes a ‘Guid’ object as a parameter.  I know.. I know.. it’s just one thing after another… This one is actually painless though.  The parameter to create a Guid object is a String representation of the GUID exactly as we have it up there.  So to create a Guid the code looks like:

Guid oGUID = new Guid(“7674ABF8-C71D-49FB-A9A3-7FD45993EDEC”);

Now we can get our SPView Object using the SPList object we found from part 1 of this blog series:

SPView oView = oList.GetView(oGUID);

Get collection of items for list and view as well as list of fields for view

Now that we have our SPList and SPView we are almost ready to iterate through the entries of the view to get our desired data.  We just need to get a little more information before we start going through the list data.

First thing we need is the SPListItemCollection for the SPList and SPView.  This is the in-memory object I was talking about earlier you should use and avoid indexing on the SPList.  You can get the SPListItemCollection out of the SPList for the SPView as follows:

SPListItemCollection oItemCol = oList.GetItems(oView);

We also need to get a String Collection of the field names for the view.  If you just iterate through the SPListItemCollection you will actually get all the fields in the list and not just the ones specified in your view.  By getting the collection of field names in the view we will be able to get only those fields in the view and also ensure we get them in the proper column order as defined in the view.  To get a String Collection of the field names of your view in the correct order:

//get the list of fields in the view, in order 
SPViewFieldCollection collViewFields = oView.ViewFields; 
//put list of view fields in a string collection to iterate through 
StringCollection stringCol = collViewFields.ToStringCollection();

Do you HAVE to convert the SPViewFieldCollection to a StringCollection? I doubt it.  I can’t even say it’s best practice; it’s the way I did it.  Give me a little slack.

Iterate through the entries for the list in the view in the proper column order

We are now ready to iterate through our list data and do what we need to with it.  You’ll have to wait for the next blog entry to see what we actually do with the data though.

So, using all of the information we have collected throughout this blog, we now have what we need.  The code below goes through every row in a SPList for a particular SPView.  With each row of data, the code iterates through the field names for a view in the order specified for the view.  The value for that field is then retrieved from that row and stored.  In this code chunk we are storing the field data in a fictitious object called oRowData and calling a fictitious method to store the row data:

//go through each row in the list for the view 
foreach (SPListItem item in oItemCol) 
{       
    //create new fictitious object to store a row of data from the view     
    oRowData = new RowData();       
    //get each field from the view and get value from list     
    foreach (String viewField in stringCol)      
    {                 
        //get field from row of data (viewField will be iterated through in order)                 
        SPField field = item.Fields.GetField(viewField);                  
        //get the display name of the current field                 
        String fieldTitle = field.Title;                 
        //get the value for the field (we are getting it as text for this application,                 
        //so if you don’t need text you’ll need to play around here)                
        String fieldValue =  field.GetFieldValueAsText(item[field.InternalName]);               
        //Store field in fictitious row object                
        oRowData.Add(fieldTitle,fieldValue);     
    }     
    StoreRowData(oRowData); 
}  
 

Putting it all together

So, let’s put this all together and see what what we have.  Taking the code from the first blog post and incorporating it into this blog post we get (notice that I changed the names of the methods so that they make more sense):

        static void Main(string[] args)
        {
            //specify the name of the list your want to find
            String listName = "AuthorizedRequestors";
            String sGuid = "7674ABF8-C71D-49FB-A9A3-7FD45993EDEC";

            bool bStored = StoreSPInfo(listName,sGuid);

            //write a message to the console window
            if (!bStored)
            {
                Console.WriteLine("There was a problem getting or storing list: {0}",listName);
            }
            else 
            {
                Console.WriteLine("List '{0}' WAS store successfully!  Press enter to exit",listName);
            }
            //wait for an enter key press
            Console.ReadLine();
        }

        private static bool StoreSPInfo(String listName, String sGuid)
        {
            //go through each SPWebApplication
            foreach (SPWebApplication oWebApp in SPWebService.ContentService.WebApplications)
            {
                Console.WriteLine("Searching WebApp: " + oWebApp.DisplayName.ToString());
                //go through each SPSite
                foreach (SPSite oSite in oWebApp.Sites)
                {
                    Console.WriteLine("Searching Site: " + oSite.Url.ToString());
                    try
                    {
                        //go throuth each SPWeb in the SPSite
                        foreach (SPWeb oWeb in oSite.AllWebs)
                        {
                            Console.WriteLine("Searching web: " + oWeb.Url.ToString());
                            try
                            {
                                //get the list based upon name.
                                //if list is not in spweb this will cause an exception
                                //to be thrown.  This is Ok. so, just catch it and continue
                                //I know.. I know.. this is not good practice.  But there is not
                                //a oWeb.ListExists() method or something like that.
                                SPList oList = oWeb.Lists[listName];
                                //list was found!
                                Console.WriteLine("LIST FOUND!");
                                StoreViewForList(oList, sGuid);
                                return true;
                            }
                            catch
                            {
                                //catch and continue
                                Console.WriteLine("List not found in web: " + oWeb.Url.ToString());
                            }
                            finally
                            {
                                //make sure to dispose of web
                                oWeb.Dispose();
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("Exception occured: {0}\r\n{1}", e.Message, e.StackTrace);
                    }
                    finally
                    {
                        oSite.Dispose();
                    }
                }
            }
            return false;
        }

        private static void StoreViewForList(SPList oList, String sGuid)
        {
            SPView oView = oList.GetView(new Guid(sGuid));
            SPListItemCollection oItemCol = oList.GetItems(oView);
            //get the list of fields in the view, in order
            SPViewFieldCollection collViewFields = oView.ViewFields;
            //put list of view fields in a string collection to iterate through
            StringCollection stringCol = collViewFields.ToStringCollection();

            //go through each row in the list for the view
            foreach (SPListItem item in oItemCol)
            {

                //create new fictitious object to store a row of data from the view
                //oRowData = new RowData();
                //get each field from the view and get value from list
                foreach (String viewField in stringCol)
                {
                    //get field from row of data (viewField will be iterated through in order)
                    SPField field = item.Fields.GetField(viewField);

                    //get the display name of the current field
                    String fieldTitle = field.Title;

                    //get the value for the field (we are getting it as text for this application, so if you don’t need text you’ll need to play around here)
                    String fieldValue = field.GetFieldValueAsText(item[field.InternalName]);

                    //Store field in fictitious row object
                    //oRowData.Add(fieldTitle, fieldValue);
                    Console.WriteLine("Field Title: {0}, Field Value: {1}",fieldTitle,fieldValue);
                }
                //StoreRowData(oRowData);
            }  


        }


So, if you run the code above with a valid List name and View GUID the code will find your SPList and iterate through all the list entries for a view.  The code will also write out to the console every field name and value that it iterates through in the column order specified for your view.

There you have it.  Nothing spectacular or super sexy, but it gets the job done.  In the next blog post we will be creating and storing this information in an excel spreadsheet.

If I did not go into enough detail somewhere please let me know and I’ll try to go back and make sure it makes sense to you. 

Finally, thanks for the kind comments I’ve received so far about this series.  Just never hesitate to tell me how I can improve.  Thanks for reading.

<UPDATE>

Part 3 is up and posted here.

</UPDATE>

Families in Germany who are facing divers health problem, such persons can buy drugs from the Web without prescription. With the market flooded with divers web-sites selling sundry medicaments, purchasing medicines from th WEB is no longer a trouble for common man. Certain medications are used to treat infections caused by dental abscesses. Of course it isn’t all. If you’re concerned about erectile health problem, you probably know about Xenical and Hoodia. Probably each adult knows about Garcinia. (Read more PhentermineXenical). The symptoms of sexual soundness problems in men turn on impossibility to have an erection sufficient for sexual functioning. Certain medications may add to sex drive difficulties, so its vital to cooperate with your soundness care professional so that the prescription can be tailored to your needs. Preparatory to taking Levitra or other medicament, speak to your pharmacist if you have any allergies. Talk to your health care purveyor for more details. Preparatory to ordering this remedy, tell your doctor if you are allergic to anything.