Sunday, April 13, 2014

How to show Holidays Events into SharePoint 2013 Calendar



Introduction

This article describes how to read an iCalendar file and insert the calendar events into a SharePoint 2013 calendar. It will also outline how we can show these new events as a calendar overlay to an existing SharePoint 2013 calendar so as to display it in another color and add additional view filters to these events.

Background

I am maintaining a departmental SharePoint 2013 team site which has a shared calendar object that the personnel in the departments rely on to update their out of office statuses and other departmental activities. As such, we thought it will be a good idea to also show public holidays on the calendar so staff can use it as a standard reference point to plan their work activities.
Public holidays are usually published in an iCalendar file on a government website. iCalendar, also known as RFC 2445, is a standard textual file format with the extension ".ics". It is a widely used format for exchanging and publishing calendaring and scheduling information, and it is used and supported by many calendaring products such as Google Calendar, Lotus Notes, Microsoft Outlook, etc.
Since the iCalendar files are in a standard format, there are multiple libraries available that can be used to extract the contents in the file. We will be using the Open Source DDay.iCal library to interact with the calendaring information in the iCalendar files and SharePoint 2013 Web Services to insert calendar events into the team site shared calendar.

SharePoint Calendar Setup

To keep the public holidays as a separate SharePoint calendar so that we can overlay the new calendar onto the existing departmental calendar, we would first have to create the new calendar. In your SharePoint site, create a new calendar under the List category. In this example, I have named the new calendar "Public Holidays".

Referencing SharePoint 2013 Web Services

After our new calendar is set up in the SharePoint site, we will need to switch back to Visual Studio 2012 to add a reference to the Web Services that are located in the SharePoint site. Create a new "Windows Console Application" project in Visual Studio 2012. Add the references to the DDay.iCal library to your solution, namely the antlr.runtime.dll and DDay.iCal.dll files. Next, we need to add a Web Service reference to our SharePoint site. Right click on "Service Reference" in your Visual Studio solution and select "Add Service Reference".
Create Service Reference
As SharePoint 2012 is utilizing .NET 2.0 style Web Services, we will need to create Web Service references instead of service references. In the "Add Service Reference" window, click on "Advanced". A "Service Reference Settings" dialog box should pop up. Click on "Add Web Reference" to add a .NET 2.0 Web Service reference to the solution.
Adding Web Reference
At the Add Web Reference screen, type in the URL of your SharePoint site which contains the calendar, followed by the service path to the Lists.asmx Web Service. In this example, our site is named "caltest". Give a name to your Web Service reference. In this example, we have named it "WService". Click "Add Reference" to add this Web Service reference to our solution.
Setting Web Reference

Using the Code

First, we need to include the DDay.iCal namespace into our code. Add the following using statement at the top of the Program.cs file:
using DDay.iCal;
Second, since we will be using CAML queries to create SharePoint 2013 calendaring entries, we will need to manipulate XML elements. We can do this easily by including the .NET System XML libraries. Include this statement following the DDay.iCal library inclusion.
using System.Xml;
To load calendar entries from the iCal files that you have downloaded, you just need to call the static LoadFromFile method. Note that you can also load from other sources such as WebDAV or database. To load the entries from your local hard drive however, you just need the statement below.
IICalendarCollection calendars = iCalendar.LoadFromFile(@"D:\Dharmendra\holidays.ics");
To iterate the events that are contained in the iCal file that you have just read, you need to define a start date and end date in the GetOccurance method before you use a foreach loop to extract each individual event or occurrence. In the example below, we specify the current year.
foreach (Occurrence currentOccurance in calendars.GetOccurrences(
   new DateTime(DateTime.Today.Year, 1, 1), 
   new DateTime(DateTime.Today.Year, 12, 31)))
{
    DateTime occurrenceTime = 
      currentOccurance.Period.StartTime.Local;
    IRecurringComponent rc = 
      currentOccurance.Source as IRecurringComponent;
    if (rc != null)
    {
        string holidayName = rc.Summary;
        DateTime holidayDate = occurrenceTime;
    }
}
To insert SharePoint 2013 calendar entries, we need to construct CAML queries and send it to the Lists.asmx Web Service. The Lists.asmx Web Service has various methods to allow you to manipulate lists in SharePoint. Calendars in SharePoint 2013 are implemented as lists, the only difference is that the list entries are rendered in a calendar view rather than a standard list view. Also, you will need to format your date string in a specific format for SharePoint 2013 to recognize it. The following example shows how to format your date as well as the various fields that you need to pass in to create the calendar entries.
string startDateString = String.Format("{0}T{1}Z", 
  holidayDate.ToString("yyyy-MM-dd"), holidayDate.ToString("HH:mm:ss"));
string endDateString = String.Format("{0}T{1}Z", 
  holidayDate.ToString("yyyy-MM-dd"), holidayDate.ToString("HH:mm:ss"));

XmlDocument doc = new XmlDocument();
XmlElement batch_element = doc.CreateElement("Batch");
string item = "<Method ID=\"1\" Cmd=\"New\">";
item = item + "<Field Name=\"Location\"></Field>";
item = item + "<Field Name=\"EventDate\">" + startDateString + "</Field>";
item = item + "<Field Name=\"EndDate\">" + endDateString + "</Field>";
item = item + "<Field Name=\"Description\">" + holidayName + "</Field>";
item = item + "<Field Name=\"Title\">" + holidayName + "</Field>";
item = item + "<Field Name=\"fAllDayEvent\">1</Field>";
item = item + "<Method>";
batch_element.InnerXml = item;
list.UpdateListItems("Public Holidays", batch_element);

Combined Final Code

Combining the code snippets above, we have something like the example below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DDay.iCal;
using System.Xml;

namespace ImportICalendar
{
    class Program
    {

        public Program()
        {
            IICalendarCollection calendars = iCalendar.LoadFromFile(@"D:\Dharmendra\holidays.ics");

            try
            {
                WService.Lists list = new WService.Lists();
                list.Url = "https://confluo.atrackspace.com/_vti_bin/Lists.asmx";
                list.Credentials = new System.Net.NetworkCredential("Confluo.user2@raxsp.com", "Mp7Pw3Br", "");  
                foreach (Occurrence currentOccurance in calendars.GetOccurrences(new DateTime(DateTime.Today.Year, 1, 1), new DateTime(DateTime.Today.Year, 12, 31)))
                {
                    DateTime occurrenceTime = currentOccurance.Period.StartTime.Local;
                    IRecurringComponent rc = currentOccurance.Source as IRecurringComponent;
                    if (rc != null)
                    {
                        string holidayName = rc.Summary;
                        DateTime holidayDate = occurrenceTime;

                        string startDateString = String.Format("{0}T{1}Z", 
                          holidayDate.ToString("yyyy-MM-dd"), 
                          holidayDate.ToString("HH:mm:ss"));
                        string endDateString = String.Format("{0}T{1}Z", 
                          holidayDate.ToString("yyyy-MM-dd"), 
                          holidayDate.ToString("HH:mm:ss"));

                        XmlDocument doc = new XmlDocument();
                        XmlElement batch_element = doc.CreateElement("Batch");
                        string item = "<Method ID=\"1\" Cmd=\"New\">";
                        item = item + "<Field Name=\"Location\"></Field>";
                        item = item + "<Field Name=\"EventDate\">" + 
                               startDateString + "</Field>";
                        item = item + "<Field Name=\"EndDate\">" + endDateString + "</Field>";
                        item = item + "<Field Name=\"Description\">" + holidayName + "</Field>";
                        item = item + "<Field Name=\"Title\">" + holidayName + "</Field>";
                        item = item + "<Field Name=\"fAllDayEvent\">1</Field>";
                        item = item + "</Method>";
                        batch_element.InnerXml = item;


                        list.UpdateListItems("Holiday", batch_element);
                    }
                }
            }
            catch(Exception e){
                Console.WriteLine("Error occurred : " + e.ToString());
            }
        }

       
        
        
        static void Main(string[] args)
        {
            new Program();
        }
    }
}
After running the code above, the entries in the iCal file should be inserted into the "Holiday" calendar. When we refresh the calendar in our SharePoint site, we should see the entries being inserted and displayed on the calendar.

Adding Additional SharePoint Calendar Overlay

Now, coming to the final part of this article, we want to overlay the "Holiday" calendar on top of our existing department SharePoint calendar. First, go back to the main calendar and click on "Calendars in View".
In the Calendar overlay screen, give a name to the overlay. In this example, we have named our overlay " Holiday Overlay". You will need to fill in the URL of your SharePoint site and click on the Resolve button to get SharePoint to retrieve all the calendars that are available for the particular SharePoint site. Select the calendar which you want to use as an overlay and click on the OK button.

You will be returned to the Additional Calendar screen. Here you can choose which particular calendars will be visible in view. Click OK to overlay the "Holiday" calendar onto your existing SharePoint 2013 calendar and you're done!

Wednesday, April 9, 2014

Migration tool

https://www.quest.com/common/registration.aspx?requestdefid=23182

Lotus Notes to SharePoint 2010 Migration


Recently I was engaged in a large scale Lotus Notes to SharePoint 2010 Migration project for a client in the travel/aviation industry vertical . Lotus Notes is a multi-user collaborative client-server application environment competing with Microsoft SharePoint 2010 suite of products /Microsoft Outlook/ Office workspace 2010. There are numerous legacy Lotus-Notes implementations which sometimes can be a overhead to main overtime and scale. This post summarize the approach taken to migrate such a application into SharePoint 2010.
The legacy Notes Applications in the context was designed and developed few years back was not quite helping accelerating the business outcomes for the client. Therefore migrating those applications onto a  single platform which can centrally manage and maintain over time was timely.
 Notes Architecture
The Domino product is an integrated messaging and Web application software platform. It provides a robust environment for creating Web applications that support workflow, RDBMS connectivity, and collaboration. Domino is ideal for creating applications that allow "sometimes connected", multiple users to cooperatively process unstructured information.The term Lotus Notes is now used to refer to the underlying client-server architecture that the product is built upon.
Storage Model
The storage model of Lotus notes storage area a "Note" (These Notes will also be referred to as documents, a term more familiar to users). In each Note we have "items"; and each item has its own "item name". ( and an item may be a list of values) .This iterative structure of one element containing other elements has been referred to as the Notes container model. The "Notes Storage Facility" and the file that creates on the Notes Client is given an extension of .NSF.The Notes data model contains no concept of a "record type". All documents in a database are equivalent as far as Notes in concerned.
User Interface
Forms is the mechanism that Notes Client (Desktop Client) use to show the user what is in a document.The areas on the form that display the values stored in the items on a document will be called fields.This listing of item values from a set of documents in a column format is a Notes View.
Agents
You can program Notes to perform tasks automatically using agents (also known as macros). Agents can help you perform repetitive tasks, such as managing documents and sending memos. Agents can complete almost any action you can do manually in your databases.When you create an agent, you can set options to specify:
  • When the agent should run. (ie. a document has been changed)
  • Which documents in the database the agent should run on. You can target all or any subset of documents in the database for the agent to run on.
  • What actions the agent should complete. You can choose actions from a list or use Notes formulas or programming scripts and languages to create actions.
Tools for the Job
  • Visio 2010 Premium – Modelling new the process workflows with business analysts/domain experts
  • SharePoint Designer 2010 – Authoring the workflows/ customising list forms etc.
  • Visual Studio 2010 – Create Solution Artefacts/ Custom event handlers/ create features, packaging sandbox .wsp solutions
  • SPServices jQuery library for SharePoint web services – UI extensibility helpers / Cascaded dropdowns etc.
  • Bit Bucket  with Mercurial/ VisualHG -Distributed Version Control (DVCS)
  • Quest Notes Migrator for SharePoint – For Data Mapping and Migration from Notes fields to SharePoint Lists.
Migration Map
Each Notes Application was mapped to Corresponding SharePoint 2010 Custom Application in its own Site Collection with its own Logical Security boundaries.
clip_image001
Process
The new applications were architected and implemented leveraging the new platform capabilities of SharePoint 2010 and mapped the required data into the new application platform. The Quest Notes migrator did a good job for us by nicely abstracting Lotus notes internals by allowing us to defined Extract-Transform-Load (ETL) operations including user mappings from Domino to AD accounts. Where Transformations were complex Extract-Load-Transform (ELT) approach was used with custom transformation rules with PowerShell / C#
High level process followed for migrating each Notes application to SharePoint 2010 platform involved following steps
  1. Consult Notes application owners (product owners) in each department and created a prioritised product backlog
  2. Modelled the new workflows /rules with Visio 2010 premium with business users
  3. Built & Prototyped the new application with the best tool fit for the job. (Visual Studio 2010   -  Author and deploy base level custom site columns/content types/list definitions/list instances/custom event handlers , SharePoint Designer 2010 – forward engineer the Visio workflows / XSLT List form customization )
  4. Data mapping jobs were created/tested with Quest Notes migrator for SharePoint in the dev environment with a subset of production data
  5. Repeated steps 3 & 4 with product continues reviews/feedback
  6. Reverse engineer reusable workflows into features and list form  into solution artefacts into SharePoint Solution packages and deploy into production environment as SharePoint features
  7. Execute the Data migration job on the production environment
Hope this post would benefit those who interested in migrating legacy lotus notes applications to SharePoint 2010.