Monday, March 28, 2011

Export SharePoint List Programmatically

If you try to search on internet on this topic, there are many posts available and each one uses different technique to achieve this
last week, one of my colleague asked me how they can export the SharePoint list content (they were accessing sites remotely) , well answer was quite simple , click on actions tab on list and then select export to spread sheet and save file , but what really puzzled me is , what are other OOB ways available by SharePoint to achieve this other than this option?
I tried searching for this for few hours and ended up with writing a sample console application which exports the list’s default view and write list contents to spreadsheet
Major disadvantage of this is, you cannot run this application when you are not directly working with SharePoint Server, because we are using Server side object model to achieve this
I am keen to see this in SharePoint 2010 environment because we can use Client Object Model to achieve this
But for now here is code I created
I know this code is little heavy (due to those foreach loops) but I thought this is ok as this won’t be running continuously on server


class Program
{

  private static DataTable dataTable;
  private static SPList list;

  static void Main(string[] args)
  {
   try
   {
    Console.WriteLine("Site Url: ");
    string _siteUrl = Console.ReadLine();
    if (!string.IsNullOrEmpty(_siteUrl))
    {
     SPSecurity.RunWithElevatedPrivileges(delegate()
     {
       using (SPSite site = new SPSite(_siteUrl))
       {
         if (site != null)
         {
          SPWeb web = site.RootWeb;

          if (web != null)
          {

            #region Export List

            Console.WriteLine("List Name:");
            string _listName = Console.ReadLine();
             if (!string.IsNullOrEmpty(_listName))
             {
               list = web.Lists[_listName];

               if (list != null)
               {
                 dataTable = new DataTable();

                 //Adds Columns to SpreadSheet
                  InitializeExcel(list, dataTable);

                  string _schemaXML = list.DefaultView.ViewFields.SchemaXml;

                  if (list.Items != null && list.ItemCount > 0)
                  {
                   foreach (SPListItem _item in list.Items)
                   {
                     DataRow dr = dataTable.NewRow();
                     foreach (DataColumn _column in dataTable.Columns)
                     {
if (dataTable.Columns[_column.ColumnName] != null   && _item[_column.ColumnName] != null)
                      {
dr[_column.ColumnName] = _item[_column.ColumnName].ToString();
                      }
                     }
                     dataTable.Rows.Add(dr);

                    }
                   }

                 }
              }

System.Web.UI.WebControls.DataGrid grid = new System.Web.UI.WebControls.DataGrid();

          grid.HeaderStyle.Font.Bold = true;
          grid.DataSource = dataTable;
          grid.DataBind();

          using (StreamWriter streamWriter = new StreamWriter("C:\\" + list.Title + ".xls", false, Encoding.UTF8))
          {
           using (HtmlTextWriter htmlTextWriter = new HtmlTextWriter(streamWriter))
           {
             grid.RenderControl(htmlTextWriter);
           }
          }

             Console.WriteLine("File Created");

            #endregion
           }
          }
        }
        });
       }
      }
      catch (Exception ex)
      {
         Console.WriteLine("Error: " + ex.Message);
      }

      Console.ReadLine();
    }

   public static void InitializeExcel(SPList list, DataTable _datatable)
   {
    if (list != null)
    {
     string _schemaXML = list.DefaultView.ViewFields.SchemaXml;
     if (list.Items != null && list.ItemCount > 0)
     {
      foreach (SPListItem _item in list.Items)
      {
       foreach (SPField _itemField in _item.Fields)
       {
        if (_schemaXML.Contains(_itemField.InternalName))
        {
          if (_item[_itemField.InternalName] != null)
          {
           if (!_datatable.Columns.Contains(_itemField.InternalName))
           {
             _datatable.Columns.Add(new DataColumn(_itemField.StaticName, Type.GetType("System.String")));
           }
          }
         }
        }
       }
      }
     }
    }
   }

Wednesday, March 23, 2011

Change PublishingPageLayout of Page Programmatically

After launch of SharePoint 2010 we all came to know that platform is improved heavily in all aspects and some enhancements in web content management too
We can easily change the layout of any Publishing Page using a ribbon in SharePoint 2010
But many of us are still in confusion that how we can achieve this using MOSS 2007? Rather some people think that we cannot change the page layout of page using MOSS 2007, but this is not true
Well, to know how to do this in MOSS 2007, here are some steps
1.    Browse the page for which you want to change page layouts (of course this should be a publishing page)
2.    If you are working with Publishing Site, click on Site Actions and select Show Page editing toolbar (If you are working with custom master pages , and see that this option is grayed out then make sure that you have added PublishingConsole control entry on master page)
3.    Now you will be able to see Page Editing tool bar, now select Page option , a drop down will appear , there you have to select Page Settings and Schedule option
4.    After selecting this you will see a page will be opened, scroll down and find option Page Layout
5.    Now this is where you can apply page layouts to page , select different page layout from dropdown and click ok
I hope now your previous page layout for page gets changed J
but there are some cases I faced where I wanted to change the layout of the page but after doing all these steps when I reached to the page where we can change page layouts , I didn’t find the dropdown filled with other page layouts , so I was not able to change
Now what to do in this case?
Well as developer, we always have code to help us , so decided to do these all using SP object model
And here is the code what I have done, this works for me at least J
Code just tries to open root web, gets collection of pages created with given page layout, searches the given page in this collection, and applies new given page layout the page and done
There can be multiple ways to do this, and code can be modified for more flexibility and according to need


static void Main(string[] args)
{
 #region Variables

 string _siteUrl = string.Empty;
 string _pageName = string.Empty;
 string _pageLayouts = string.Empty;
 string _newPageLayout = string.Empty;
 string _responce = string.Empty;
 PublishingPageCollection _pages = null;

 #endregion

 try
 {
   Console.WriteLine("Site Url: ");
   _siteUrl = Console.ReadLine();

   if (!string.IsNullOrEmpty(_siteUrl))
   {
    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
      using (SPSite site = new SPSite(_siteUrl))
      {
        using (SPWeb web = site.RootWeb)
        {
          if (web != null)
          {
           if (PublishingWeb.IsPublishingWeb(web))
           {
             PublishingWeb pWeb = PublishingWeb.GetPublishingWeb(web);
             Console.WriteLine("Search Pages with Layout: ");
             _pageLayouts = Console.ReadLine();

             if (!string.IsNullOrEmpty(_pageLayouts))
             {
string query = @"<Where><Contains><FieldRef   Name='PublishingPageLayout' /><Value Type='URL'>" + _pageLayouts + "</Value></Contains></Where>";
                 
_pages = pWeb.GetPublishingPages(query);
             }

             do
             {
              if (_pages != null)
              {
               Console.WriteLine();
               Console.WriteLine("Search Page With Name: ");
               _pageName = Console.ReadLine();

               //LINQ to get actual page for processing
PublishingPage _desiredPage = _pages.Where(p => p.Name.ToLower().Contains(_pageName.ToLower())).FirstOrDefault();

                                              

   if (_desiredPage != null)
               {
                if (_desiredPage.ListItem.File.Level != SPFileLevel.Checkout)
                {
                                                        Console.WriteLine("Processing.." + _desiredPage.Name);
                                                        _desiredPage.ListItem.File.CheckOut();

                  Console.WriteLine("which Page Layout to apply?");
                  _newPageLayout = Console.ReadLine();

_desiredPage.ListItem["PublishingPageLayout"] = @"/_catalogs/masterpage/" + _newPageLayout;
                                                        _desiredPage.ListItem.Update();

_desiredPage.ListItem.File.CheckIn(string.Empty);

                  if (pWeb.PagesList.EnableMinorVersions)
                  {
_desiredPage.ListItem.File.Publish("Page Layout Changed..");
                  }
                   if (pWeb.PagesList.EnableModeration)
                   {
_desiredPage.ListItem.File.Approve("Approved by Console Application");
                   }

                   Console.WriteLine("Page Layout Updated");

                   Console.WriteLine("do you want to continue?");
                    _responce = Console.ReadLine();

                  }
                else
                {
Console.WriteLine("Page is already Checked out to user " + _desiredPage.ListItem.File.CheckedOutBy.Name);
                }
               }
               else
               {
                 Console.WriteLine("Page Not Found!!");
               }
              }
             }
while (_responce.ToLower().Equals("y") || _responce.ToLower().Equals("yes"));

            if (pWeb != null)
            {
              pWeb.Close();
            }

           }
          }
        }
       }
      });
     }
     else
     {
      Console.WriteLine("Invalid Site Url");
     }

    }
    catch (Exception ex)
    {
      Console.WriteLine("{0}:{1}", "Error", ex.Message);
    }

     Console.ReadLine();
   }

Tuesday, March 15, 2011

Get PublishingPageContent using SharePoint Web Services

Well.. this was something interesting I was looking into for few hours and came up with quick solution
We can easily get the PublishingPageContent of any Publishing Page using Publishing API but what If we want to achieve this using SharePoint Web Services?
Here is sample code,
I have  created a simple console application where I am trying to access SharePoint Pages List data using Lists.asmx
we just need to pass the url of the site and title of the page , this creates a local .htm file which has PublishingPageContents and Image if has any
Splitting code is basically done to refractor the urls of images because file is getting saved locally

I know that this code is somewhat dirty and can be much improved but that was just a quick solution I figured out and so posted
I hope this helps someone (at least to try some trick) J
Reference : SharePoint Magazine

static void Main(string[] args)
{
  string siteUrl = string.Empty;
  string pageName = string.Empty;
  Console.WriteLine("Enter Site Name:");
  siteUrl = Console.ReadLine();
  Console.WriteLine("Enter Page Name:");
  pageName = Console.ReadLine();
  Uri _uri = new Uri(siteUrl);

  #region Get Publishing Page Content

  StringBuilder _contentImageBuilder = null;

  try
  {
    ListsSvc.Lists lsts = new ConsumeWebService.ListsSvc.Lists();
    lsts.UseDefaultCredentials = true;
    lsts.Url = siteUrl + @"/_vti_bin/Lists.asmx"; ;

    System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
    System.Xml.XmlElement query = xmlDoc.CreateElement("Query");
    System.Xml.XmlElement viewFields = xmlDoc.CreateElement("ViewFields");
    System.Xml.XmlElement queryOptions = xmlDoc.CreateElement("QueryOptions");

    /*Use CAML query*/

    //Querying Pages with Required Page Name
    query.InnerXml = @"<Where><Contains><FieldRef Name='Title' /><Value Type='Text'>" + pageName + "</Value></Contains></Where>";

    //ViewFields to be returned with Result
    viewFields.InnerXml = "<FieldRef Name=\"Title\" /><FieldRef Name=\"PublishingPageContent\" />";

    queryOptions.InnerXml = string.Empty;

   //Get Data 
   System.Xml.XmlNode nodes = lsts.GetListItems("Pages", string.Empty, query, viewFields, "500", null, null);

   foreach (System.Xml.XmlNode node in nodes)
   {
     if (node.Name == "rs:data")
     {
       for (int i = 0; i < node.ChildNodes.Count; i++)
       {
         if (node.ChildNodes[i].Name == "z:row")
         {
           if (node.ChildNodes[i].Attributes["ows_PublishingPageContent"] != null)
           {
             _contentImageBuilder = new StringBuilder();

             string[] tokens = node.ChildNodes[i].Attributes["ows_PublishingPageContent"].Value.Split('"');
             foreach (string token in tokens)
             {
              if (token.StartsWith("/"))
              {
_contentImageBuilder.AppendFormat("{0}://{1}{2}", _uri.Scheme, _uri.Host, token);
              }
              else
              {
                 _contentImageBuilder.Append(token);
              }
             }
            }

if (_contentImageBuilder != null && !string.IsNullOrEmpty(_contentImageBuilder.ToString()))
{
StreamWriter writer= new StreamWriter("C:\\contents.htm", true, Encoding.UTF8);                                                                        writer.Write(_contentImageBuilder.ToString());
  writer.Close();
}

}
}
}
}
}
catch (Exception ex)
{
  Console.WriteLine("Error " + ex.Message);
}
#endregion
}