SharePoint Online: Change Content Type of List Items using PowerShell

Requirement: Change Content Type of All Items in a SharePoint Online List.

How to Change the Content Type in SharePoint Online?

If you’re looking to change the content type of list items or files in SharePoint Online, there are a few steps you’ll need to take. This guide will show you how to make the switch using the web browser interface easily, and I’ll show you how to use PowerShell to change the content type!

You can change the content type of existing list items by editing the particular item and switching the “Content Type” field.

sharepoint online change content type powershell

Well, let’s bulk change content type in SharePoint Online with PowerShell.

Before changing the content type of list items, You must add the content type to the list first: How to Add a Content Type to List in SharePoint Online using PowerShell?

Change Content type in SharePoint Online using PowerShell:

Let us change the content type “Crescent Project V1” with “Crescent Project V2” for all list items (whichever item using the content type “Crescent Project V1”).

#Load SharePoint 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"

#Function to Change the Content Type of All Items in SharePoint Online list using powershell
Function Change-SPOContentType
{
    param
    (
        [string]$SiteURL  = $(throw "Enter the Site URL!"),
        [string]$ListName = $(throw "Enter the List Name!"),
        [string]$OldContentTypeName = $(throw "Enter the Old Content Type Name!"),
        [string]$NewContentTypeName = $(throw "Enter the New Content Type Name!")
    )
    Try {
        #Get Credentials to connect
        $Cred= Get-Credential
 
        #Setup the context
        $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
        $Ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password)

        #Get the Web
        $Web = $Ctx.Web
        $Ctx.Load($Web)
        $Ctx.ExecuteQuery()
        
        #Get the List & and content types
        $List = $Web.lists.GetByTitle($ListName)
        $ContentTypes = $List.ContentTypes
        $Ctx.Load($List)
        $Ctx.Load($ContentTypes)
        $Ctx.ExecuteQuery()

        #Get the content type to Update
        $OldContentType = $ContentTypes | Where {$_.Name -eq $OldContentTypeName}
        $NewContentType = $ContentTypes | Where {$_.Name -eq $NewContentTypeName}

        If($NewContentType -eq $Null)
        {
            Write-Host "Content Type '$NewContentTypeName' doesn't Exist in the list. Add the Content Type to the List First!" -ForegroundColor Yellow
            Return
        }

        #Define Query to get List Items in batch
        $Query = New-Object Microsoft.SharePoint.Client.CamlQuery
        $Query.ViewXml = "@
        <View Scope='RecursiveAll'>
            <Query>
                <OrderBy><FieldRef Name='ID' Ascending='TRUE'/></OrderBy>
            </Query>
            <RowLimit Paged='TRUE'>$BatchSize</RowLimit>
        </View>
        @"

        $Counter = 1
        $BatchCounter = 0
        #Get List Items in Batch
        Do
        {
            $ListItems = $List.GetItems($Query)
            $Ctx.Load($ListItems)
            $Ctx.ExecuteQuery()
            $Query.ListItemCollectionPosition = $ListItems.ListItemCollectionPosition
            $Ctx.ExecuteQuery()
            $BatchCounter += $ListItems.Count

            #Get All List Items with Old Content Type
            $ItemsToUpdate = $ListItems | Where {$_["ContentTypeId"].StringValue -eq ($OldContentType.ID)}
            Write-host "Number of Items Found with Old Content Type in the Batch ($Counter to $BatchCounter):" $ItemsToUpdate.count
            $Counter = $BatchCounter

            If($ItemsToUpdate.count -gt 0)
            {
                #Iterate through each item with old content type and update the conent type
                ForEach($Item in $ItemsToUpdate)
                {
                    $Item["ContentTypeId"]  = $NewContentType.Id
                    $Item.Update()
                    Write-host "Content Type Update Quued for List Item ID: $($Item.ID)" -ForegroundColor yellow
                }
                $Ctx.ExecuteQuery()
                write-host "Content Types Updated Successfully!" -ForegroundColor  Green
            }
        }While($Query.ListItemCollectionPosition -ne $null)
    }
    Catch {
        write-host -f Red "Error Changing Content Type!" $_.Exception.Message
    }
}

#Variables
#Set Variables
$SiteURL = "https://crescent.sharepoint.com/sites/pmo"
$ListName ="Projects"
$OldContentTypeName= "Crescent Project V1"
$NewContentTypeName= "Crescent Project V2"
$BatchSize = 500

#Call the function to Change the content type
Change-SPOContentType -SiteURL $SiteURL -ListName $ListName -OldContentTypeName $OldContentTypeName -NewContentTypeName $NewContentTypeName 

This PowerShell changes the content type programmatically for all items in the SharePoint Online list. This can be useful if you need to change the content type of files already in your SharePoint site.

SharePoint Online: Change Content Type using PnP PowerShell

Here is how to change content type in SharePoint Online with PowerShell PnP Module:

#Set Variables
$SiteURL = "https://crescent.sharepoint.com/sites/projects"
$ListName = "Project Proposal"
$OldContentTypeName = "Crescent Proposal V1"
$NewContentTypeName = "Crescent Project Proposal V2"

#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -Interactive

#Get the New Content Type from the List
$NewContentType = Get-PnPContentType -List $ListName | Where {$_.Name -eq $NewContentTypeName}

#Get List Items of Old content Type
$ListItems = Get-PnPListItem -List $ListName -Query "<View><Query><Where><Eq><FieldRef Name='ContentType'/><Value Type='Computed'>$OldContentTypeName</Value></Eq></Where></Query></View>"
Write-host "Total Number of Items with Old Content Type:"$ListItems.count

ForEach($Item in $ListItems)
{
    #Change the Content Type of the List Item
    Set-PnPListItem -List $ListName -Identity $Item -ContentType $NewContentType
}

While the above script works perfectly fine for lists and libraries with less than 5000 items, the “PageSize” parameter has no effect when combined with the “Query” parameter of Get-PnPListItem cmdlet and gets “Get-PnPListItem : The attempted operation is prohibited because it exceeds the list view threshold.” error. So, Here is the PowerShell script to handle larger lists:

Let me show you how to use PnP PowerShell to change the content type of list items in SharePoint Online:

#Set Variables
$SiteURL = "https://crescent.sharepoint.com/sites/projects"
$ListName = "Project Proposal"
$OldContentTypeName = "Crescent Proposal V1"
$NewContentTypeName = "Crescent Project Proposal V2"

#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -Interactive
$List =  Get-PnPList -Identity $ListName

#Get the Old and New Content Types from the List
$OldContentType = Get-PnPContentType -List $ListName | Where {$_.Name -eq $OldContentTypeName}
$NewContentType = Get-PnPContentType -List $ListName | Where {$_.Name -eq $NewContentTypeName}

#Get List Items of old content type from the list
$global:counter = 0;
$ListItems = Get-PnPListItem -List $List -PageSize 500 -Fields ContentTypeId -ScriptBlock { Param($items) $global:counter += $items.Count; Write-Progress -PercentComplete `
              ($global:Counter / ($List.ItemCount) * 100) -Activity "Getting Items from List" -Status "Checking Items $global:Counter to $($List.ItemCount)"} | Where {$_.FieldValues.ContentTypeId.ToString() -eq $OldContentType.StringId}

Write-host "Total Number of Items with Old Content Type Found:"$ListItems.count
#Loop through List Items
ForEach($Item in $ListItems)
{
    #Change the Content Type of the List Item
    Set-PnPListItem -List $ListName -Identity $Item -ContentType $NewContentType | Out-Null
    Write-host "Content Type Updated for List Item ID $($Item.ID)!" -f Green
}

Salaudeen Rajack

Salaudeen Rajack is a SharePoint Architect with Two decades of SharePoint Experience. He loves sharing his knowledge and experiences with the SharePoint community, through his real-world articles!

4 thoughts on “SharePoint Online: Change Content Type of List Items using PowerShell

  • If my list is having more than 5000 items the query is throwing list item threshold and not able to get items. How to make this above script to work for list with more than 5000 items.

    Reply
    • I’m having the same question how to get it working with more than 5000 items?

      Reply
      • Post updated with the CSOM & PnP PowerShell scripts to handle larger lists and Libraries.

        Reply
      • Thank you for the updated version, works like a charm now 🙂

        Reply

Leave a Reply