Velin Georgiev Blog

Provision custom list with SharePoint PnP PowerShell

SharePoint modern list experience

At the moment users with Edit or higher permissions can add fields to a SharePoint modern list from the UI with just one click. However, adding field like that generates new field with random internal names. This makes the developer work hard later if that field has to be accessed from a custom code. So if you are an IT pro or developer don't do it from the UI. I know, I just made it more complex, but this can save some work in long term.

What is SharePoint site column and SharePoint list field?

Site column is reusable column definition, or template, that you can assign to multiple lists across multiple SharePoint lists created at site level. So it is like template for field where you have to create the template first in the root site and later add new field instance based on that template in a list or multiple lists. Here is a good definition for SharePoint site column

I will refer to list field as field created as new instance directly in the list not based on template or definition. That is also possible, but it is bound to that list and cannot be reused. This is how a field can be created, but I do not consider it as good practice.

List field created without site column definition is not a bad think, although I would not recommend it. A really bad practice is creating a list field from the UI and later try to use it in programs.

Good practices for provisioning a new SharePoint list

Part of the information architecture for SharePoint was to structure correctly the metadata. That means to have site columns instead of list fields, to have content types that bundle site columns in a business object and then add the content type to the new list. This gives good understanding about the business value of the metadata added to the list, also gives us clean field internal names that developer can use and also gives us the power to explicitly specify ids for the fields, content types and use them later in a custom solution.

Use SharePoint provisioning technique to create the fields and list

There are many ways to provision SharePoint components. The SharePoint PnP provisioning engine is one option and it provides C#, PowerShell and XML definition ways to provision stuff. Here is one technique how this can be done with relatively small effort i.e. use the SharePoint PnP PowerShell cmdlets.

Connect-PnPOnline -Url -Credentials xxx

Add-PnPField -DisplayName 'Bookmark Url' -InternalName BookmarkUrl -Type URL -Id a1ae949b-9177-44e0-8353-40238f55efe9 -Group 'MyGroup' -Required -ErrorAction Continue
Add-PnPField -DisplayName 'Bookmark Icon' -InternalName BookmarkIcon -Id fecc7c78-0be9-49c7-8364-29b71420aca8 -Group 'MyGroup' -Type Choice -Choices Clock,Money -Required -ErrorAction Continue

Add-PnPContentType -Name 'Bookmark' -ContentTypeId 0x01001409de18cddb413ba33e41bedaa89133 -Group 'MyGroup' -ErrorAction Continue
$bookmarkBase = Get-PnPContentType -Identity 'Bookmark'

Add-PnPFieldToContentType -Field BookmarkUrl -ContentType $bookmarkBase
Add-PnPFieldToContentType -Field BookmarkIcon -ContentType $bookmarkBase

New-PnPList -Title 'Bookmarks' -Template GenericList -Url Lists/Bookmarks -ErrorAction Continue
$bookmarksList = Get-PnPList -Identity Lists/Bookmarks

Set-PnPList -Identity 'Bookmarks' -EnableContentTypes $true -EnableVersioning $true -MajorVersions 100
Add-PnPContentTypeToList -List $bookmarksList -ContentType $bookmarkBase -DefaultContentType
Add-PnPView -List $bookmarksList -Title Bookmarks -SetAsDefault -Fields Title,BookmarkUrl,BookmarkIcon

Follow up on the provisioning script

The script would connect to your SharePoint site, create two site column definitions, create one content type, add the site columns to the content type and then create new list and add the content type to the list therefore the fields would exist in the list. Also adds new view with the fields included in the view.

This is simple, fast and convenient way to provision SharePoint components the right way. In a case of a rollback, something like that can be used, but be careful. If there is already data added to the list below script will delete the list.

Remove-PnPList -Identity 'Bookmarks' -Force
Remove-PnPContentType -Identity 'Bookmark' -Force
Remove-PnPField -Identity BookmarkUrl -Force
Remove-PnPField -Identity BookmarkIcon -Force


If you are new to SharePoint, have a look at the PnP provisioning engine, because there are way to many things around the SharePoint information architecture and topology that might not be known to you and they might be learned the hard way if some good practices are not followed.