Wednesday 24 June 2015

Update the Choices of an Office 365 or SharePoint Choice Field using PowerShell and CSOM

Today I needed to update some SharePoint Choice fields with new values using PowerShell and CSOM. To my surprise, I didn't find much on the web about doing this, hence this post!

The code is pretty rudimentary, but hopefully you get the picture! The example is for an Office 365 site, but it works the same with SharePoint on premises, except that you need to pass in a different credential object (see the commented code).

#Add the Client dll's
Add-Type -Path 'C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll' -EA 0
Add-Type -Path 'C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll' -EA 0

#Set some variables
$url = "https://sometenant.sharepoint.com/sites/somesite"
$listTitle = "ListWithSomeFields"

#Create the credentials
$username = Read-Host -Prompt "Enter your password" 
$securePassword  = Read-Host -Prompt "Enter your password" -AsSecureString
#Create the credential for Office 365
$O365Credential = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $securePassword)
#If you're doing this on SharePoint on premises, then you need to create the credential like this:
$onPremCredential = Get-Credential -Message "Enter your SharePoint on-premises credentials"

$ctx = new-object Microsoft.SharePoint.Client.ClientContext($url)
$ctx.Credentials = $O365Credential;
$ctx.RequestTimeout = "500000"; 

#Load the site and web that contains the field
$Site = $ctx.Site
$ctx.Load($Site)
$ctx.ExecuteQuery()
$rootWeb = $Site.RootWeb
$ctx.Load($rootWeb)
$ctx.ExecuteQuery()

#Get the list that the field exists on
$list = $rootWeb.Lists.GetByTitle($listTitle);
$ctx.Load($list);
$ctx.ExecuteQuery()

#Get the fields collection from the list (or from the web)
$FieldCollection = $list.Fields
$ctx.Load($FieldCollection)
$ctx.ExecuteQuery()

#Get a reference to the field
$field = $FieldCollection.GetByInternalNameOrTitle("MySingleChoiceField");
$ctx.Load($field);
$ctx.ExecuteQuery();

#Define your choices
$choices = @("Fred","Barney","Wilma");
#"CAST" the field to a Microsoft.SharePoint.Client.FieldMultiChoice
#This works the same whether the field you're updating is a single or multi choice field
$choiceField = New-Object Microsoft.SharePoint.Client.FieldMultiChoice($ctx, $field.Path)
#Load the Multichoicefield
$ctx.Load($choiceField);
$ctx.ExecuteQuery();
$choiceField.Choices.Clear()
$choiceField.Choices = $choices            
$choiceField.UpdateAndPushChanges($true);
$ctx.ExecuteQuery();