Set Web Part properties in loop

25/06/2013 18:05

Add web part to the page as instance of custom class, set its properites

Script reads *.webpart file and sets properties for webpart instance in a loop. Only string, bool and int type are set, because values are casted. Other properties are skipped. Web part in example is standard ContentByQueryWebPart and is added to /Pages/default.aspx page.

 

Add-PSSnapin microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

function TextToBool([string]$text)
{
 $result = $false
 if($text)
 {
  switch($text.ToLower())
  {
         "true"  { $result = $true; break }
   "1"  { $result = $true; break }
        "false"  { $result = $false; break }
   "0"  { $result = $false; break }
     }
 }
 return $result
}

function CastPropertyValue([string]$type, [string]$value)
{
 if($type -eq "string")
 {
  return $value
 }
 elseif($type -eq "bool")
 {
  return (TextToBool $value)
 }
 elseif($type -eq "int")
 {
  return [int]::Parse($value)
 }
 else
 {
  return $null
 }
}


#settings

$webUrl = "https://yoursitecollection"
$pageRelativeUrl = "/Pages/default.aspx"
$wpTitle = "My Content Query web part"
$LocalWebPartPath = "C:\temp\Content Query.webpart"
$ZoneName = "MainWPZ"
$ZoneIndex = 1

$AssemblyName = "Microsoft.SharePoint.Publishing"
$FullWpTypeName = "Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart"

#code

$pageFullUrl = $webUrl + $pageRelativeUrl

#first you have to check out the file/page, if publishing/versioning is disabled, then you can skip this step
$web = Get-SPWeb -identity $webUrl
$file = $web.GetFile($pageRelativeUrl)
$web.AllowUnsafeUpdates = $true
if ($file.Level -ne [Microsoft.SharePoint.SPFileLevel]::Checkout)
{
 write-host " Checking-out page" $pageRelativeUrl
 $file.CheckOut()

#initialize the webpart-manager and locate it to the page
$webpartmanager = $web.GetLimitedWebPartManager($pageFullUrl, [System.Web.UI.WebControls.WebParts.PersonalizationScope]::Shared)

#Define context, it's needed for setting properties
if ($null -eq [System.Web.HttpContext]::Current)
{
 $sw = New-Object System.IO.StringWriter
 $resp = New-Object System.Web.HttpResponse $sw
 $req = New-Object System.Web.HttpRequest "", $Web.Url, ""
 $htc = New-Object System.Web.HttpContext $req, $resp
 #explicitly cast $web to spweb object else sharepoint will
 #see it as a PSObject, and AddWebpart wil fail
 $htc.Items["HttpHandlerSPWeb"] = $Web  -as [Microsoft.SharePoint.SPweb]
 [System.Web.HttpContext]::Current = $htc
 if ($sw -ne $null)
 {
  $sw.Dispose()
 }
}

#Load your custom assembly
[void][reflection.assembly]::LoadWithPartialName($AssemblyName)

try
{
  
 #Create web part instance

 $webpart = new-object $FullWpTypeName
 
 #Load properties from *.webpart file and use them for webpart
 $xml = [xml](Get-Content -Path $LocalWebPartPath)
 $wpProperties = $xml.Webparts.webpart.data.properties.property
 
 #Continue with setting correct properties, skip wrong
 $ErrorActionPreference = "Continue"
 
 foreach($property in $wpProperties)
 {
  Write-Host $property.Name ": " $property.InnerText
  
  try
  {
   $prop = $webpart.GetType().GetProperty($property.Name)
   $propertyValue = CastPropertyValue $property.type $property.InnerText
   if($propertyValue)
   {
    $prop.SetValue($webpart, $propertyValue, $null)
   }
   else
   {
    Write-Host "Property " $property.Name " was not set." -ForegroundColor Red
   }
  }
  catch
  {
   Write-Error $_
  }
 }
 $ErrorActionPreference = "Stop"

 #Overwrite web part title with value from Xml
 $webpart.Title = $wpTitle
 

 #the code in the brakets adds the $webpart to the mentioned zone and sets the sorting of the webpart on the first place
 $webpartmanager.AddWebPart($webpart, $ZoneName,$ZoneIndex);
 $webpartmanager.SaveChanges($webpart)

 $web.Update()
 Write-Host "Web part '$FullWpTypeName' succesfuly added to " $pageRelativeUrl

 
 }
 catch
 {
  Write-Error $_.exception
 }
 
 $file.CheckIn("Checkin",[Microsoft.SharePoint.SPCheckInType]::MajorCheckin)
 if($web -ne $null){
   $web.Dispose()
 }