Convert an existing plain text note field/column to rich text




If you create a SharePoint site column (a note field in this case), associate it with a site content type, and then associate that content type with a list in a sub site, the site column will be available on that library. Obviously right?

However, when you update the site column (and push all changes to lists and libraries) not *all* of the changes you make are in fact pushed down. An example of this is the setting that dictates whether a note field should allow rich text or enforce plain text. If you change this setting at the site column level it will *not* propagate to libraries which already exist. New instances of the column (say if you associated the content type with a list for the first time) will be configured correctly, but existing list-level instances are not updated. NOTE: This is only true for properties specific to particular column type; common properties such as ‘required’ will be pushed down to existing instances of the column at the list level.

Configuring a SharePoint note field to support rich text
Configuring a SharePoint note field

So you want to change a list-level instance of a plain text note column to a rich text note column (or vice-versa, or otherwise change column specific properties or another field type)? You need to do it for every list where the column is in use. That would be very tedious to do via the SharePoint UI, but you can’t anyway. The UI only supports changing the set of common field properties (type, required, hidden, etc).

In comes PowerShell. Below you will find a script which updates a plain text note column to be a rich text note column. It is important to note that this script only updates the list-level columns and not the site column. This means that after running the script, new instances will continue to inherit the site column configuration.

The script takes advantage of recursion using delegate functions which is an approach I blogged about here: PowerShell Recursion with Delegate Functions

Credit also to Chris O’Brien’s topofscript.ps1 for the CSOM integration bit: Using CSOM in PowerShell scripts with Office 365

The script is written for SharePoint Online (and assumes that the SharePoint Online Client Components SDK is installed) but for this to work on-premises you would only need to update the referenced assemblies (v15 for 2013) and modify the code which passes the credentials.

# Parameters
$siteCollectionUrl = "https://<tenant>.sharepoint.com/sites/<site collection>" # UPDATE
$username = "<username>" # UPDATE

$listTitle = "Pages" # UPDATE
$fieldName = "Comments" # UPDATE

# From here on, errors should stop the script
$ErrorActionPreference = "stop"

# Utility function
function foreachDecendentWeb(
  [Parameter(Mandatory=$true)]
  [Microsoft.SharePoint.Client.Web]$web, 
  [Parameter(Mandatory=$true)]
  [Action[Microsoft.SharePoint.Client.Web]]$webAction)
{
  # Load child webs
  $context = $web.Context
  $childWebs = $web.Webs
  $context.Load($childWebs)
  $context.ExecuteQuery()
  
  # Iterate child webs
  foreach($childWeb in $childWebs)
  {
    # Perform action on child web
    $webAction.Invoke($childWeb)

    # Iterate child-child webs
    foreachDecendentWeb $childWeb $webAction
  }
}

function Prompt-Password ($username) {
  [string]$password = read-host "Provide password for $username"
  if($password.length -lt 1) {
    LogError "You must provide a password"
    Exit
  }
  return $password
}

# Work to be done at each web
[Action[Microsoft.SharePoint.Client.Web]]$updateListField = 
{
  param([Parameter(Mandatory=$true)]$web)
	
  write-host ""
  write-host "Found web: " -nonewline
  write-host "$($web.Title)" -f green
	
  # Fetch list fields
  write-host "Fetching list fields..."
  $list = $web.Lists.GetByTitle($listTitle)
  $fields = $list.Fields
  $ctx.Load($fields)
  $ctx.ExecuteQuery()

  # Find specific field
  write-host "Finding field..."
  $field = $fields | ?{$_.InternalName -eq $fieldName}

  # Update field properties
  write-host "Updating field properties..."
  $field.set_RichText($true)
  $field.set_RestrictedMode($false)
  $field.set_AllowHyperlink($true)
  $field.Update()
  $ctx.Load($field)
  $ctx.ExecuteQuery()
	
  write-host "Done!"
}

write-host "*Script: Update site description field to support rich text*"
write-host "Site collection: $siteCollectionUrl" -f green

[string]$password = Prompt-Password $username

# Import CSOM assemblies
write-host "Importing CSOM assemblies..."
Add-Type -Path "c:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll" 
Add-Type -Path "c:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll" 

# Authenticate
write-host "Authenticating to SharePoint Online..."
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteCollectionUrl)
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $securePassword) 
$ctx.Credentials = $credentials

# Perform action on root web
$rootWeb = $ctx.Web
$ctx.Load($rootWeb)
$ctx.ExecuteQuery()
$updateListField.Invoke($rootWeb)

# Perform action on every descendent web
foreachDecendentWeb $rootWeb $updateListField

write-host ""
write-host "All done!" -f green

Paul.




2 thoughts on “Convert an existing plain text note field/column to rich text”

  1. Hi Paul, thanks for posting this. I get this error in PowerShell. SharePoint Online Client Components SDK is installed.

    Unable to find type [Microsoft.SharePoint.Client.Web]: make sure that the assembly containing this type is loaded.
    At line:45 char:1
    + [Action[Microsoft.SharePoint.Client.Web]]$updateListField =
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (Microsoft.SharePoint.Client.Web:TypeName) [], ParentContainsErrorRecordExc
    eption
    + FullyQualifiedErrorId : TypeNotFound

Leave a Reply

Your email address will not be published.