Even though we now have the new Content Type Hub feature introduced in SharePoint Server 2010 for propagating columns and content types across all site collections in the farm, it can still be useful to export site columns from one site collection and import them into another. For example:
- When using SharePoint Foundation, where the Content Type Hub feature doesn’t exist
- Deploying a production environment with site columns created on a separate development or staging farm
- Keeping a record of the site columns created in a site collection for documentation or governance purposes
With PowerShell, we can use the column schema from a source site collection in SharePoint to generate an XML file, which can then be used to import the site columns into another site collection.
For this example I have created the following site columns under the “Custom Columns” group in my development site collection:
The PowerShell script below will export these site columns to an XML file called Script-SiteColumns.xml in the C:\Install folder. Note that the script looks at the group called “Custom Columns” to ensure columns created by a standard SharePoint installation are not included in the export. You will need to ensure that appropriate custom group name(s) are specified in your script when exporting:
$sourceWeb = Get-SPWeb http://portal
$xmlFilePath = "C:\Install\Script-SiteColumns.xml"#Create Export Files
New-Item $xmlFilePath -type file -force#Export Site Columns to XML file
Add-Content $xmlFilePath "<?xml version=`"1.0`" encoding=`"utf-8`"?>"
Add-Content $xmlFilePath "`n<Fields>"
$sourceWeb.Fields | ForEach-Object {
if ($_.Group -eq "Custom Columns") {
Add-Content $xmlFilePath $_.SchemaXml
}
}
Add-Content $xmlFilePath "</Fields>"$sourceWeb.Dispose()
This script will generate an XML file similar to the one shown below.
Once you have the XML file, it can be used to import columns into another site collection by using the script below. The first part of the script gets the destination Web URL and exported XML file:
$destWeb = Get-SPWeb http://portal/sites/migrationtest
$installPath = "C:\Install"
#Get exported XML file
$fieldsXML = [xml](Get-Content($installPath + "\Script-SiteColumns.xml"))
The final part of the script cycles through each field specified in the XML file, the properties associated with each column type, and then creates the column in the destination site. Whilst I have included the majority of properties associated with each type of site column (e.g., MaxLength, EnforceUniqueValues, Sortable, etc.), there may still be some properties you need to add yourself as I haven’t tested the script with every column type available in SharePoint:
$fieldsXML.Fields.Field | ForEach-Object {
#Configure core properties belonging to all column types
$fieldXML = '<Field Type="' + $_.Type + '"
Name="' + $_.Name + '"
ID="' + $_.ID + '"
Description="' + $_.Description + '"
DisplayName="' + $_.DisplayName + '"
StaticName="' + $_.StaticName + '"
Group="' + $_.Group + '"
Hidden="' + $_.Hidden + '"
Required="' + $_.Required + '"
Sealed="' + $_.Sealed + '"'
#Configure optional properties belonging to specific column types – you may need to add some extra properties here if present in your XML file
if ($_.ShowInDisplayForm) { $fieldXML = $fieldXML + "`n" + 'ShowInDisplayForm="' + $_.ShowInDisplayForm + '"'}
if ($_.ShowInEditForm) { $fieldXML = $fieldXML + "`n" + 'ShowInEditForm="' + $_.ShowInEditForm + '"'}
if ($_.ShowInListSettings) { $fieldXML = $fieldXML + "`n" + 'ShowInListSettings="' + $_.ShowInListSettings + '"'}
if ($_.ShowInNewForm) { $fieldXML = $fieldXML + "`n" + 'ShowInNewForm="' + $_.ShowInNewForm + '"'}
if ($_.EnforceUniqueValues) { $fieldXML = $fieldXML + "`n" + 'EnforceUniqueValues="' + $_.EnforceUniqueValues + '"'}
if ($_.Indexed) { $fieldXML = $fieldXML + "`n" + 'Indexed="' + $_.Indexed + '"'}
if ($_.Format) { $fieldXML = $fieldXML + "`n" + 'Format="' + $_.Format + '"'}
if ($_.MaxLength) { $fieldXML = $fieldXML + "`n" + 'MaxLength="' + $_.MaxLength + '"' }
if ($_.FillInChoice) { $fieldXML = $fieldXML + "`n" + 'FillInChoice="' + $_.FillInChoice + '"' }
if ($_.NumLines) { $fieldXML = $fieldXML + "`n" + 'NumLines="' + $_.NumLines + '"' }
if ($_.RichText) { $fieldXML = $fieldXML + "`n" + 'RichText="' + $_.RichText + '"' }
if ($_.RichTextMode) { $fieldXML = $fieldXML + "`n" + 'RichTextMode="' + $_.RichTextMode + '"' }
if ($_.IsolateStyles) { $fieldXML = $fieldXML + "`n" + 'IsolateStyles="' + $_.IsolateStyles + '"' }
if ($_.AppendOnly) { $fieldXML = $fieldXML + "`n" + 'AppendOnly="' + $_.AppendOnly + '"' }
if ($_.Sortable) { $fieldXML = $fieldXML + "`n" + 'Sortable="' + $_.Sortable + '"' }
if ($_.RestrictedMode) { $fieldXML = $fieldXML + "`n" + 'RestrictedMode="' + $_.RestrictedMode + '"' }
if ($_.UnlimitedLengthInDocumentLibrary) { $fieldXML = $fieldXML + "`n" + 'UnlimitedLengthInDocumentLibrary="' + $_.UnlimitedLengthInDocumentLibrary + '"' }
if ($_.CanToggleHidden) { $fieldXML = $fieldXML + "`n" + 'CanToggleHidden="' + $_.CanToggleHidden + '"' }
if ($_.List) { $fieldXML = $fieldXML + "`n" + 'List="' + $_.List + '"' }
if ($_.ShowField) { $fieldXML = $fieldXML + "`n" + 'ShowField="' + $_.ShowField + '"' }
if ($_.UserSelectionMode) { $fieldXML = $fieldXML + "`n" + 'UserSelectionMode="' + $_.UserSelectionMode + '"' }
if ($_.UserSelectionScope) { $fieldXML = $fieldXML + "`n" + 'UserSelectionScope="' + $_.UserSelectionScope + '"' }
if ($_.BaseType) { $fieldXML = $fieldXML + "`n" + 'BaseType="' + $_.BaseType + '"' }
if ($_.Mult) { $fieldXML = $fieldXML + "`n" + 'Mult="' + $_.Mult + '"' }
if ($_.ReadOnly) { $fieldXML = $fieldXML + "`n" + 'ReadOnly="' + $_.ReadOnly + '"' }
if ($_.FieldRef) { $fieldXML = $fieldXML + "`n" + 'FieldRef="' + $_.FieldRef + '"' }$fieldXML = $fieldXML + ">"
#Create choices if choice column
if ($_.Type -eq "Choice") {
$fieldXML = $fieldXML + "`n<CHOICES>"
$_.Choices.Choice | ForEach-Object {
$fieldXML = $fieldXML + "`n<CHOICE>" + $_ + "</CHOICE>"
}
$fieldXML = $fieldXML + "`n</CHOICES>"
}
#Set Default value, if specified
if ($_.Default) { $fieldXML = $fieldXML + "`n<Default>" + $_.Default + "</Default>" }
#End XML tag specified for this field
$fieldXML = $fieldXML + "</Field>"
#Create column on the site
$destWeb.Fields.AddFieldAsXml($fieldXML.Replace("&","&"))
write-host "Created site column" $_.DisplayName "on" $destWeb.Url
$destWeb.Dispose()
}
You may get some warning messages during processing of the import script if there are columns contained in the exported schema XML file that are already present in the destination site collection. Unless there are conflicting issues with your imported columns during testing, these warnings should be safe to ignore (or the columns removed from the exported XML if not required) as the script will not overwrite what is present in the site collection already. Once the script has been run, the custom site columns exported from the original site collection will be present in the new site collection:
In my next article, I cover exporting and importing content types from one site collection to another using a similar process…
Phil, luv your Powershell posts. I have a brain teaser. I need to update a Site Column in SharePoint 2007. It seems the consultant has left out the "List = UserInfo" property when it was deployed thus users get the dreaded "Datasheet Error 0x80070057" when trying to lookup a username. Is it possible to do this in Powershell? The site column is in the ContentDB it seems.
ReplyDeleteBismark
Hi Phil, upon running your import to re-add the lists I get Field type is not installed properly. Go to the list settings page to delete this field.
ReplyDeletewhen I browse the site settings->site columns list.. help.
Hi Phil,
ReplyDeletethis is the first time in my life, I download a script and it runs without any error AND does the expected thing. By the way I'm 46 years and started to study computer sience about 20 years ago.
Great Work!
Michael
Michael - first time in your life! Wow! I'm glad it worked.... :-)
ReplyDeleteHello,
ReplyDeleteI tried the scripts, the first one went fine, i got all the columns however i'm having the same issue as "Muse" {Field type is not installed properly. Go to the list settings page to delete this field. } can you help please
Thx
I'll reply to my own question. I had created some workflows before and i had some columns in my site. Thus we generating the XML file, there was a column with <Field Name="Type_x0020.... i deleted it and ran the script again and "Voila" the only problem is that as the script doesn't do any override i had to delete the site recreate it and re-run the scripts
ReplyDeleteHello Phil,
ReplyDeleteI got same issue with Muse... "Field type is not installed properly. Go to the list settings page to delete this field."
Is there any proper way to fix it safely?
Phil - We are working with Microsoft's EPM (Enterprise Project Management)which uses Sharepoint as a repository for project documents. EPM has a site collection with a project site template which is instantiated for each new project. Within the site template are lists for tracking Risks, Issues, Change Requests etc. We want to add some columns to the Risks list and have these propagate to all existing project sites, not just new sites created going forward. Do you have any tips you can share on how to achieve this? Thanks.
ReplyDeleteIf the lists work from a site content type then you can add the columns there - if not, you could use PowerShell to walk through each site, connect to the Risks list and add the columns required
ReplyDeleteWonderful blog! I found it while searching on Yahoo News. Do you have any tips on how to get listed in Yahoo News? I’ve been trying for a while but I never seem to get there! Many thanks.sbobet
ReplyDeletePhil
ReplyDeleteUseful blog thanks, wondering if this script works when site columns are referencing managed metadata?
Thanks
Thanks Phil! Your blog was easy to follow and the script worked perfectly the 1st time!
ReplyDeleteGreat! Thanks for the feedback, Peter
DeletePhil, thanks for all the scripts that you put here. They are really useful for someone starting with SP.
ReplyDeleteThis script works fine, but when I try to add or create a new calculated column using AddFieldAsXML, it never works. I add field properties, formula and fieldrefs in Schema XML, and after running script, field is added but formula is not. Even I tried to do this field.formula = and field.Update()...it doesn't work.
Do you have any other idea how we can add calculated field using powershell ?
Thanks a lot.
Ashish,
Germany
I now could solve this problem. So for calculated field, dont add any fieldrefs or formula in XML Schema. Just use AddFieldAsXml first to create this field and later on after this field is added, use field.formula = "formula here with brackets in column name" and field.update(), and it works.
DeleteThanks anyways Phil and keep Posting.
Ashish
Hi Phil,
ReplyDeleteThanks for this script. It worked great for me. The only small issue I had is with the assignment of term/term-set for a site column of type Managed Metadata type. The site column of type Managed Metadata type is imported properly. It shows me the whole term store to select any term. But it doesn't pre-assign the particular term which was assigned from the place where I imported the column.
Do you know if I can achieve this assignment of term automatically while importing.
Thanks
David
Hi Phil,
ReplyDeleteI need to add list=userinfo in my schema xml..Is it possible to do with powershell.
Great scripts, thanks!
ReplyDeleteSmall issue you might like to fix; the script doesn't actually force the file to be written in UTF-8, which caused me troubles when choice options used characters with umlauts.
Easy fix, just add
" -Encoding UTF8 "
after each Add-Content statement.
Regards,
Jan Steenbeek
Thanks for the tip, Jan!
ReplyDeleteOh, also, the builder for the column doesn't recognice MultiChoice columns.
ReplyDelete> if ($_.Type -eq "Choice") {
Should be
> if (($_.Type -eq "Choice") -or ($_.Type -eq "MultiChoice")) {
Regards, Jan
Excellent script. Just the thing I was looking for. Thanks very much for sharing your knowledge.
ReplyDeleteThanks for the script.
ReplyDeleteDid you ever encounter the following problem:
Exception calling "AddFieldAsXml" with "1" argument(s): ""
Its just this one column which have Problems. It's a simple Text column. Do you have an idea why this error came up?
regards, nadine
Thanks for the script, I modified the second version and managed to get it down to very few lines.
ReplyDeleteSince you're dealing with an Xml object anyways, why not grab the OuterXml and use that?
$fieldsXML.Fields.Field | ForEach-Object {
$destWeb.Fields.AddFieldAsXml($_.OuterXml.Replace("&","&"))
write-host "Created site column" $_.DisplayName "on" $destWeb.Url
$destWeb.Dispose()
}
Saved me having to build up my own xml string which was prone to me missing things.
Cheers,
Kyle
This comment has been removed by the author.
ReplyDeleteThanks Phil, this was very helpful!
ReplyDeleteDoug
http://www.Codesigned.com