I was working with PowerShell to update a managed metadata field that accepted multiple values in a publishing page library today and it was more difficult than it seemed like it should have been, so I’m posting here what actually worked for me. It turned out to be much simpler than I was trying to make it.  The larger project here was reading values in for publishing page properties from an XML file, but I have skipped all that for the purpose of this post. 

The first thing you need to do is connect to your site and your term store and term set.

   1:  $site = Get-SPSite http://intranet.contoso.com
   2:  $session = New-Object Microsoft.SharePoint.Taxonomy.TaxonomySession($site)
   3:  $termStore = $session.TermStores["Managed Metadata Service"]
   4:  $group = $termStore.Groups["Corporate"]
   5:  $termSet = $group.TermSets["Locations"]
   6:  $terms = $termSet.GetTerms()

These lines are loading all the terms in the term set named “Locations”.  Next, we need to specify what values we are trying to set.  In this example, we are manually setting them in the script, but these could easily be read in from XML, CSV or something else.

$locations = "Charlotte", "Chicago", "New York", "Boston"

So we have our terms set in an array, now we can loop through each element of the array, find the corresponding term in the term set (stored in $terms from line 6 above) and create a “Term | Term ID” string to insert into our managed metadata field.  Individual terms are separated by a semi-colon in this case since our field allows multiple values.

   1:  foreach($location in $locations) {
   2:       $term = $terms | ?{$_.Name -eq $location}
   3:       $termString += $term.Name + "|" + $term.Id + ";"
   4:  }    

Now we just need to apply this string to our managed metadata field.  It will translate it so that only the term names are shown.  It stores the term ID in a separate hidden field.

   1:  $newPage.ListItem["Location"] = $termString.Substring(0,$termString.Length-1) #fails with a trailing ; so, remove it

The managed metadata field will reject your string if it contains a trailing semi-colon, so when we set the value to our field, just strip off the last character.  This will need to be removed no matter how many terms there are.

So, lets put that all together with all the additional code we need to connect and work with the publishing page library:

   1:  $site = Get-SPSite http://intranet.contoso.com   
   2:  $web = $site.rootweb
   3:  $pubWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($web)
   4:  $pages = $pubWeb.GetPublishingPages($pubWeb)
   6:  $newPageName = "Test-to-Set-Locations"
   7:  $pageLayout = $pubWeb.GetAvailablePageLayouts() | Where-Object {$_.Title -eq "Article Page"}
   8:  $pageurl = "Pages/" + $newPageName + ".aspx"
   9:  $newpage = $pages.Add($pageurl, $pagelayout)
  11:  $session = New-Object Microsoft.SharePoint.Taxonomy.TaxonomySession($site)   
  12:  $termStore = $session.TermStores["Managed Metadata Service"]   
  13:  $group = $termStore.Groups["Corporate"]   
  14:  $termSet = $group.TermSets["Locations"]   
  15:  $terms = $termSet.GetTerms()   
  17:  $locations = "Charlotte", "Chicago", "New York", "Boston"   
  18:  foreach($location in $locations) {  
  19:       $term = $terms | ?{$_.Name -eq $location}  
  20:       $termString += $term.Name + "|" + $term.Id + ";"  
  21:  }      
  22:  $newPage.ListItem["Location"] = $termString.Substring(0,$termString.Length-1)   
  23:  Write-host "Managed Metadata Set"
  24:  $newPage.Update()