SharePoint 2010 Cross-Site Lookup using PowerShell

A common SharePoint request is to create a lookup field from a list in another site. This is possible so long as the sites are within the same site collection, but it does require some customization.

Since I am dealing with a single-server farm, I was able to do this fairly quickly in PowerShell:

# Set the site collection in which the source and destination webs exist
$site = Get-SPSite("https://mysite/path/")

# Set the source web to the web where the source list exists
$sourceweb = $site.OpenWeb("sourcepath")

# Set the destination web to the web where you wish to add the lookup
$destinationweb = $site.OpenWeb("destinationpath")

# Set the source list to the list in which the field exists
$sourcelist = $sourceweb.Lists["List Name"]

# Set the source field to the field you wish to perform lookups on
$sourcefield = $sourcelist.Fields["Field Name"]

# Get the collection of all fields in the destination list
$destinationfields = $destinationweb.Lists["List Name"].Fields

# Add a lookup field to the fields collection
# See the SPFieldCollection AddLookup(String,Guid,Guid,Boolean) method
# For details: http://msdn.microsoft.com/en-us/library/ms430950.aspx
$lookupname = $destinationfields.AddLookup($sourcefield.Title,$sourcelist.ID,$sourceweb.ID,false)
# The above produces an error: Missing expression after ','. At line:1, char:83
# Right--in Powershell, $false is False.
$lookupname = $destinationfields.AddLookup($sourcefield.Title,$sourcelist.ID,$sourceweb.ID,$false)

# Get the newly-added lookup field
$lookup = $destinationfields.GetFieldByInternalName($lookupname)

# Set the lookup field to the internal name of the source field
$lookup.LookupField = $sourcefield.InternalName

# Update the lookup -- without this the previous changes won't be saved
$lookup.Update()

# Dispose of the SPWeb and SPSite objects
$sourceweb.Dispose()
$destinationweb.Dispose()
$site.Dispose()

Moving SharePoint sites using stsadm.exe

I recently needed to move a SharePoint site from one site collection to another. Fortunately, this is very easy to do using the stsadm tool (located in the bin directory of the 14 hive).

Following the instructions at Using Stsadm.exe to Migrate Site Data (a SharePoint 2007 document, but still applicable to SharePoint 2010), I used the stsadm export command from the 14 hive with the following parameters:

bin\stsadm.exe -o export -includeusersecurity -versions 4 -url 'https://mysite.url/oldcollection/myweb' -filename myweb.cmp

However, that returned the following error message:
Syntax error in argument: url

If you drop the quotation marks around the URL, it works:
bin\stsadm.exe -o export -includeusersecurity -versions 4 -url https://mysite.url/oldcollection/myweb -filename myweb.cmp

(I find that really unbelievable. Text parameters almost always appear as quoted values. Even if it doesn’t need the quotes, you’d still expect it to accept the quotes!)

The instructions for the export command mention cabsize but don’t indicate the default:
-cabsize <integer>
Specifies the maximum size of the .cmp file in megabytes. The range is from 1 to 1024 MB. If the export data exceeds the maximum specified, the data is split into multiple files."

For the site I was working with, the export command saved the site as 4 files, each around 25 megabytes. I decided I would prefer a single .cmp file (and the site I was exporting did not exceed 1024Mb) so I increased the cabsize to the maximum:
bin\stsadm.exe -o export -cabsize 1024 -includeusersecurity -versions 4 -url 'https://mysite.url/oldcollection/myweb' -filename myweb.cmp

To import the site into the new site collection, run the import command:
bin\stsadm.exe -o import -url https://mysite/newcollection/myweb/ -filename myweb.cmp

Once you’ve moved the site–and checked the new location to make sure everything worked–don’t forget to delete the old site and the .cmp file.

SharePoint Breadcrumb Styles

SharePoint (and .NET) has a built-in SiteMapPath control that is designed to display a breadcrumb trail.

There are a lot of options in terms of styling the breadcrumb trail, but it is not obvious how all of them are used. Even more confusing, though, is when you make a change the the styles but you don’t see that change reflected on your site. For example, on one site I am working on I saw breadcrumbs like these:

An example of SharePoint breadcrumbs
An example of SharePoint breadcrumbs

I didn’t like how much vertical space this style occupied. I wanted something a little more compact. But how to change the appearance?
Continue reading SharePoint Breadcrumb Styles

Using a list or array as a PowerShell script input parameter

One of my colleagues created a PowerShell script that we use to migrate SharePoint 2010 sites from the SharePoint 2007 interface (UI 3) to the SharePoint 2010 interface (UI 4). The script works rather well for updating one or two sites at a time:

Set-UserInterface2010.ps1 -url "https://my.sharepoint.site/path/"

Today I received a request to update a list of 32 sites. After updating one, I thought–this is going to be tedious. We can improve this.

First, I updated the parameter to accept an array of strings instead of a single string.

Before
param([string]$url = $(throw "Please specify a Site URL to convert to the SP2010 look and feel"))

After
param([string[]]$url = $(throw "Please specify a Site URL to convert to the SP2010 look and feel"))

Next, I wrapped the call to the main function in a ForEach loop:
ForEach ( $siteurl in $url ) {
...
# Throw in a line break to separate output
Write-Host ("`n`n")
}

The script can still take a single site as input (the string is treated as a string array with a single element), but now I can also pass it a list:

Set-UserInterface2010.ps1 -url "https://my.sharepoint.site/path1/","https://my.sharepoint.site/path2/","https://my.sharepoint.site/path3/"

Here’s hoping that taking a couple minutes to update the script and running it once saved me more time than running it 32 times!

SharePoint error when editing a wiki page: Sys.WebForms.PageRequestManagerServerException: An unexpected error has occurred

I’ve had an ongoing problem where some users, when clicking the Edit Page button on a SharePoint 2010 wiki page, get the following error:

Sys.WebForms.PageRequestManagerServerException: An unexpected error has occurred

I found a couple blog posts about this suggesting a permissions issue (which made sense, as users in other groups could successfully edit pages):

Both sites suggested that an Access Denied message should appear in the ULS logs. However, no such message appeared in relation to my errors.

ULS entry:
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.SharePoint.Publishing.WebControls.MediaWebPart.get_WebPartAdderId()
at Microsoft.SharePoint.Publishing.WebControls.InsertMediaRibbonButton.RegisterRequiredScripts()
at Microsoft.SharePoint.Publishing.WebControls.InsertMediaRibbonButton.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... 1317dffd-b607-4f1c-9145-b4adc1d364ba

The MediaWebPart. SharePoint 2010 added a video/audio insertion feature on the ribbon, and the error occurred when trying to add the button.

It turns out, the permissions to the Web Part Gallery had been customized (i.e. broken inheritance from the parent site collection), and some groups who had permission to edit wiki pages did not have read permission for the Web Part Gallery (and, consequently, the MediaWebPart). Adding Restricted Read access for the group in question (to either the MediaWebPart or to the Web Part Gallery) solved this problem.

I don’t imagine this will be a common problem for other people, but I thought it worth mentioning.

Displaying numeric fields in SharePoint 2010 without commas

A common request is to display number fields in SharePoint 2010 lists without commas. For example, if you had a list of books that included PublicationYear column, it would format the values as:

  • 2,001
  • 1,998
  • 2,011

This is confusing to the viewer, as values no longer look like years.

The most frequent suggestion is to create an additional field that calculates a value based on the Number field and ignores all non-numeric parts. This is relatively straightforward, and can be accomplished entirely within the browser:

=TEXT([MyNumericData], "0")

Or, in a case where you’d like to retain two digits after the decimal:
=TEXT([MyNumericData], "0.00")

SharePoint appears to store the data in its numeric format in a another column, hidden to the browser but visible in SharePoint Designer. It’s [column name] followed by a period. For example, I created a field called MyNumericData, so the hidden field is MyNumericData. Again:

  • MyNumericData
  • MyNumericData.

Adding this to a view via SharePoint Designer is non-obvious. Here are the steps I used:

  1. Click on a data item in Design mode until you see a tab labeled xsl:value-of:
    SharePoint Designer 2010 Design Mode
  2. Right-click the item and select Edit Formula
  3. Remove the current XPath expression
  4. Add the MyNumericData. row from the fields pane
  5. Add the format-number function from the Math / Number functions
  6. Add the appropriate format pattern (e.g. ‘#’)

The appropriate format pattern depends on how you wish to display the data:

  • Display integer value:
    format-number($thisNode/@MyNumericData.,'#')
  • Always display two digits after the decimal:
    format-number($thisNode/@MyNumericData.,'0.00')
  • Display up to 2 digits after the decimal:
    format-number($thisNode/@MyNumericData.,'#.##')

If you look at the code view after making these changes, you will see that SharePoint Designer added a hefty chunk of XSL to the XsltListViewWebPart.

Is there any advantage to this method over adding a calculated field? Not as far as I can tell–but it’s interesting to note that there is more than one overly-complicated solution to what seems like a trivial problem.

Updating a SharePoint page’s Page Layout using PowerShell

Earlier today I tried to update the page layout on a SharePoint 2010 site via the browser, which produced an error. I looked up the error’s correlation ID in the ULS logs and found this:
GetFileFromUrl: ArgumentException when attempting get file Url https://oldsitename/webname/_catalogs/masterpage/Block.aspx Value does not fall within the expected range.

I couldn’t change the page layout via the browser. I couldn’t change the page layout via SharePoint Designer.

Fortunately, I found Patrick Lamber’s helpful post, How to programmatically change the page template in Moss 2007, which basically described the same error and described applying a new page layout via the object model.

For whatever reason, I thought I could do it just as easily via PowerShell. I started following Jason Grimme’s post, Update SharePoint List Item(s) with Powershell, but I was unable to check-out/check-in the page or access the PublishingPageLayout property.

Liam Cleary’s reply on a TechNet post (Using PowerShell to Checkout and Checkin a file) tipped me off that I needed to use SPFile (rather than SPListItem) in order to perform the necessary operations. Here are the commands I ended up using:

$spWeb = Get-SPWeb("http://currentsitename/webname")
$spFile = $spWeb.GetFile("http://currentsitename/webname/Pages/Test-Page.aspx")
$spFile.CheckOut("Online",$null)
$spFile.Properties["PublishingPageLayout"] = "/_catalogs/masterpage/Block.aspx, Block"
$spFile.Update()
$spFile.CheckIn("Update page layout via PowerShell",[Microsoft.SharePoint.SPCheckinType]::MajorCheckIn)
$spWeb.Dispose()

I visited the page and…another error! This one telling me there wasn’t a valid page layout. Funny, it worked in development.

It turns out, when I compared it to the PublishingPageLayout property of a working page, I had missed the space character after the comma.

Doesn’t work:
"/_catalogs/masterpage/Block.aspx,Block"

Works:
"/_catalogs/masterpage/Block.aspx, Block"

Once I applied the proper path, I was also able to change the page layout via the browser again.

Importing Data into a SharePoint List

SharePoint Joel’s recent post, Managing Large Lists in SharePoint for Users and Site Admins got me interested in testing the 5000 list view item limit.

It also gave me a good opportunity to put fakenamegenerator.com to the test. The site quickly provided me with a list of 6000 random names.

Now, how to get them into a SharePoint list? Continue reading Importing Data into a SharePoint List

SharePoint user control to display a random image

The master page of a SharePoint site I work on loaded 7 photographic images, all over 50 kB each, to display at random as a banner adjacent to the site logo. The way it loaded the images was very inefficient: a default image was loaded in the HTML, and Javascript on the page created 7 image objects and returned one at random to overwrite the default. I decided to find a C# way to solve the problem.
Continue reading SharePoint user control to display a random image

Using SharePoint’s Imaging Web Service to access Publishing Images

I spent a fair amount of time yesterday trying to access the images in the Images list (also known as Publishing Images) of a SharePoint site using the SOAP-based Imaging web service. Every time it failed, usually with an uninformative error message.

Finally, I used cURL to send the SOAP requests so that I could see every last detail of the transaction. The SOAP response was pretty clear at that point:

The list PublishingImages is not found

or

The list Images is not found

I tried other Picture Libraries on the site, and that worked fine. That’s when it dawned on me: the SharePoint Images (or PublishingImages) list is a Document Library, not a Picture Library. That makes absolutely no sense whatsoever, but fine, it wouldn’t be the first time I’ve run into something nonsensical in SharePoint.

I was hoping to use the download method of the Imaging web service. I don’t have an alternative solution at this time, but I hope to find one soon using one of the other SharePoint web services.