Programmatically change the New Menu in SharePoint Online using PowerShell

Back in October 2018 Microsoft changed the way the New menu on a document library worked. You can now edit what is shown in the New menu directly from the library.

I needed to know how to do this in code, and it looked like PNP automatically does this for you. After doing a get-pnpprovisioningtemplate, when you look at the list you will see a XML element called NewDocumentTemplates, which has a JSON formatted string. The property NewDocumentTemplates exists on the view of the list. This made me think that you could have different menu items for different views, but this doesn’t seem to be the case.

{"contentTypeId":"0x0101009348E1CE5767914598D327EAE7EB97D500245281855DF00844BF9BD64ADD983B7D","isContentType":true,"templateId":"0x0101009348E1CE5767914598D327EAE7EB97D500245281855DF00844BF9BD64ADD983B7D","title":"CF New Request","visible":true},
{"templateId":"NewDOC","title":"Word document","visible":true},
{"templateId":"NewXSL","title":"Excel workbook","visible":true},
{"templateId":"NewPPT","title":"PowerPoint presentation","visible":true},
{"templateId":"NewONE","title":"OneNote notebook","visible":true},
{"templateId":"NewXSLForm","title":"Forms for Excel","visible":true},

Now this seems to work, when applying it back to the same list. However, I found that if I set my own content types with visible to false, and then tried on a different list that did have that content type, it didn’t hide it.

So why not?

The reason is because the contentTypeId it is expecting, is the ListContentTypeId, not the actual ContentTypeId. For each list, the ListContentTypeId will be different.

When you add a site content type to a list:

“SharePoint list makes a local copy of the site content type and adds the copy to the content type collection on the list. The new list content type is a child of the site content type. The value of the Id property for the list content type is different from the value of the Id property for its parent site content type, but otherwise the two content types are initially the same.”

I’m sure PNP will pick up on this and update the code at some point.

PowerShell script

I decided to write my own PowerShell script to solve this issue. First, I needed to understand the JSON format. For the built in Microsoft menu items the JSON looks as follow:

  "title": "Word Document",
  "templateId": "NewDOC",
  "visible": true

There are quite a few built in ones, and from using PNP to export out, I was able to find what they were called. (If you find out any more, that I don’t have listed here please let me know.)

  • TemplateId – Name
  • NewFolder – Folder
  • NewDOC – Word Document
  • NewXSL – Excel workbook
  • NewPPT – PowerPoint presentation
  • NewONE – OneNote notebook
  • NewVSDX – Visio drawing
  • NewXSLForm – Forms for Excel
  • Link – Link

Note: If you don’t have a license for Visio, or do not have Forms enabled for your E3 license, then the menu item will not show up anyway.

The JSON format for content types are the following:

  "title": "<Content Type Name>",
  "templateId": "<ListContentTypeID>",
  "visible": <true/false>,
  "contentTypeId": "<ListContentTypeID>",
  "isContentType": <true/false>

Below is my function script. Set-ListNewMenuItems.ps1 With this script you can hide any content types/default menu items by using the titles.

-Url:’; -ListTitle:’Documents’ -ContentTypesToHide:’OneNote notebook’,’PowerPoint’,’Custom CT Name’

You can also hide all default menu items, and let your content types show. It will still show links and folder.

-Url:’; -ListTitle:’Documents’ -HideDefault:$true

If you want to hide link and folder too, you would need to include their names in the ContentTypesToHide.

-Url:’; -ListTitle:’Documents’ -ContentTypesToHide:’Folder’,’Link’ -HideDefault:$true

Set the New Menu on a document library.
Sets the New Menu on a document libary, allow you to hide content types you don't want to show. This will grab all list content types currently assigned to the library.
Default Content Types used by Microsoft 'Folder', 'Word document', 'Excel workbook', 'PowerPoint presentation', 'OneNote notebook' 'Visio drawing', 'Link'
Updates the SharePoint library New Menu, but hiding given Content Types.
-Url:'; -ListTitle:'Documents' -ContentTypesToHide:'OneNote notebook','PowerPoint','Custom CT Name'
Updates the SharePoint library New Menu, but hiding Default Content Types ('Word document', 'Excel workbook', 'PowerPoint presentation', 'OneNote notebook' 'Visio drawing')
-Url:'; -ListTitle:'Documents' -HideDefault:$true
Updates the SharePoint library New Menu, but hiding Default Content Types ('Word document', 'Excel workbook', 'PowerPoint presentation', 'OneNote notebook' 'Visio drawing') and given Content Types
-Url:'; -ListTitle:'Documents' -ContentTypesToHide:'OneNote notebook','Link' -HideDefault:$true
# The url to the site containing the Site Requests list
$HideDefault = $false
function Add-MenuItem() {
$newChildNode = New-Object System.Object
$newChildNode | Add-Member type NoteProperty name title value:$title
$newChildNode | Add-Member type NoteProperty name visible value:$visible
$newChildNode | Add-Member type NoteProperty name templateId value:$templateId
if ($null -ne $contentTypeId) {
$newChildNode | Add-Member type NoteProperty name contentTypeId value:$contentTypeId
$newChildNode | Add-Member type NoteProperty name isContentType value:$true
return $newChildNode
function Get-DefaultMenuItems() {
$DefaultMenuItems = @()
$DefaultMenuItems += Add-MenuItem title:"Folder" templateId:"NewFolder" visible:$true
$DefaultMenuItems += Add-MenuItem title:"Word document" templateId:"NewDOC" visible:$true
$DefaultMenuItems += Add-MenuItem title:"Excel workbook" templateId:"NewXSL" visible:$true
$DefaultMenuItems += Add-MenuItem title:"PowerPoint presentation" templateId:"NewPPT" visible:$true
$DefaultMenuItems += Add-MenuItem title:"OneNote notebook" templateId:"NewONE" visible:$true
$DefaultMenuItems += Add-MenuItem title:"Visio drawing" templateId:"NewVSDX" visible:$true
$DefaultMenuItems += Add-MenuItem title:"Forms for Excel" templateId:"NewXSLForm" visible:$true
$DefaultMenuItems += Add-MenuItem title:"Link" templateId:"Link" visible:$true
return $DefaultMenuItems
function Set-NewMenuOnList() {
Connect-PnPOnline Url:$URL UseWebLogin
Write-Host "Connected to URL:$Url" ForegroundColor Green
$list = Get-PnpList Identity:$ListTitle
Write-Host "Connected to List:$($list.Title)"
$listContentTypes = Get-PnPContentType List $List
$defaultView = Get-PnpView List:$List | Where-Object {$_.DefaultView -eq $true}
$MenuItems = Get-DefaultMenuItems
$listContentTypes | ForEach-Object {
$ct = $PSItem
if($ct.Name -eq "Folder"){
$MenuItems += Add-MenuItem title:$ct.Name visible:$true templateId:$ct.StringId contentTypeId:$ct.StringId
$hideContentType = $ContentTypesToHide;
if($HideDefault -eq $true){
write-host "Hiding default content types"
$hideContentType += 'Word document', 'Excel workbook', 'PowerPoint presentation', 'OneNote notebook','Visio drawing'
}else {
write-host "Including default content types"
$MenuItems | ForEach-Object {
if ($hideContentType -contains ($_.title)) {
$_.visible = $false
write-host "Hiding content type $($_.title)" ForegroundColor Yellow
else {
write-host "Showing $($_.title)" ForegroundColor Green
$defaultView.NewDocumentTemplates = $menuItems | ConvertTo-Json
Write-Host "Updated $($list.Title)"
Set-NewMenuOnList URL:$URL ListTitle:$ListTitle ContentTypesToHide:$ContentTypesToHide HideDefault:$HideDefault

After running my script to remove Document, OneNote notebook, Word Document and Forms For Excel

-Url:’; -ListTitle:’Documents’ -ContentTypesToHide:’Document’,’OneNote notebook’,’Word Document’,’Forms For Excel’ -HideDefault:$false

As you can see from above, it states that it is Showing Visio drawing. However, on my tenant I do not have a license for it. Below shows you how my New menu has been updated.

The code isn’t perfect, and could do with improvements such as ordering. Please feel free to use it.

One thought on “Programmatically change the New Menu in SharePoint Online using PowerShell

  1. Pingback: ICYMI: PowerShell Week of 29-March-2019 |

Comments are closed.