GitHub Icon Image
GitHub

Add document templates to the New dropdown in a document library

Summary

It is pretty easy to add document templates to a document library in SharePoint Online by hand, but we often have to provide those document templates as part of a provisioning solution. This script shows how to add document templates to a document library using PnP PowerShell. The most importent property in this sample is view.NewDocumentTemplates. This property is a JSON string that contains the templates that are shown in the New dropdown in the document library. I am just using a string replacement approach using [ReplaceToken] in the baseNewTemplatesAsJson string to make it easy to add the new template to the list of templates.

Example Screenshot

  • PnP PowerShell

function AddDocumentTemplateToLibrary {
    param (
        [Parameter(Mandatory=$true)]
        [string]$targetUrl,
        [Parameter(Mandatory=$true)]
        [string]$templateFileUrl,
        [Parameter(Mandatory=$true)]
        [string]$libraryName,
        [Parameter(Mandatory=$true)]
        [string]$targetContentType,
        [Parameter(Mandatory=$true)]
        [string] $templateId,
        [Parameter(Mandatory=$false)]
        [string] $baseNewTemplatesAsJson
    )
    
    #add a doucment template from another site to the library using the NewDocumentTemplates 

    #in this case I assume that you want to create the library if it does not exist
    $list = Get-PnPList -Identity $libraryName -Connection $targetConn -ErrorAction SilentlyContinue
    if($null -eq $list)
    {
        New-PnPList -Title $libraryName -Template DocumentLibrary -Connection $targetConn
        $list = Get-PnPList -Identity $libraryName -Connection $targetConn
    }
      

    #add the document template to the librarys Forms folder
    if($templateFileUrl)
    {
        $targettemplateFileUrl = $targetConn.Url + "/$libraryName/Forms/"+ $templateFileUrl.Split("/")[-1]

        #we can't be sure if the URL is using "sites" or "teams" so we need to check for both
        if($templateFileUrl.IndexOf("/sites/") -gt -1)
        {
            $relativetemplateFileUrl = $templateFileUrl.Substring($templateFileUrl.IndexOf("/sites/"))
        }
        else 
        {
            if($templateFileUrl.IndexOf("/teams/") -gt -1)
            {
                $relativetemplateFileUrl = $templateFileUrl.Substring($templateFileUrl.IndexOf("/teams/"))
            }   
            else 
            {
                throw "The template file URL does not contain /sites/ or /teams/"
            }
            
        }
        
        #check if the file already exists in the library
        $file = Get-PnPFile -Url $targettemplateFileUrl -Connection $targetConn -AsFileObject -ErrorAction SilentlyContinue
        if(-not $file)
        {
            $localeTemplateContainer = "$($targetConn.Url)/$libraryName/Forms"
            Copy-PnPFile -SourceUrl $relativetemplateFileUrl -TargetUrl $localeTemplateContainer -Connection $targetConn -Force -ErrorAction Stop
            #I have seen that the file is not always available immediately after the copy, so we need to retry a few times
            $retryindex = 0
            while($retryindex -lt 5 -and -not $file)
            {
                Start-Sleep -Seconds 5
                $file = Get-PnPFile -Url $targettemplateFileUrl -Connection $targetConn -AsFileObject -ErrorAction SilentlyContinue
                $retryindex++
            }
            
            if(-not $file)
            {
                throw "Failed to copy the template file to the library"                
            }
        }             
    }

    $view = Get-PnPView -List $list -Connection $targetConn | Where-Object { $_.DefaultView -eq $true }
    #if no value is provided for the baseNewTemplatesAsJson, then use the default value
    if($baseNewTemplatesAsJson -eq $null -or $baseNewTemplatesAsJson -eq "")
    {
        $existingTemplates = $view.NewDocumentTemplates
        #feel free to add or remove templates to the list
        $baseNewTemplatesAsJson = '[{"visible":true,"title":"Folder","isFolder":false,"iconProps":{"iconName":"folder16_svg","className":"newDocumentCommandIcon_4913fd57"},"templateId":"NewFolder","order":0},{"visible":true,"title":"Word document","isFolder":false,"iconProps":{"iconName":"docx16_svg","aria-label":"docx","className":"newDocumentCommandIcon_4913fd57"},"templateId":"NewDOC","order":1},{"visible":true,"title":"Excel workbook","isFolder":false,"iconProps":{"iconName":"xlsx16_svg","aria-label":"xlsx","className":"newDocumentCommandIcon_4913fd57"},"templateId":"NewXSL","order":2},{"visible":true,"title":"PowerPoint presentation","isFolder":false,"iconProps":{"iconName":"pptx16_svg","aria-label":"pptx","className":"newDocumentCommandIcon_4913fd57"},"templateId":"NewPPT","order":3},{"visible":true,"title":"OneNote notebook","isFolder":false,"iconProps":{"iconName":"onetoc16_svg","aria-label":"onetoc","className":"newDocumentCommandIcon_4913fd57"},"templateId":"NewONE","order":4},{"visible":true,"title":"Excel survey","isFolder":false,"iconProps":{"iconName":"xlsx16_svg","aria-label":"xlsx","className":"newDocumentCommandIcon_4913fd57"},"templateId":"NewXSLSurvey","order":5},{"visible":true,"title":"Forms for Excel","isFolder":false,"iconProps":{"iconName":"xlsx16_svg","aria-label":"xlsx","className":"newDocumentCommandIcon_4913fd57"},"templateId":"NewXSLForm","order":6},{"visible":true,"title":"Visio drawing","isFolder":false,"iconProps":{"iconName":"vsdx16_svg","aria-label":"vsdx","className":"newDocumentCommandIcon_4913fd57"},"templateId":"NewVSDX","order":7}[ReplaceToken]]'
    }
    #get the ID of List Conten type for Document
    $ct = Get-PnPContentType -List $list -Connection $targetConn | Where-Object { $_.Name -eq $targetContentType }
    if($null -eq $ct)
    {
        throw "Failed to find the content type $targetContentType in the list $libraryName" 
    }
    $replacer = ',{"contentTypeId":"'+ $($ct.Id.StringValue) +'","isUpload":true,"templateId":"'+ $templateId +'","title":"'+ $templateId+'","url":"'+$targettemplateFileUrl+'","visible":true}'
    
    if($existingTemplates -ne $null)
    {
        $index = $existingTemplates.LastIndexOf("]")
        $baseNewTemplatesAsJson = $existingTemplates.Substring(0, $index) + "[ReplaceToken]]"
        
    }
    $newtemplatesAsJson = $baseNewTemplatesAsJson -replace "\[ReplaceToken\]", $replacer
    
    $view.NewDocumentTemplates = $newtemplatesAsJson
    $view.Update()
    Invoke-PnPQuery -Connection $targetConn
    
}

$libraryName = "Docs2"
$targetUrl = "https://contoso.sharepoint.com/sites/site1"
$templateFileUrl = "https://contoso.sharepoint.com/sites/GlobalTemplateSite/SiteAssets/PnP Modern Search Q.docx"

if($targetConn -eq $null)
{
    $targetConn = Connect-PnPOnline -Url $targetUrl -Interactive -ReturnConnection -ClientId "your id"
}

if($sourceConn -eq $null)
{
    $sourceConn = Connect-PnPOnline -Url $templateFileUrl -Interactive -ReturnConnection -ClientId "your id"
}

AddDocumentTemplateToLibrary -targetUrl $targetUrl -templateFileUrl $templateFileUrl -templateId "PnP Modern Search Q" -libraryName $libraryName -targetContentType "Document" 

$templateFileUrl = "https://contoso.sharepoint.com/sites/GlobalTemplateSite/SiteAssets/Building%20Blocks.dotx"
AddDocumentTemplateToLibrary -targetUrl $targetUrl -templateFileUrl $templateFileUrl -templateId "Building Blocks" -libraryName $libraryName -targetContentType "Document" 

$templateFileUrl = "https://contoso.sharepoint.com/sites/somesite/Shared%20Documents/Fejl.docx"
AddDocumentTemplateToLibrary -targetUrl $targetUrl -templateFileUrl $templateFileUrl -templateId "Fejl" -libraryName $libraryName -targetContentType "Document" 




Check out the PnP PowerShell to learn more at: https://aka.ms/pnp/powershell

The way you login into PnP PowerShell has changed please read PnP Management Shell EntraID app is deleted : what should I do ?

Contributors

Author(s)
Kasper Larsen

Disclaimer

THESE SAMPLES ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.

Back to top Script Samples
Generated by DocFX with Material UI