Setting Metadata Defaults for Folders
SharePoint Libraries can be configured with metadata defaults for documents added to specific folders.
Column Defaults are manually configurable in Library Settings. For each folder that has metadata defaults, the folder is marked with a green stamp.
Any document added to the folder gets the default metadata by default
This configuration can be done using PowerShell. In this example, I have created Folder Content Types, by defining them as inheriting from the Folder Content Type, then adding metadata to the folder Content Types. This makes it easy to then assign the metadata defaults.
We can clear away any existing metadata defaults on a folder using these commands to grab a metadata defaults object, then call the RemoveAllFieldDefaults() method:
[Microsoft.Office.DocumentManagement.MetadataDefaults] $columnDefaults = new-object Microsoft.Office.DocumentManagement.MetadataDefaults($JPLib); $nuthin=$columnDefaults.RemoveAllFieldDefaults($JPFolder.Folder); $columnDefaults.update() |
We can assign a metadata default for one field for one folder using these commands:
[Microsoft.Office.DocumentManagement.MetadataDefaults] $columnDefaults = new-object Microsoft.Office.DocumentManagement.MetadataDefaults($JPLib); $nuthin=$columnDefaults.SetFieldDefault($JPFolder.Folder, $InternalName, $AssignmentValue); $columnDefaults.update() |
Before we get to the script, it is very important to note that get SPSite and SPWeb object must be acquired using the precise correct case.
It seems the case-sensitive XML underlying these calls is affected by an incorrect case; the folders will get the green stamp, but the metadata defaults won’t be applied unless the case is exactly correct.
To get around this problem, you can grab all SPSites for a Web Application and pipe them to get the SPWebs to process.
The only problem with that approach is the extreme memory inefficiency.
More than that, until the objects are totally released, the changes accrue in the SQL Transaction Log until released, allowing .NET to commit them.
Also note the SPFolder object does not require an update(), as the metadata default methods handle the update.
Here’s the full script:
#already matched to the Claim Folder Fields on 9/4/12 to confirm all necessary fields are included. no changes actually made. #Added CT filtering on these folder CTs: Claim Acct Folder|Claims Common Folder [system.reflection.assembly]::LoadWithPartialName("Microsoft.SharePoint") $Action="WipeAndApplyDefaults" #$Action="ApplyDefaults" #$Action="WipeDefaults" $FolderFields="Field1,Field2,Field3" $FolderFieldsArr=$FolderFields.split(","); $baseURL="http ://SharePoint/ManagedPath/" $SiteURL="http ://SharePoint/ManagedPath/a" $OutputSuffix="A" $mylogfile=$mylogfile="L:PowerShellLoggingMetadataDefaults$($OutputSuffix).csv" #$WebAppHeading="http ://SharePoint" Write-Host ("$(get-date) Running script assign metadata defaults to folders") if ($siteurl) { write-host $site.Url $WebScope=start-SPAssignment $TargetWeb=$WebScope | Get-SPWeb $siteURL; $ListOfLists = @(); # Loop through all doc libs $lists=$TargetWeb.lists; $listsCount=$lists.count for ($ii=0; $ii -lt $listsCount; $ii++) { $JPlib=$lists[$ii]; if ( ($JPlib.BaseType -ne "DocumentLibrary") -or ($JPlib.hidden) ) { # forget the rest and return to top Write-Host -foregroundcolor darkred "fast test skipping Library: $($JPlib)"; } elseif ($JPLib.Title -Match "Photo|Image|SitesAssets|CustomizedsReports|Templates|Pages|Picture|cache|style") { # forget the rest and return to top Write-Host -foregroundcolor darkred "fast test skipping Library because it mentions $Matches: $($JPlib)"; } else { $ListOfLists += $JPlib.title; } } $TargetWeb.dispose(); $JPlib=$null; stop-SPAssignment $WebScope foreach ($CurrentLib in $ListofLists) { $WebScope=start-SPAssignment $TargetWeb=$WebScope | Get-SPWeb $siteURL; $JPlib=$TargetWeb.lists[$CurrentLib]; $JPlib.title if ($JPlib -eq $null) { Write-Host "COULD NOT GET LIB $($CurrentLib)" continue; } $JPFolders=$JPlib.Folders; $JPCount=$JPFolders.get_count(); for ($i=0; $i -lt $JPCount; $i++) #Do not use ItemCount, that one includes folders! { $JPFolder=$JPFolders[$i]; $CT=$JPFolder.contenttype.name; if ($CT -notmatch "Folder CT1|Folder CT2") { Write-Host "+" -NoNewline if (($Action -eq "WipeDefaults") -or ($Action -eq "WipeAndApplyDefaults")) { [Microsoft.Office.DocumentManagement.MetadataDefaults] $columnDefaults = new-object Microsoft.Office.DocumentManagement.MetadataDefaults($JPLib); $nuthin=$columnDefaults.RemoveAllFieldDefaults($JPFolder.Folder); $columnDefaults.update() } if (($Action -eq "ApplyDefaults") -or ($Action -eq "WipeAndApplyDefaults")) { foreach ($FF in $FolderFieldsArr) { try { if ($JPFolder[$FF] -ne $null) { $TargetField=$JPFolder.Fields[$FF]; $InternalName=$TargetField.InternalName; if (($TargetField.type -eq "DateTime") -or ($TargetField.type -eq "Date")) { $AssignmentValue=Get-Date $JPFolder[$FF] -Format u; #Z style universal format for assignment } else { $AssignmentValue=$JPFolder[$FF].tostring() } #Leaves open all kinds of field type challenges, such as Managed Metadata if ($AssignmentValue -ne $null) { [Microsoft.Office.DocumentManagement.MetadataDefaults] $columnDefaults = new-object Microsoft.Office.DocumentManagement.MetadataDefaults($JPLib); $nuthin=$columnDefaults.SetFieldDefault($JPFolder.Folder, $InternalName, $AssignmentValue); $columnDefaults.update() } } } catch { Write-Host "problem with field $($FF)" } #must have been a field I shouldn't be poking, no biggie } } #Action=ApplyDefaults #folder update is not required, columnDefault update propagates immediately } } # loop for items $JPlib.Update(); $JPlib=$null; $Targetweb.update() $TargetWeb.dispose(); Stop-SPAssignment $WebScope } #Only process this lib }# Lib loop Write-Host "SCRIPT COMPLETE $(get-date)" |
Want to talk?
Drop us a line. We are here to answer your questions 24*7.