Continuing with the same scenario/example described in my previous post PowerShell Script to create Site Columns, here is a powershell script which creates site content types in bulk by reading the input from a list or a .csv file.
The pre-req for this script is to create site columns that will be assigned to these content types. You can use existing ones too if they are already created. In case, you wish to create empty content types without adding any site columns, please leave the "Site Columns" column blank. You will see errors in the output window when you run the script but they can be safely ignored.
So lets dive in..
As mentioned earlier; the script can read input from either a list or a .csv file. My input looks something like this. This time I went with the data list approach in contract with the creation of site columns, coz I wanted to give a group of users the ability to define what content types they wish to use for their set of documents.
You can choose to change the properties/columns as per your requirement but do not forget to tweak the code appropriately
(or)
Please note, I did not populate the Document Template column in my list entries for this example, however if you wish to do so, the input must be in the form of http://servername/sitecollectionname/subweb/documentlibrary/documentname.fileextension
# Description
# This script is
used to create content types by reading data from a SharePoint Data List.
# The data list must
have the columns
#
Content Type Name Single line of text Required
#
Group Single
line of text Optional
#
Parent Single line of text Required
#
Description Multiple lines of
text Optional
#
Read Only Yes/No Optional
#
Update Child Content Types Yes/No Optional
#
Division Choice Required
#
Site Columns Multiple lines of text Optional
#
Document Template Hyperlink or Picture Optional
# To input data from
a csv file(Optional)
# Get the CSV File location which contains the input values. Change
value in "" to match appropriate location
$inputFile = "C:\/*Folder lcoation*/\ContentTypesToBeAdded.csv"
#Import values from the CSV
$ctToBeAdded = import-csv $inputFile
# To input Data from
data list
# Get the web in which the input data list is located
$listWeb =
Get-SPWeb "/*Url of web*/"
# Get the List which stores the input values. Change the value in
"" to match appropriate list name
$list
= $listWeb.Lists["Content types to be Created"]
# Get the list items
$listItems = $list.Items
# Create an array to store the field links to all site columns that
will be added to the content type
$fieldLinksArray = @()
# for each list item in the data list, do the following
foreach($item in $listItems)
{
# Get the SPSite object for the site collection the content types
are created in
$ctToBeAddedSite
= new-Object Microsoft.SharePoint.SPSite "/*Url of Site
Collection*/"
# If the content types are created at a site collection level - Get the root web
# If the script is used for creating web content types, get the rootweb first and store in a seperate variable say "$ctToBeAddedRootWeb" and the use the Get-SPWeb cmdlet to get the url of subweb
# The reason why you need another variable to store the root web is if your parent content type is a built in content type for eg: Document, it can only be accessed from the rootweb contenttypes collection folder
# $ctToBeAddedWeb
= Get-SPWeb "/*Url of sub web*/"
# Parent content type
# Note: If you are adding the content types to a subweb, use
# $parentContentType= $ctToBeAddedRootWeb.ContentTypes[$item[$list.Fields["Parent"]]]
$parentContentType
= $ctToBeAddedWeb.ContentTypes[$item[$list.Fields["Parent"]]]
# Content Type collection the new content type will be added to
$ctToBeAddedCollection
= $ctToBeAddedWeb.ContentTypes
# Name of content type to
be added
$ctToBeAddedName = $item[$list.Fields["Content Type
Name"]]
# Names of site columns
to be added seperated by ','
$ctSiteColumns
= $item[$list.Fields["Site
Columns"]]
# When adding site
columns to a content type; reading the input from a string with values separated
by comma, for some reason, PowerShell skips the last value (still researching on this error).
# You will notice that the array
will be built with all the values in it, but the last value is always skipped when the field
links are added.
# To avoid this, my code
adds a "," at the end of the input string and treat the last value as
a blank.
# This step can be
avoided by adding a "," at the end of the string in the input list
# Check if the input
string ends with a comma, if it doesn’t append a “,” to the end of the string.
if($ctSiteColumns.EndsWith(",")
-eq $false)
{
# Append a comma at the end of the string
$ctSiteColumnsFinalString
= $ctSiteColumns + ","
}
else # Keep the input as is
{
$ctSiteColumnsFinalString
= $ctSiteColumns
}
# Store all site columns
in an array by splitting values at ","
$ctSiteColumnsArray
= $ctSiteColumnsFinalString.Split(",")
# for each site column in
the array; do the following
foreach($siteColumn in $ctSiteColumnsArray)
{
# Get the SPField object
$ctSiteColumnToBeAdded
= $ctToBeAddedWeb.Fields[$siteColumn]
# If it exists
if($ctSiteColumnToBeAdded -ne $null)
{
# Create a field link to
the site column
$fieldLink
= new-object Microsoft.SharePoint.SPFieldLink $ctSiteColumnToBeAdded
# Add it to the
field link array
$fieldLinksArray
+= ,$fieldLink
}
else # Site column does not exist
{
write-host
"The Site Column:" $siteColumn
"to be added to content type:" $ctToBeAddedName "does not exist"
}
}
# Check if the content type exists
if($ctToBeAddedWeb.ContentTypes[$item[$list.Fields["Content Type
Name"]]] -eq $null)
{
# Create a new
content type
$newContentType
= new-object
Microsoft.SharePoint.SPContentType($parentContentType,$ctToBeAddedCollection,$ctToBeAddedName)
# Add the content
type to the content type collection
$ctToBeAddedCollection.Add($newContentType)
# Set the content type properties
$newContentType.Group
= $item[$list.Fields["Group"]]
$newContentType.Description
= $item[$list.Fields["Description"]]
[boolean]$newContentType.ReadOnly
= [System.Convert]::ToBoolean($item[$list.Fields["Read
Only"]])
#Setting this
property is optional. I chose to store the documents in a separate library,
create a hyperlink column called “Document Template” in my list/.csv file and
then attach the link to the content type
$newContentType.DocumentTemplate
= $item[$list.Fields["Document
Template"]]
# Foreach field link in the array
foreach($link in $fieldLinksArray)
{
# Add the column to the new
content type
$newContentType.FieldLinks.Add($link)
}
$newContentType.Update([System.Convert]::ToBoolean($item[$list.Fields["Update Child
Content Types"]]))
}
else # Content type already exists
{
write-host "Content Type:" $item[$list.Fields["Content Type
Name"]] "already exists"
}
}
# Dispose the web and site ** Important **
$ctToBeAddedWeb.Dispose()
$listWeb.Dispose()
$ctToBeAddedSite.Dispose()
Output:
Sources:
1. Google.com