MOSS MVP

I've moved my blog to http://blog.falchionconsulting.com!. Please update your links. This blog is no longer in use--you can find all posts and comments at my new blog; I will no longer be posting to this site and comments have been disabled.

Monday, February 18, 2008

Import Site Columns

In my last post I wrote about a command that I created to export site columns to an xml file because I needed the data for a Feature I was working on. But what if you just want to create a column using the exported results and for whatever reason you don't want to create a Feature? I figured it would take me about 2 minutes to throw together an import command that would take in the results of the export so may as well add it to the collection. So now you can use the gl-importsitecolumns command to import what you exported using gl-exportsitecolumns (useful if you're just trying to move some fields around though I'd still recommend you do this via a Feature). Note that this command will blow up if a column already exists with the same name. The code for this is really simple - just loop through the XML and call the SPFieldCollection's AddFieldAsXml method: 

   1:  string url = Params["url"].Value;
   2:   
   3:  XmlDocument xmlDoc = new XmlDocument();
   4:  xmlDoc.Load(Params["inputfile"].Value);
   5:   
   6:   
   7:  // Get the source content type and fields.
   8:  using (SPSite site = new SPSite(url))
   9:  using (SPWeb web = site.AllWebs[Utilities.GetServerRelUrlFromFullUrl(url)])
  10:  {
  11:      foreach (XmlElement fieldNode in xmlDoc.SelectNodes("//Field"))
  12:      {
  13:          web.Fields.AddFieldAsXml(fieldNode.OuterXml);
  14:      }
  15:  }
The syntax of the command can be seen below:
C:\>stsadm -help gl-importsitecolumns

stsadm -o gl-importsitecolumns

Imports one or more site fields (columns) to a site.

Parameters:
        -url <url>
        -inputfile <file to import fields from>
Here's an example of how to import site columns that were exported using the exportsitecolumns command:
stsadm -o gl-importsitecolumns -url "http://intranet" -inputfile c:\fields.xml

16 comments:

Marcus said...

First of all... what a great set of tools. Most of the extensions are really contributing to managing Sharepoint.

I do have a question with regards to the gl-importsitecolumns command;

I exported my existing site columns as follows:

stsadm -o gl-exportsitecolumns -url "http://testnet.mysp.com" -outputfile c:\fields.xml -group "My Columns"

This creates the fields.xml successfully.

When I import the site columns to a different site collection (not in the same server farm I must say) the command ends succesfully, but I do not see any of the site columns I expect.
The command I am using is:

stsadm -o gl-importsitecolumns -url "http://testnet2.com" -inputfile fields.xml

Is there anything else that I might have to consider before importing the site columns?

Thanks in advance and keep up the great work!

Regards,

Marcus.

Gary Lapointe said...

Not sure why they are not showing up. I made a modification to the import code just now to add the AddFieldInternalNameHint enum option so that it uses thes Name attribute for the internal name (without that in place it was using the display name as the internal name). I won't be able to push the code up until later today though but if you want to download the source and make the same modification it's real easy - just change the web.Fields.AddFieldAsXml statement in the ImportSiteColumns.cs file to: web.Fields.AddFieldAsXml(fieldNode.OuterXml, false, SPAddFieldOptions.AddFieldInternalNameHint);. Beyond that the only thing I can ask is to make sure you're looking in the right place for the columns :)

Kevinlife said...

I think it's something wrong with output xml...

please change output xml string from
< Elements xmlns="http://schemas.microsoft.com/sharepoint/">
< Field DisplayName="QQQ" Type="Text" Required="FALSE" ID="{4b3ef9ad-6788-4364-a4d8-8d2f8d29eacf}" SourceID="{03f49504-72cc-4291-83fe-c90dc5e2ab8d}" StaticName="QQQ" Name="QQQ" />
< /Elements>

to

< Fields>
< Field DisplayName="QQQ" Type="Text" Required="FALSE" ID="{4b3ef9ad-6788-4364-a4d8-8d2f8d29eacf}" SourceID="{03f49504-72cc-4291-83fe-c90dc5e2ab8d}" StaticName="QQQ" Name="QQQ" />
< /Fields>

then
It's successfull to import ...

Gary Lapointe said...

Yes - you are correct- I'd added the namespace attribute to help with my feature development and forgot to test the import which assumed no namespace. I've updated the build so that it will work with or without the namespace attribute - just download the latest.

Dave said...

Very nice set of extensions.

The first time around things went very well.
Exported from site A
Imported into site B

Do again after adding or changing site columns in site A cause the import to report the following:
A duplicate name XXXX was found.

Net change was not part of the inital code. Any thoughts on best approach?

Miguel said...

Hey Gary,
First of all, thanks for your work

After exporting and importing(to a different server) site columns using your tool, i get the infamous error

Key cannot be null.
Parameter name: key

when i go to Site Settings->Galleries->Site Columns.


I know that the import command inserted 40 new columns.

Now the problem is how can I identify and delete the column(s) that is giving me an headache?

I tried to debug but I couldn't. .
this line works fine
SPFieldCollection fields = web.Fields;

but when I get here it gives the error
foreach (SPField field in fields)

So how can I identify and remove the invalid column?

Gary Lapointe said...

Can you turn on the stack trace to see where in the call stack it's failing? If you want you can send me the exported XML and I can try to reproduce (it will be at least a couple of days before I can get to it though) - gary at thelapointes dot com.

Miguel said...

here it is:
Key cannot be null.
Parameter name: key at System.Collections.Hashtable.get_Item(Object key)
at Microsoft.SharePoint.SPField.GetFieldType(String strType)
at Microsoft.SharePoint.SPFieldCollection.PopulateFieldsSafeArrayFromXml(String fieldsSchema)
at Microsoft.SharePoint.SPFieldCollection.EnsureFieldsSafeArray(Boolean bGetFullXML)
at Microsoft.SharePoint.SPFieldCollection.Undirty(Boolean bGetFullXML)
at Microsoft.SharePoint.SPFieldCollection.Undirty()
at Microsoft.SharePoint.SPBaseCollection.System.Collections.IEnumerable.GetEnumerator()
at Microsoft.SharePoint.ApplicationPages.FieldListRenderer.OnPreRender(EventArgs e)
at System.Web.UI.Control.PreRenderRecursiveInternal()
at System.Web.UI.Control.PreRenderRecursiveInternal()
at System.Web.UI.Control.PreRenderRecursiveInternal()
at System.Web.UI.Control.PreRenderRecursiveInternal()
at System.Web.UI.Control.PreRenderRecursiveInternal()
at System.Web.UI.Control.PreRenderRecursiveInternal()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

Gary Lapointe said...

Miguel - it would appear as though one of the fields you imported had a Type attribute not set (or set to an empty string). Take a look at your exported XML and make sure all the fields have a Type attribute. If they do then also check to make sure that if you are using a custom field type that the field type exists in the target. You "might" also be able to use a tool like SharePoint Manager to view the fields and possibly identify the offending field that way (otherwise you might be stuck having to look in the database).

Tundey said...

I am having a problem with columns imported using importsitecolumns. The columns show up fine in SharePoint's Site Column Gallery but when I try to bind them to an InfoPath field, they do not show up in InfoPath. Not only that, after importing columns, other random columns also stop showing up in InfoPath (during property promotion). Any ideas on how to fix this?

Gary Lapointe said...

I've not seen that behavior before. Can you share the schema of the field you are trying to update.

Tundey said...

They were basic columns. Nothing fancy. Just texts and dates. Here's a sample:

<Field Type="Text" DisplayName="TestColumn" Required="FALSE" MaxLength="255" Group="Milestone Columns" ID="{7ab3acbd-015d-43a3-ae42-6605ffb18d1a}" SourceID="{95ec7eb2-cac8-4a8c-8024-825bf4361a4a}" StaticName="TestColumn" Name="TestColumn"></Field>

I ended up exporting the columns and deploying them as a feature.

Gary Lapointe said...

You might try changing the sourceid to "http://schemas.microsoft.com/sharepoint/v3" - I've seen issues related to the sourceid and infopath before (same with the static name). Features is the way to go though anyways.

tripwire said...

Hi Gary,

I've been experiencing an issue where I'm unable to edit certain columns after an import. I had the same issue when using your gl-copycontenttype command.

After much hair pulling I managed to resolve this by removing the Version attribute from the field definition. Not sure if it's actually needed or not. :)

Mélanie said...

Hi Gary,
We having a problem with column imported using importsitecolumns. We have all informations about this column after import except the "get information from" field. We import the list before and then we use this command:

thanks!

Gary Lapointe said...

Mélanie - could you provide more specific information? Not sure if I'll be able to help or not but with some additional details I might be able to offer up something.