Monthly Archives: March 2016

Statistics in Office 365 Video

Another new feature in Office 365 video is the usage statistics. There are two graphs currently available for the last 14 days or 36 months showing the views, visitors and viewer engagement. Check out my video review of the new features below.



Adding subtitles and captions to Office 365 video

I’ve created a quick video guide on how to add subtitles in Office 365 video. It consists of first creating a VTT file containing the subtitles data and then uploading it into the video settings inside Office 365. Please find the video below and hope you find it useful!



Using PowerShell to add a list or library WebPart to a SharePoint publishing page via CSOM

Thought I would share this as I struggled to find a complete article online how to do this. First of all, the code below is based on José Quinto’s post USING POWERSHELL TO ADD WEBPART TO SHAREPOINT PAGE VIA CSOM IN OFFICE 365. It’s a really good article on adding a content editor web part to a publishing page.

I couldn’t find any posts online on how to use the same technique to add a list view web part to a page. Eventually I figured out how to create the XML for adding a list view web part.

This is an adaptation of Jose’s function to add a web part to a page:

function AddWebPartToPage ($ctx, $sitesURL, $WebPartXml, $pageRelativeUrl, $wpZoneID, $wpZoneOrder) {
	try{
		Write-Host "Starting the Process to add the User WebPart to the Home Page" -ForegroundColor Yellow
		#Adding the reference to the client libraries. Here I'm executing this for a SharePoint Server (and I'm referencing it from the SharePoint ISAPI directory, 
		#but we could execute it from wherever we want, only need to copy the dlls and reference the path from here        
		Add-Type -Path "c:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll" 
		Add-Type -Path "c:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll" 
		Write-Host "Getting the page with the webpart we are going to modify" -ForegroundColor Green
		#Using the params, build the page url
		$pageUrl = $sitesURL + $pageRelativeUrl
		Write-Host "Getting the page with the webpart we are going to modify: " $pageUrl -ForegroundColor Green
		#Getting the page using the GetFileByServerRelativeURL and do the Checkout
		#After that, we need to call the executeQuery to do the actions in the site
		$page = $ctx.Web.GetFileByServerRelativeUrl($pageUrl);
		$page.CheckOut()
		$ctx.ExecuteQuery()
		try{
		#Get the webpart manager from the page, to handle the webparts
		Write-Host "The page is checkout" -ForegroundColor Green
		$webpartManager = $page.GetLimitedWebPartManager([Microsoft.Sharepoint.Client.WebParts.PersonalizationScope]::Shared);
		Write-Host $WebPartXml.OuterXml
		#Load and execute the query to get the data in the webparts
		Write-Host "Getting the webparts from the page" -ForegroundColor Green
		$ctx.Load($webpartManager);
		$ctx.ExecuteQuery();
		#Import the webpart
		$wp = $webpartManager.ImportWebPart($WebPartXml.OuterXml)
		#Add the webpart to the page
		Write-Host "Add the webpart to the Page" -ForegroundColor Green
		$webPartToAdd = $webpartManager.AddWebPart($wp.WebPart, $wpZoneID, $wpZoneOrder)
		$ctx.Load($webPartToAdd);
		$ctx.ExecuteQuery()
		}
		catch{
			Write-Host "Errors found:`n$_" -ForegroundColor Red
		}
		finally{
			#CheckIn and Publish the Page
			Write-Host "Checkin and Publish the Page" -ForegroundColor Green
			$page.CheckIn("Add the User Profile WebPart", [Microsoft.SharePoint.Client.CheckinType]::MajorCheckIn)
			$page.Publish("Add the User Profile WebPart")
			$ctx.ExecuteQuery()
			Write-Host "The webpart has been added" -ForegroundColor Yellow 
		}	
	}
	catch{
		Write-Host "Errors found:`n$_" -ForegroundColor Red
	}
}

And this is the XML to add a SharePoint document library called “Documents” to the page.

$WebPartXml1 =  "
		<webParts>
			<webPart xmlns='http://schemas.microsoft.com/WebPart/v3'>
				<metaData>
				<type name='Microsoft.SharePoint.WebPartPages.XsltListViewWebPart, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' />
				<importErrorMessage>Cannot import this Web Part.</importErrorMessage>
			</metaData>
			<data>
				<properties>
					<property name='ListUrl' type='string'>Documents</property>
					<property name='ListName' type='string'>Documents</property>
				</properties>
			</data>
			</webPart>
		</webParts>"

The URL for a list is slightly different to a document library, the example below is the XML for an announcement list.

$WebPartXml1 =  "
		<webParts>
			<webPart xmlns='http://schemas.microsoft.com/WebPart/v3'>
				<metaData>
					<type name='Microsoft.SharePoint.WebPartPages.XsltListViewWebPart, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' />
					<importErrorMessage>Cannot import this Web Part.</importErrorMessage>
				</metaData>
				<data>
					<properties>
						<property name='ListUrl' type='string'>Lists/Student Announcements</property>
						<property name='ListName' type='string'>Student Announcements</property>
						<property name='JSLink' type='string'>~sitecollection/Style%20Library/cdb_custom_announcements/cdb_custom_announcements.js</property>
					</properties>
				</data>
			</webPart>
		</webParts>"

I then get the client context and pass the XML and variables to the function to add it to the page

$tenantAdmin = "user@domain.com"
$tenantAdminPassword = "password"
$secureAdminPassword = $(convertto-securestring $tenantAdminPassword -asplaintext -force)
$siteURL = "https://domain.com/sites/subsite";
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl) 
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($tenantAdmin, $secureAdminPassword)  
$ctx.Credentials = $credentials
$relUrl = "/sites/subsite"
$pageRelativeUrl1 = "/Pages/Default.aspx"
$wpZoneID1 = "Top Left"
$wpZoneOrder1 = 0
#Run function
AddWebPartToPage $ctx $relUrl $WebPartXml1 $pageRelativeUrl1 $wpZoneID1 $wpZoneOrder1

Nice example of adding web parts to a SharePoint Online publishing page using PowerShell CSOM.

Editing Office Documents Collaboratively in Office 365

If you are new to office 365 or are not aware of this, editing documents simultaneously is a great feature and surprisingly easy to use. You may be used to collaborating on documents using Office on your desktop with the files stored on shares but one of the problems in the older versions of Office was documents being locked for editing by other users. Of course if you require documents to be locked for editing, you can enable checking in and checking out of documents to get the same effect in office 365, however working collaboratively on documents now doesn’t mean you accidently save over the other persons work. Parts of the document lock to allow you to see what the other collaborators are doing in the document. This feature is available in Word, PowerPoint, Excel and OneNote files.

It’s a really exciting way to collaborate and makes working in groups much quicker than having to edit the document one by one. As a teacher you could be working on a documents together as a department rather than passing around marksheets or assessment data for each teacher to enter one at a time. It’s also great for businesses having to work on long documents which require collaboration such as proposals.

My video below demonstrates the functionality.



Adding SharePoint Online navigation from XML using PowerShell CSOM

The following PowerShell scripts were created to enable me to deploy a custom navigation across multiple site collections. You can use managed metadata navigation as mentioned in my previous post. Unfortunately this method doesn’t allow the user to reuse managed metadata navigation across multiple site collections (no idea why, I thought that was one of the advantages of managed metadata navigation!).

So a new and clean way of doing this is to use the CSOM for PowerShell. The code below deletes every navigation node using the first function and then adds each item added to an XML file. A strength of using this method is it can be manipulated to add additional logic for adding links to particular site collections depending on the variables in the XML file. Hope you find this useful.

For SharePoint design, workflows, automation, training and support please visit my SharePoint consultancy site www.clouddesignbox.co.uk. We offer education and business SharePoint solutions and services.

Deleting all navigation nodes using CSOM PowerShell

It’s fairly straightforward to enumerate nodes in an array, in this example I’m deleting all the top navigation menu nodes in a SharePoint site. This is how I would normally loop through the top navigation menu:

$topNav = $context.Web.Navigation.TopNavigationBar;
$context.Load($topNav);
foreach ($topNavItem in $topNav)
{
	Write-Host $topNavItem.Title
}

However if I want to loop through the menu and delete all the nodes, the above function errors as the array has changed each time it loops, the method below works but doesn’t catch all the menu items.

for ($ii = 0; $ii -lt $topNodes.Count; $ii++)
{
	Write-Host $topNodes[$ii].Title 
	$topNodes[$ii].deleteObject();
	$context.ExecuteQuery();
}

As we are enumerating the nodes, we are removing nodes from the start and changing the position of the other nodes in the array. As the loop continues to run, it can skip positions of some of the nodes.

A solution which works better is looping through the array backwards. As you loop through the array backwards, it doesn’t change the position of items still in the array.

for ($ii = $topNodes.Count - 1; $ii -ge 0; $ii--)
{
	Write-Host $topNodes[$ii].Title 
	$topNodes[$ii].deleteObject();
	$context.ExecuteQuery();
}

Hope you may find this useful, it can be difficult to find why the loop misses some random items and hopefully looping backwards will avoid any issues like this.