Migrating your SharePoint Site between versions

by Benjamin Niaulin

This is going to be a very popular subject in 2013. We’ve been using SharePoint 2007 and 2010 for quite some time now, and now SharePoint 2013 is at the door knocking. This means we will be hearing a lot about SharePoint migration. The thing is, it might be very different this time around. In SharePoint 2007, when we did a migration, most of the time we would just restart because we saw it as an opportunity to do it right this time around. But most of us are now quite comfortable with SharePoint, enough to have used Content Types and a well-structured architecture this time. This means we might actually want to migrate our site between versions. There is no easy way to do this.

What’s to migrate?

Of course we have to make sure we understand the structure before we can talk about ways to migrate. Saying we want to copy or move a site is nice and all but how is it actually stored in SharePoint? SharePoint sites are always part of a “Site Collection” this is all sites that are grouped together by a single hierarchy and a top site, the root site. Sites are not individually stored in the Database but rather the Site Collections are. This would make it easy for us if we were migrating a SharePoint Site Collection. Why? Well using the interface or PowerShell we can isolate a Site Collection in a Database. We can take that database and move it to the destination, which in this case would be SharePoint 2013.

But first things first, what’s a SharePoint Site? We can look at it as a container. We create a Site to group lists and libraries together. Those are the only objects that exist inside of our site. So when you migrate a site, you’re basically migrating a container of lists and libraries.

What are your options?

This is where it gets complicated, there is no “Migrate Site” button in SharePoint, you have to figure it out yourself.

As mentioned above, one way would be to take the Database with the entire Site Collection in which your site is located and do a database-attach upgrade.

Once you’ve attached your database in a test farm or test web application, depending on your infrastructure, you can use the SharePoint tools to export your site and import it to a new location. The tricky thing is to never forget that your site was part of a Site Collection. Which means it might have been dependent on features, site columns or content types that may have existed at the root site or site collection level.

Microsoft always offers ways, either by PowerShell, SharePoint Designer or the interface to manage sites within the same version. Unfortunately there is no easy way to move across versions. One thing I noticed throughout my migrations is that this can be a very long process just to move a few sites. Without a good SharePoint Migration tool it can be very hard or very long for us to do it.

SharePoint 2013 only supports Database-Attach upgrade scenario. So we have to find ways to get the sites that we want into a database in 2010 and bring it over to 2013 to then move it to the right destination. And if you are one of the very many still on SharePoint 2007, Site migration is going to be very difficult without passing through 2010. I would even say impossible without custom tools.

No easy way

My conclusion is that when doing a SharePoint migration of sites between versions, you will probably run into a few problems. Microsoft recommends migrating by taking the databases of the old and upgrading to the new keeping everything as is. We have to play around with this to make it work for our Site migration. If you are planning a large number of site migrations or do this on a regular basis, you’re probably better off investing in a SharePoint Migration tool.

Biography – Benjamin Niaulin
Benjamin Niaulin works as a SharePoint Geek at Sharegate, a Montreal-based software development firm specialized in SharePoint migration.
Passionate about SharePoint, Benjamin has been helping people around the globe reaching their goals by simplifying SharePoint solutions. With his Microsoft Certified Trainer certification and over 5 years of Training and Speaking experience, he has acquired the skills needed to help everyone understand and use SharePoint.

SharePoint Sketches: SPServices Cascading Dropdowns

I’ve been finding design solace in my notebook lately, and I’m realizing this is turning into a mini-series on sketched-out, front-end development in SharePoint. So for this part of the series I’m covering SPServices Cascading Dropdowns.

Although cascading dropdown menus have been a feature of SPServices for ages, I have never taken the time to sit down and walk through how it all works. As I was using it on a recent project I decided I needed to draw out what I was reading in the Documentation to make sure I understood. So, here’s how SPCascadeDropdowns plays out in my mind (descriptions below):

jQuery SPServices SPCascadeDropdowns

Description:

In this solution I’ve used SPServices Cascading Dropdowns to create a new “Student” list item. As well as storing the student’s name, the create form allows me to select a division (Elementary School, Middle School, or High School), and then select a teacher who is part of that division using cascading dropdowns.

Setup:

Create 3 lists:

  • Divisions
    • Column 1 – Title (one list item for each division)
  • Teachers
    • Column 1 – Title (for Teacher’s name)
    • Column 2 – Division (Lookup column from Divisions list)
  • Students
    • Column 1 – Title (for Student’s name)
    • Column 2 – Division (Lookup column from Divisions list)
    • Column 3 – Teacher (Lookup column from Teachers list)

Once you have your three lists, populate the first two (Divisions and Teachers) with your content.

Next, open up the NewForm.aspx (or EditForm.aspx) file for your list in SharePoint Designer. Look for the PlaceHolderAdditionalPageHead Content Placeholder. Put the following script inside that placeholder (assuming you’ve already loaded jQuery and SPServices elsewhere):

<script type="text/javascript">
$(document).ready(function(){
	$().SPServices.SPCascadeDropdowns({
		relationshipList: "Teachers",
		relationshipListParentColumn: "Division",
		relationshipListChildColumn: "Title",
		parentColumn: "Division",
		childColumn: "Teacher",
		debug: true
	})
})
</script>

Explanation of how script works

The trickiest part of SPservices and the SPCascadeDropdowns function is figuring out which columns to use where. So here’s the breakdown:

relationshipList: This is the list in your setup that contains both of the columns you eventually want to use in the cascade (but not the target list where the cascading happens). In this case it is the “Teachers” list because it contains both of the columns we’ll use.

relationshipListParentColumn: This is the “base” column from the relationshipList (“Teachers”), the one you will use to begin the cascading process. In this case it is “Division,” because we first select a division, and then select a teacher.

relationshipListChildColumn: This is the column from the relationshipList (“Teachers”) that comes after the base column has been selected. In this case it is “Title,” NOT “Teacher,” because remember we’re looking at the relationship list.

ParentColumn: This is the column in your target list (“Students”) (and therefore in the New and Edit forms) that will begin the cascade. In this case it is “Division,” because as I mentioned earlier it is the column that we select first to obtain the cascaded list of teachers.

ChildColumn: This is the column in your target list (“Students”) that will be altered based on what you choose in the ParentColumn. In this case it is “Teacher,” because we want to receive a drop-down list of teachers once we select a division.

Once you stop and look at it, everything seems to make sense. But it can be slightly confusing when your source tables all have similar column names because they are lookup columns.

Hope this helps!

SharePoint in Education: Case Study Sketches (jQuery and SPServices)

Here’s a preview inside my notebook for how the new SharePoint Scheduling Assistant works. It’s been honed down to use 3 master lists instead of creating a new list for every teacher (70+ in this case). It’s built using jQuery, SPServices, and of course SharePoint 2010. Check out the more extensive case study to see how it was done. Hope to post more soon with even more details!

SharePoint, jQuery, and SPServices in Education

SharePoint and jQuery SPServices in Education: A Case Study

This is a morphed, updated, renewed version of the SharePoint Scheduling Assistant. I’m not releasing this version quite yet, but this is a brief case study on how it’s working at a specific school.

Business Needs

The International School of Beijing needed a way for Elementary School parents to book time slots with teachers during bi-annual parent-teacher conferences.

The requirements:

  • Easy to use (training is impossible).
  • Integrate into the current intranet portal.
  • Sync with the database to omit any kind of manual setup for secretaries.
  • Deny parents the ability to book more than one slot with the same teacher.
  • Allow parents to book the same slot for two different teachers (in case mother and father come in and meet with 1 teacher each to save time)
  • If two or more parents are online at the same time, correctly queue the submissions so a double booking does not occur.
  • Allow teachers to pre-block out slots where parents cannot book times.
  • Allow teachers the ability to see their entire schedule, including which student is coming in during which time slot.

Solution (SharePoint, jQuery, and SPServices)

A SharePoint solution was built with jQuery to meet the requirements of the Elementary School. Let’s break down how the solution was created:

Part 1 – SharePoint

Within SharePoint three lists were created:

  • Bookings (Each reservation had its own row in this list that stored the details of who booked it, for which teacher, etc.)
  • Time Slots (A pre-determined list of time slots…in this case a list item was created for each 20 minute time slot from 12-6pm on Thursday and Friday Oct 18 and 19).
  • People (An external content type that pulled records from the database for each student, each of their parents, and each of their teacher names)

One of the trickier parts of this solution was grabbing the external content from the database in a usable way. Once it was in, we were able to work with the data. However, this list has 10,000+ items, so dealing with larger data like this was quite challenging. Enter jQuery.

Part 2 – jQuery and SPServices

The bulk of this solution was created with the jQuery and jQuery SPServices Libraries. Using jQuery, we stepped through the process like this:

  1. Get the details of the logged in user (parent) using SPServices
  2. Hit the SharePoint external data list once, filter it by Parent (matching to the Parent login ID), and store it in a javascript object for later use. This was the biggest strain on the system. We minimized the data call to only one time, but even still, pulling a list of 10,000 records even once isn’t super quick.
  3. Get all the children of the logged in parent, push them to a drop-down menu
  4. Get all the teachers of the selected child from #3, push them to another drop-down menu
  5. Get all time slots from the Time Slots list, push to a third drop-down menu
  6. Retroactively disable all time slot options that have already been booked (by searching through the Bookings list for records that match the time slot and the selected teacher)

Once the data was present, the parent could interact with it in two ways, book, and delete.

To book a time slot, the selected child, selected teacher, and selected time slot (along with a comments area) was submitted and saved to the list. To delete a time slot, a delete button is appended to each reservation in the on-screen schedule with the ID of the reservation as the ID of the link element.

The data from the Bookings list is checked once during the time slot selection process, and again during the form submit process to make sure no double bookings have occurred.

Benefits

This solution enables, for the first time at this school, parents to go online and manage their entire Parent-Teacher Conference schedule. Also, as an added bonus, if a mother and father both login, they can see the complete schedule for their child, even if only one of the parents made the bookings.

Once a parent books a time slot, they receive an email containing the details of their reservation.

An additional feature of this solution was that it was duplicated and tweaked for teachers to use a similar interface to pre-block out time slots where they did not want parents to come (ie, lunch, coffee break, going home). In that scenario the “one-block” restriction was removed for teachers, allowing them to customize when parents would be given the option to come in.

Create a jQuery accordion with a SharePoint CQWP

Today we’ll be creating 5 (don’t be scared!) small files that will result in you being able to add a Content Query Web Part to a page, and display the results in a jQuery accordion format. It should look something like this:

Click for a demo or download the source files

Steps to create your own:

Step 1: Add, then Export a standard CQWP

This method of editing a CQWP to do what you want involves no custom coding, no packaging, no .wsp files. All you need to do is go to any page and insert a CQWP Web Part (OOTB). Once it is on your page, click the little black arrow that displays the Web Parts context menu and select Export. This will download a .webpart file called Content. Open this file in your favorite code editor (at the moment mine are Notepad++ for Windows and TextMate for Mac), and go to step 2.

Step 2: Edit the .webpart file to read custom .xsl files

To see the full .webpart file, check out the source code, but basically we’re going to edit 4 lines and put links to our custom .xsl files:

  • Title
  • ItemXslLink
  • MainXslLink
  • XsL

Once you have edited these 4 lines, upload this webpart to the root Web Part gallery by clicking Site Actions > Site Settings > Web parts.

<property name="Title" type="string">Accordion</property>
<property name="ItemXslLink" type="string">/Style Library/XSL Style Sheets/AccordionStyle.xsl</property>
<property name="MainXslLink" type="string">/Style Library/XSL Style Sheets/AccordionCQWP.xsl</property>
<property name="Xsl" type="string">&lt;xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:cmswrt="http://schemas.microsoft.com/WebPart/v3/Publishing/runtime" exclude-result-prefixes="xsl cmswrt x" &gt; &lt;xsl:import href="/Style Library/XSL Style Sheets/Header.xsl" /&gt; &lt;xsl:import href="/Style Library/XSL Style Sheets/AccordionStyle.xsl" /&gt; &lt;xsl:import href="/Style Library/XSL Style Sheets/AccordionCQWP.xsl" /&gt; &lt;/xsl:stylesheet&gt;</property>

Step 3: Create AccordionStyle.xsl

Instead of using SharePoint’s ItemStyle.xsl (not best practice to edit that directly) we’re going to create our own stylesheet (the one we linked to in step 2). It has the same header as ItemStyle.xsl, so feel free to copy from there or from below. However, it only has one template. I’ve called the template Accordion, so when you’re editing the Web Part properties in the browser you’ll see this as the only selectable style in the Presentation pane.

Basically all this style does is wrap the header field (represented by @Title) in a div with a class of accordion-header, and the body field (represented by @Body) in a div with a class of accordion-content. We’ll use these classes later in the jQuery functions.

Once you’ve created this file, put it in /Style Library/XSL Style Sheets/ using SharePoint Designer.

<xsl:stylesheet
  version="1.0"
  exclude-result-prefixes="x d xsl msxsl cmswrt"
  xmlns:x="http://www.w3.org/2001/XMLSchema"
  xmlns:d="http://schemas.microsoft.com/sharepoint/dsp"
  xmlns:cmswrt="http://schemas.microsoft.com/WebParts/v3/Publishing/runtime"
  xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:msxsl="urn:schemas-microsoft-com:xslt">

<!-- Accordion Template -->
    <xsl:template name="Accordion" match="Row[@Style='Accordion']" mode="itemstyle">

       <div class="accordion-header"><xsl:value-of select="@Title"/></div>
	   <div class="accordion-content"><xsl:value-of select="@Body" disable-output-escaping="yes" /></div>

    </xsl:template>
</xsl:stylesheet>

Step 4: Create AccordionCQWP.xsl

The next page we’ll make starts off as a clone of ContentQueryMain.xsl, so go there real quick and copy all of that code into your new file.

There are three things we will do to this code.

  1. Replace dfwp-list with accordion (on lines 32 and 83)
  2. Replace all occurrences of dfwp-item with accordion-item (line 34)
  3. Add (using html character codes…annoying) “expand all” and “collapse all” divs before the list.

Come to think of it, you wouldn’t have to do #3 if you just used jQuery to prepend those buttons to the list. Yeah, that’s the easier way…I’ll update the post soon.

Once you’ve done those 3 edits, upload this file to /Style Library/XSL Style Sheets/ (the same place as the file in step 3)

      <!-- beginning of code from ContentQueryMain.xsl goes here -->
  <xsl:variable name="BeginList" select="string('&lt;ul class=&quot;accordion&quot;&gt;&lt;div class=&quot;expand-all&quot;&gt;Expand All&lt;/div&gt;&lt;div class=&quot;collapse-all&quot;&gt;Collapse All&lt;/div&gt;')" />
  <xsl:variable name="EndList" select="string('&lt;/ul&gt;')" />
  <xsl:variable name="BeginListItem" select="string('&lt;li class=&quot;accordion-item&quot;&gt;')" />
  <xsl:variable name="EndListItem" select="string('&lt;/li&gt;')" />
  <xsl:template match="/">
        <xsl:call-template name="OuterTemplate" />
    </xsl:template>
    <xsl:template name="OuterTemplate">
        <xsl:variable name="Rows" select="/dsQueryResponse/Rows/Row" />
        <xsl:variable name="RowCount" select="count($Rows)" />
        <xsl:variable name="IsEmpty" select="$RowCount = 0" />
            <div id="{concat('cbqwp', $ClientId)}" class="cbq-layout-main">
                 <xsl:if test="$cbq_iseditmode = 'True' and string-length($cbq_errortext) != 0">
                    <div class="wp-content description">
                        <xsl:value-of disable-output-escaping="yes" select="$cbq_errortext" />
                    </div>
                  </xsl:if>
                  <xsl:choose>
                      <xsl:when test="$IsEmpty">
                           <xsl:call-template name="OuterTemplate.Empty" >
                               <xsl:with-param name="EditMode" select="$cbq_iseditmode" />
                           </xsl:call-template>
                      </xsl:when>
                      <xsl:otherwise>
                           <xsl:call-template name="OuterTemplate.Body">
                               <xsl:with-param name="Rows" select="$Rows" />
                               <xsl:with-param name="FirstRow" select="1" />
                               <xsl:with-param name="LastRow" select="$RowCount" />
                          </xsl:call-template>
                      </xsl:otherwise>
                  </xsl:choose>
            </div>
            <xsl:if test="$FeedEnabled = 'True' and $PageId != ''">
                <div class="cqfeed">
                    <xsl:variable name="FeedUrl1" select="concat($SiteUrl,$FeedPageUrl,'xsl=1&amp;web=',$WebUrl,'&amp;page=',$PageId,'&amp;wp=',$WebPartId,'&amp;pageurl=',$CBQPageUrl,$CBQPageUrlQueryStringForFilters)" />
                    <a href="{cmswrt:RegisterFeedUrl( $FeedUrl1, 'application/rss+xml')}"><img src="\_layouts\images\rss.gif" border="0" alt="{cmswrt:GetPublishingResource('CbqRssAlt')}"/></a>
                </div>
            </xsl:if>
    </xsl:template>
    <xsl:template name="OuterTemplate.Empty">
        <xsl:param name="EditMode" />
            <xsl:if test="$EditMode = 'True' and string-length($cbq_errortext) = 0">
                <div class="wp-content description">
                    <xsl:value-of disable-output-escaping="yes" select="$cbq_viewemptytext" />
                </div>
            </xsl:if>
    </xsl:template>
    <xsl:template name="OuterTemplate.Body">
      <xsl:param name="Rows" />
      <xsl:param name="FirstRow" />
      <xsl:param name="LastRow" />
      <xsl:variable name="BeginColumn1" select="string('&lt;div class=&quot;expand-all&quot;&gt;Expand All&lt;/div&gt;&lt;div class=&quot;collapse-all&quot;&gt;Collapse All&lt;/div&gt;&lt;ul class=&quot;accordion&quot; style=&quot;width:')" />
      <xsl:variable name="BeginColumn2" select="string('%&quot; &gt;')" />
      <xsl:variable name="BeginColumn" select="concat($BeginColumn1, $cbq_columnwidth, $BeginColumn2)" />
      <xsl:variable name="EndColumn" select="string('&lt;/ul&gt;')" />
      <!-- rest of code from ContentQueryMain.xsl goes here -->

Step 5: jQuery functions

Our jQuery code is going to do several things:

  • Start every content pane hidden and make sure all headers are deactivated
  • When a header is clicked, it toggles the “expanded” class on the header (giving it a different style) and uses slideToggle (a jQuery animation) to show or hide the content pane.
  • It adds functions to the “expand all” and “collapse all” buttons we made earlier

When you’re done copy and pasting (or modifying) this code, save it in /Style Library/scripts/accordion.js. If you’ve got other javascript files there you should consider combining and condensing your code for less calls, but for the sake of this tutorial, it will be a standalone .js file. Once you’ve dropped the file into your system, link to it from the Master Page. Here’s an article on how to call custom javascript from your Master Page.

function accordionLoad() {

	$(".accordion-header").removeClass("expanded");
	$(".accordion-content").hide();

	$(".accordion-header").bind("click", function(){
		$(this).toggleClass("expanded");
		$(this).siblings(".accordion-content").slideToggle();
	})

	$(".expand-all").bind("click",function(){
		$(this).siblings(".accordion").find(".accordion-content").slideDown();
		$(this).siblings(".accordion").find(".accordion-header").addClass("expanded");
	})

	$(".collapse-all").bind("click",function(){
		$(this).siblings(".accordion").find(".accordion-content").slideUp();
		$(this).siblings(".accordion").find(".accordion-header").removeClass("expanded");
	})
}

$(document).ready(function(){
	accordionLoad();
});

side note: I would love to rewrite this jQuery to be a controller, that way it can be re-used across the site anytime somebody adds .accordion() to an element using jQuery.

Step 6: CSS

This is the way I want my accordion to look, so feel free to modify. This is also the style used in the demo of this tutorial.

When you’re done, drop this file in /Style Library/css/accordion.css (again, you could also include this in you main css, but for the sake of the tutorial it’s standalone).

/* Accordion Style
********************************************************** */
ul.accordion {
	list-style:none;
	margin:0px;
	padding:0px;
}
.accordion-item {
	border-top:1px solid #ccc;
}
.accordion-header {
	font-size:1.2em;
	cursor:pointer;
	padding:10px;
}
.accordion-header:hover {
	background:#efefef;
}
.accordion-header.expanded {
	background:#dfdfdf;
}
.accordion-content {
	padding:20px;
}
.expand-all,
.collapse-all {
	display:inline-block;
	cursor:pointer;
	padding:5px 10px;
}
.expand-all:hover,
.collapse-all:hover {
	background:#efefef;
}

Step 7: Putting it all together

So, once you’ve made all of the above files, your structure should look like this:

  • /Style Library/XSL Style Sheets/AccordionStyle.xsl
  • /Style Library/XSL/Style Sheets/AccordionCQWP.xsl
  • /Style Library/scripts/accordion.js
  • /Style Library/css/accordion.css
  • Accordion.webpart (uploaded to the Web Part Gallery)

Now go to your page, add the Accordion Web Part, and use it to display a list of items (FAQs and announcements work great in this format). It should be quite easy to read in the is jQuery Accordion format.

Click for a demo or download the source files

“Send” emails to a SharePoint Task List

A colleague and I were looking to have a quick way to manage tasks between the two of us. We had previously just used email. But since most of our workload is using SharePoint, we figured we’d drink our own medicine and see if we could improve the workflow.

Things we wanted to accomplish:

  1. a running history of all of our tasks in SharePoint
  2. quick access (no filling out forms online)
  3. be able to assign tasks to each other
  4. save emails as attachments of tasks, to track requests as they come in

Setting up a task list in SharePoint is quite straightforward, but making it easy and fast to manage took a little bit of thinking. Luckily, everything can be done out of the box, and I’ll show you how here.

Step 1 – Setup the task list

Go to Site Actions > More Options and create a Tasks list.

I created a few views of my tasks and put them on my dashboard so we can see all our active tasks, and the tasks we’ve recently completed.

Step 2 – Connect to Outlook

Go to your task list and click Connect to Outlook in the ribbon. You’ll be prompted (most likely) with several alerts asking you to confirm the connection. After that, if you go to Tasks in Outlook you’ll see your connected SharePoint task list right beneath your local task list. You can create tasks just like you would normally do in Outlook, and they should sync with the SharePoint list.

But that only got us halfway there. All of our requests come by email, so we wanted to avoid re-typing each task. We wanted a way to “send” the email into the task list.

 

Step 3 – Copy emails to the task list

Problem solved! Right click on the email you want to use to originate a task and click on Move > Copy to Folder

A window will come up with all of the options of where you can copy the email. If you scroll to the bottom of the list you should see a folder called SharePoint Lists. Expand that folder and you’ll see your SharePoint task list that has been connected to Outlook.

Click OK and a new task window will pop up with the body of the email in the task description. You can assign the task to yourself or anyone else that has access to the SharePoint list. Also, just to confirm you are assigning that task to the shared list, look in the footer of the window and you should see something to the effect of: In Shared Folder: SharePoint Tasks.

BONUS: If you want to save an email that has an attachment, first double-click the email message to open it in a new window. From there, if you follow the above steps of moving it to the task list folder, it will save the email message as an attachment to the task, including all attachments in the email itself.

How to import Data into SharePoint 2010 using Lightning Tools Data Masher

This post will cover how to import data into SharePoint 2010 from your database using Lightning Tools Data Masher.

Step 1 – Activate Feature

Make sure the Data Masher Menu Items feature is activated in your site features.

Step 2 – Create a new import

Next, click on Site Settings > Create Data Masher Import

Step 3 – Settings

Now for the fun part!
Input the connection string to your database and click Connect to Data Source. At this point, more options will appear below. Choose your table from the database (in my case it’s a community directory SQL view).
Next, give the import a title and description (both are required).
Then choose whether to create a new list from this import (easiest way) or to import the data into an existing list (more tricky, as you have to map each column). If you choose to create a  new list, your list will have the name of the database table you are importing. Choose the columns you would like to import by CTRL + clicking each column name.
Finally, choose how frequently you would like your list updated and click Save.

Step 4 – Results

If everything was successful you should be presented with a list (after the job runs the first time…which may not be immediate) that has all of your freshly imported data.