Adding a SharePoint View to every library

How to add a SharePoint View to every library

Sometimes one has to create a custom view and deploy it to every library. This example walks through a set of explicitly named site collections within a given Managed Path, and adds a custom view. To enable running it multiple times, the script first deletes every instance of that named view, if any exist. Otherwise we would have a new duplicate view in each library each time we ran this script. Note both filtering and sort order is specified by a CAML query. This example shows a very simple one (sort by filename) but it’s possible to construct complex queries. The two approaches I like to use is use a tool called CAMLBuilder, or create a test view, and then navigate the object model and extract the CAML query. Lastly I add the fields using the static (internal) name in the preferred sequence.

#adds "Field" to right  in Default View; deletes field first, in case it already exists, so this can be rerun safely
Add-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue
# Script changes the default View. 
$envrun="Prod"			# selects environment to run in
if ($envrun -eq "Dev")
{
}
elseif ($envrun -eq "Prod")
{
$siteUrl = "http ://sharepoint/ManagedPath/"
$LoopString = "A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,09"  #these are the explicitly named Site Collections
$LoopStringArr = $LoopString.Split(“,”)
}
else
{
Write-Host "ENVIRONMENT SETTING NOT VALID: script terminating..."
$siteUrl =  $null;
return;
}
Write-Host "script starting" 
$myheader = "STARTING: $(get-date)"
foreach ($letter in $LoopStringArr)
{
$SiteName=$siteurl+$letter
$rootSite = New-Object Microsoft.SharePoint.SPSite($SiteName)
$site=$rootSite  #skipping traversing all sites for now
write-host $site.Url
if ($true) #this is useful to uncomment as a filter
#  if ($site.Url -like "$siteurl/personal/plau*")  
{
Write-Host -foregroundcolor darkblue "$($site.id) - $($site.Url) - $($site.contentdatabase.id) - $($site.contentdatabase.name)"   
$rootWeb = $site.RootWeb
$web=$rootWeb;
$JPLists=$web.Lists;
$JPListsCount=$JPLists.Count  #it much more efficient to resolve Lists object and count outside the loop
for ($i=0;$i -lt $JPListsCount;$i++)
{ 
$JPLib=$JPLists[$i];
$A_Lib_Count++;
$SkipLib=$true; #true
if ( ($JPlib.BaseType -ne "DocumentLibrary") -or ($JPlib.hidden) )
{
# forget the rest and return to top
Write-Host -foregroundcolor green "fast test skipping Library: $($JPlib)";   
}
elseif ($JPLib.Title -Match "SitesAssets|Photo|Image|CustomizedsReports|Templates|Pages|Picture|cache|style|Slide")
{
# forget the rest and return to top
Write-Host -foregroundcolor red "fast test skipping Library because it mentions $Matches: $($JPlib)";   
}
elseif ($JPLib.BaseTemplate -ne "DocumentLibrary")   #alternatively, only skip if -eq XMLForm
{
# forget the rest and return to top
Write-Host -foregroundcolor red "fast skipping Library because it is not of base DocumentLibrary, it is BaseType:$($JPlib.basetemplate): $($JPlib.title)";   
}
elseif (($JPLib.ThumbnailsEnabled) -or ($JPLib.DefaultView -eq "AllSlides"))
{
# forget any library with thumbnails, these are not normal doclibs, and return to top
Write-Host -foregroundcolor red "fast test skipping Library because it has Thumbnails/Slides $($JPlib)";   
}
elseif (!$JPLib.ContentTypesEnabled)
{
Write-Host -foregroundcolor red "skipping because it does not have CTs enabled: $($JPlib)";   
}
else
{  $SkipLib=$false;	}
if (!$SkipLib)
{
write-Host -foregroundcolor green "Processing Library: $($JPlib)";   
#hah, don't even delete and add if found, just cycle
$x=$null;
try
{
$x=$JPLib.Views.get_Item("NEW View")
}
catch {$x=$null}
if ($x -ne $null)
{
continue;
}
try
{
$x=$JPLib.Views.get_Item("NEW View")
if ($x.id -ne $null) #prevents duplicate entries
{
$JPLib.Views.Delete($x.ID.ToString())
}
}
catch
{}
if ($JPLib.Views["NEW View"] -eq $null) #prevents duplicate entries
{
$viewQuery = '<OrderBy><FieldRef Name="FileLeafRef" /></OrderBy>'  #This is any CAML query you construct
#let's add the fields, by internal name, in the preferred sequence
$viewFields = New-Object System.Collections.Specialized.StringCollection
$viewFields.Add("DocIcon") > $null
$viewFields.Add("LinkFilename") > $null
$viewFields.Add("Title") > $null
$viewFields.Add("Modified") > $null
$viewFields.Add("Editor") > $null
$viewFields.Add("ProductCode") > $null
$viewFields.Add("ProductDescription") > $null
$viewFields.Add("DocumentType") > $null
$viewFields.Add("ReportSubType") > $null
#RowLimit property
$viewRowLimit = 30
#Paged property
$viewPaged = $true
#DefaultView property
$viewDefaultView = $false
#$ViewQuery=$null;
$viewTitle="NEW View"
$newview = $JPLib.Views.Add($viewTitle, $viewFields, $viewQuery, $viewRowLimit, $viewPaged, $viewDefaultView)
} #endif view doesn't exist
}
}
try
{
$rootweb.Dispose()
$web.Dispose()
}
catch{}
} #if $true/Siteurl is not null, if environment setup is valid
try
{
$rootSite.Dispose()
$site.Dispose()
}
catch{}
} #foreach letter

Adding one field to a SharePoint View in every library in every site

Adding a field every SharePoint View

Sometimes one needs to change a SharePoint library view across all libraries and sites. Here’s how to do it. First loop through sites/webs/libraries and find the target libraries. In this example, I use Content Types enabled as one of the criteria. Next, I delete the field I want to add. This is to make the script safe to re-run. If we didn’t try to delete the field first, we would end up with a view with multiple columns for the same field. Note no Update() method is required to alter a View.

#adds "Field" to right  in Default View; deletes field first, in case it already exists, then moves the field into position. 
Add-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue
$envrun="Prod"			# selects environment to run in
if ($envrun -eq "Dev")
{
# you can always tune Dev to behave differently.  I prefer to make my scripts multi-environment enabled
}
elseif ($envrun -eq "Prod")
{
$siteUrl = "http ://sharepoint/"  #use ytour site colelction URL, or choose to loop through all site collections
}
else
{
Write-Host "ENVIRONMENT SETTING NOT VALID: script terminating..."
$siteUrl =  $null;
return;
}
Write-Host "script starting" 
$myheader = "STARTING: $(get-date)"
$SiteName=$SiteURL
$rootSite = New-Object Microsoft.SharePoint.SPSite($SiteName)
$site=$rootSite  #skipping traversing all sites for now
Write-Host -foregroundcolor darkblue "$($site.id) - $($site.Url) - $($site.contentdatabase.id) - $($site.contentdatabase.name)"   
$rootWeb = $site.RootWeb
$web=$rootWeb;
$JPLists=$web.Lists;
$JPListsCount=$JPLists.Count
for ($i=0;$i -lt $JPListsCount;$i++)
{ 
$JPLib=$JPLists[$i];
$A_Lib_Count++;
$SkipLib=$true; #true
if ( ($JPlib.BaseType -ne "DocumentLibrary") -or ($JPlib.hidden) )
{
# forget the rest and return to top
Write-Host -foregroundcolor green "fast test skipping Library: $($JPlib)";   
Add-Content $mylogfile "Skipping Library: $($JPlib.title)`n";   
}
elseif ($JPLib.Title -Match "SitesAssets|Photo|Image|CustomizedsReports|Templates|Pages|Picture|cache|style|Slide")
{
# forget the rest and return to top
Write-Host -foregroundcolor red "fast test skipping Library because it mentions $Matches: $($JPlib)";   
}
elseif ($JPLib.BaseTemplate -ne "DocumentLibrary")   #alternatively, only skip if -eq XMLForm
{
# forget the rest and return to top
Write-Host -foregroundcolor red "fast skipping Library because it is not of base DocumentLibrary, it is BaseType:$($JPlib.basetemplate): $($JPlib.title)";   
}
elseif (($JPLib.ThumbnailsEnabled) -or ($JPLib.DefaultView -eq "AllSlides"))
{
# forget any library with thumbnails, these are not normal doclibs, and return to top
Write-Host -foregroundcolor red "fast test skipping Library because it has Thumbnails/Slides $($JPlib)";   
}
elseif (!$JPLib.ContentTypesEnabled)
{
Write-Host -foregroundcolor red "skipping because it does not have CTs enabled: $($JPlib)";   
}
else
{  $SkipLib=$false;	}
if (!$SkipLib)
{
write-Host -foregroundcolor green "Processing Library: $($JPlib)";   
try
{
$ListView = $JPLib.Views["All Documents"];  #This is the one view we are looking for
}
catch
{
$ListView=$null;
}
if ($ListView -eq $null)  #let's not try to add a column to a non-existent view.
{
continue;
}
$ListFields=$JPLib.Fields;
$ListViewFields=$ListView.ViewFields;
#We might have duplicate entries; let's delete them all, then when we add the field, we know there's only one field
$stillDeleting=$true;
do {
try   {$ListViewfields.Delete("LinkFilename")}   #note the use of the internal (static) name whenever deleting 
catch {$stillDeleting=$false}
} while ($stillDeleting)
$stillDeleting=$true;   #similar field, just to be sure
do {
try   {$ListViewfields.Delete("LinkFilenameNoMenu")}
catch {$stillDeleting=$false}
} while ($stillDeleting)
#Re-add field
$ListViewFields.add("LinkFilename");
#Move Field to position #2
$ListViewFields.MoveFieldTo("LinkFilename",1);
$ListView.Update();  #note no update() method is required
}
}

Creating a View in each Document Library in a Web Application

Crate a View in each Library in a Web App

My friend Rob Holmes raised an interesting challenge; deploying a new view to all libraries. Here’s the script to apply it to all libraries with Content Types enabled that are Document Libraries, across all libraries in all webs in all site collections of a web application.

Sorting/filtering entries in a view requires the use of CAML, for which I provide a few examples commented in the script. To write CAML, one needs to know the available fields. If you have a $Lib, you can dump the static or internal names for every field in the library with this command:

$Lib.Fields | select internalname

Here’s some CAML examples.

'<OrderBy><FieldRef Name="mvReceived_x0020_Time" Ascending="FALSE" /></OrderBy><Where><IsNotNull><FieldRef Name="mvReceived_x0020_Time" /></IsNotNull></Where>'
'<OrderBy><FieldRef Name="mvSentOn" Ascending="FALSE" /></OrderBy><Where><IsNotNull><FieldRef Name="mvReceived_x0020_Time" /></IsNotNull></Where>'
'<OrderBy><FieldRef Name="mvSentOn" Ascending="FALSE" /></OrderBy><Where><IsNotNull><FieldRef Name="mvSentOn" /></IsNotNull></Where>'

There’s a few good CAML builder tools. You can also just navigate an existing View and grab the XML from the View in SharePoint.

Here’s the script:

Add-PSSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue
$wa=get-spwebapplication http ://sharepoint
Write-Host "script starting $(get-date)"
$wa=get-spwebapplication http ://sharepoint
foreach ($Site in $wa.sites)
{
if ($site.url -like $MatchStr)
{
$webs=$Site.AllWebs
$webcount = $Site.AllWebs.Count
for ($i=0; $i -lt $webcount; $i++)
{
$web=$webs[$i]
Write-Host "working in $($web.url)"
$lists=$web.lists;
for ($k=0; $k -lt $lists.count; $k++)
{
$JPLib = $lists[$k];
#don't bother adding a view to a hidden library
if ($JPLib.Hidden)
{
continue;
}
#only for libraries, not for GenericList and other types
if ($JPLib.BaseType -ne "DocumentLibrary")
{
continue;
}
#choose your own lib filter; this acts on every content type enabled library
if ($JPLib.ContentTypesEnabled)
{
write-host -f green "The Library $($JPLib.title) exists in the site $($web.url), about to tune the view"
try
{
$x=$JPLib.Views.get_Item("Email")
if ($x.id -ne $null) #prevents duplicate entries
{
$JPLib.Views.Delete($x.ID.ToString())
}
}
catch
{}
if ($JPLib.Views["Email"] -eq $null) #prevents duplicate entries
{
#$viewQuery = '<OrderBy><FieldRef Name="mvReceived_x0020_Time" Ascending="FALSE" /></OrderBy><Where><IsNotNull><FieldRef Name="mvReceived_x0020_Time" /></IsNotNull></Where>'
#$viewQuery = '<OrderBy><FieldRef Name="mvSentOn" Ascending="FALSE" /></OrderBy><Where><IsNotNull><FieldRef Name="mvReceived_x0020_Time" /></IsNotNull></Where>'
$viewQuery = '<OrderBy><FieldRef Name="mvSentOn" Ascending="FALSE" /></OrderBy><Where><IsNotNull><FieldRef Name="mvSentOn" /></IsNotNull></Where>'
$viewFields = New-Object System.Collections.Specialized.StringCollection
$viewFields.Add("DocIcon") > $null
$viewFields.Add("LinkFilename") >  $null
$viewFields.Add("Title") >  $null
$viewFields.Add("mvTo") >  $null
$viewFields.Add("mvFrom") >  $null
$viewFields.Add("mvSubject") >  $null
$viewFields.Add("mvSentOn") >  $null
$viewFields.Add("mvAttach_x0020_Count") >  $null
#	 $viewFields.Add("DocType") >  $null # this is accounting specific
#RowLimit property
$viewRowLimit = 50
#Paged property
$viewPaged = $true
#DefaultView property
$viewDefaultView = $false
#$ViewQuery=$null;
$viewTitle="Email"
$newview = $JPLib.Views.Add($viewTitle, $viewFields, $viewQuery, $viewRowLimit, $viewPaged, $viewDefaultView)
}
}
}
}
#} #foreach site
} #if $true/Siteurl is not null, if environment setup is valid
}