Distribute a list to multiple sites or webs in SharePoint Online using Powershell DevPnP

14 augustus 2018

You might get sometimes the question to distribute a list to multiple locations. In On-Premises SharePoint you could save the list as template and use Powershell to do this with $web.Lists.Add.
However, this doesn't work in SharePoint Online..

So, how to proceed...

Make Template

Of course, same in On-Premises, create a list, make it how you want and save it as template.
After saving the template will be in the List Templates Gallery. Nothing strange there from On-Premises.

If you want to deploy this template to different Site Collections, download the file. At the end of this blog I'll let you know how to upload the template as well.

Create Provisioning template

First apply the template manually to a sample site. This makes sure we get the templates ID's in the Provisioning template
Secondly we need to create a provisioning template. Connect to the sample site with "Connect-PnPOnline -Url <URL>" and the use the PnP-cmdlet with parameters for this job: "Get-PnPProvisioningTemplate -Out template.xml".
Remove everything you don't need, but keep the basic stuff and the list you want to provision.

The XML should look like this:

When all the changes in you XML are done you can deploy them to the subsites.

Deploy template

This part is simple per subweb: Connect -> deploy -> Next.
I also wanted to break inheritance, place the new list as second item on the Quick Launch menu and set some extra permissions (when breaking inheritance, only your permissions remain).
So I created a script:

$url =  'https://contoso.sharepoint.com/sites/sitecollection'
$creds = Get-Credential -UserName "user@contoso.com"

### Connect
Connect-PnPOnline $url -Credentials $creds

$currentSubwebs = Get-PnPSubWebs -Recurse

## For each loop
foreach($site in $currentSubwebs) {
Write-host "Connecting to " $site.Title "("$site.")"
Connect-PnPOnline $site.Url -Credentials $creds
$number = $($site.ServerRelativeUrl).Remove(0, 22) #strips /sites/sitecollection/ from the relative URL, needed in the name of the groups
Apply-PnPProvisioningTemplate -Path template.xml
$nodes = Get-PnPNavigationNode -Location "QuickLaunch"
$nodes | Select-Object -First 1 | Remove-PnPNavigationNode -Force
$CL = $site.ServerRelativeUrl+"/Lists/CustomList"
Add-PnPNavigationNode -Title "Custom List" -Url $CL -Location "QuickLaunch" -First
Add-PnPNavigationNode -Title "Start" -Url $site.ServerRelativeUrl -Location "QuickLaunch" -First
Set-PnPList -Identity "Custom List" -BreakRoleInheritance
Set-PnPListPermission -Identity 'Custom List' -Group 'Super Users' -AddRole 'Full control'

The part "$currentSubwebs = Get-PnPSubWebs -Recurse" gets all the subwebs of the current site collection. Of course you can use a array, XML or file to give the URL's.
A nice other command is to use search for the correct site collections, only to be used if all the needed sites have something in common. Use this part of code:

$sites = Get-PnPSiteSearchQueryResults -Query "path:https://contoso.sharepoint.com/sites/commonname_*"


Upload List Template to different Site Collection

To upload the list template to different Site Collections, use the next bit of code.

Function Upload-ListTemplate($WebURL, $TemplateFilePath)
#Get the Web
$web = Get-SPWeb $WebURL
#Get the List template Gallery Folder
$TemplateFolder = $web.GetFolder("List Template Gallery")
#Get the Files collection
$TemplateFileCollection = $TemplateFolder.Files

#Get the Template file from Local File system
$TemplateFile = Get-ChildItem $TemplateFilePath

#Open the File in Read mode and Add to Templates collection
$TemplateFileCollection.Add("_catalogs/lt/$($TemplateFile.Name)", $TemplateFile.OpenRead(), $true)
Write-Host "Done! Template has been uploaded!!"

#Call the function to upload list template
Upload-ListTemplate "https://contoso.sharepointonline.com/sites/templatesite" "D:\Templates\CreditTemplate.stp"


Submit a comment