This is the final of the two-series blog. Before proceeding further, here’s the link to the 1st part, https://realmpksharepoint.wordpress.com/2015/06/19/export-sharepoint-metadata-to-csv-along-with-their-guids/. The objectivity of the entire series has been already defined there so I won’t be re-iterating the same. However, I must re-visit some of the items relevant to the current context. So following are the objectives of this script:
- Import Terms to SharePoint only when they don’t already exist. The search will be done using the Term Name only.
- Can create a Term with the given Guid i.e., Guids can be retained across the servers. This is optional. If you don’t want to use this option, then keep this column blank and the TermSet will be created using a brand new Guid assigned by the SP.
- Deprecate/Un-Deprecate an existing or a new Term. If you want to change this option on a number of pre-existing TermSets or you even want to create the TermSets with the deprecate value on, then simply update the corresponding column in the exported CSV and then run the import script.
- Modify the availability for Tagging option. If you have to change this option on a number of pre-existing or new TermSets then simply update the given CSV accordingly and then run the import script.
- Most importantly, it applies custom sorting to the TermSets. So the TermSet and their child terms will exactly appear in the same order as has been listed in the processing CSV file.
Input
There are three parameters that needs to be set before executing the script. They are:
- $fileName: Full path of the csv file to be imported.
- $termStoreGroupName: Term group name. Please note that the script does not create a term group. Hence do ensure first that the group already exist at SharePoint even if its blank.
- $MMSStore: Name of the managed metadata service.
Here’s the script preview. Download link for the same has been provided in the later segment.
$fileName = "D:\Piyush\TermTest.csv" $termStoreGroupName = "TEST" $isTermAvailable = $true $lcid = 2 $availableId = 3 $descId = 4 $deprecateId = 5 $fstTrmId = 6 $delimiter = ',' $nameDelimiter = "~~" $dictTerms = @{} $dictGuids = @{} $snapinName = "Microsoft.SharePoint.PowerShell" if ((Get-PSSnapin | Where-Object {$_.Name -eq $snapinName }) -eq $NULL) { write-host "SharePoint SnapIn not loaded. Loading..." Add-PSSnapin $snapinName -ErrorAction SilentlyContinue } #Connect to Central Admin $caWebApp = [Microsoft.SharePoint.Administration.SPAdministrationWebApplication]::Local $CAsiteCollectionUrl = $caWebApp.Sites[0].Url $CAsite = Get-SPSite $CAsiteCollectionUrl write-host "Connection made with Central Admin -"$CAsite #Connect to Term Store in the Managed Metadata Service Application $taxonomySession = Get-SPTaxonomySession -site $CAsite $MMSStore = "Managed Metadata Service" $termStore = $taxonomySession.TermStores[$MMSStore] write-host "Connection made with term store -"$termStore.Name #Get TermGroup and TermSet $termStoreGroup = $termStore.Groups[$termStoreGroupName] function ClearAll() { $dictTerms.Clear() $dictGuids.Clear() $CAsite.Dispose() $taxonomySession = $null $termStore = $null } function ApplyOrdering { $isCommit = $false foreach($key in $dictGuids.Keys) { $dictTerms.Get_Item($key).CustomSortOrder = $dictGuids.Get_Item($key) if($isCommit -eq $false) { $isCommit = $true } } if($isCommit -eq $true) { $termStore.CommitAll() } } function CacheTermOrder($ordTerm, $term) { if($ordTerm -ne $null) { Write-Host ("Ord " + $ordTerm.Name) Write-Host ("Exst " + $term.Name) $trmId = [string]$term.Id if($dictGuids.ContainsKey($trmId)) { $existId = $dictGuids.Get_Item($trmId) $newId = [string]$ordTerm.Id if($existId.Contains($newId) -eq $false) { $dictGuids.Set_Item($trmId, ($existId + ":" + $newId)) } } else { $dictGuids.Add($trmId, ([string]$ordTerm.Id)) $dictTerms.Add($trmId, $term) } } } function DeprecateEnableTerms($term, $termDetail) { $isCommit = $false if(($term.IsAvailableForTagging -eq $true) -and ($termDetail[$availableId] -eq "FALSE")) { $term.IsAvailableForTagging = $false $isCommit = $true } if(($term.IsAvailableForTagging -eq $false) -and ($termDetail[$availableId] -eq "TRUE")) { $term.IsAvailableForTagging = $true $isCommit = $true } if(($term.IsDeprecated -eq $true) -and ($termDetail[$deprecateId] -eq "FALSE")) { $term.Deprecate($false) $isCommit = $true } if(($term.IsDeprecated -eq $false) -and ($termDetail[$deprecateId] -eq "TRUE")) { Write-Host "Deprecating..." $term.Deprecate($true) $isCommit = $true } if($isCommit -eq $true) { Write-Host "Commit" $termStore.CommitAll() Write-Host "Deprecate" } } function GetNewName($termSetName) { $splitNameNew = if(([string[]]$termSetName).Length -eq 1){ ([string[]]$termSetName)[0] } else { ([string[]]$termSetName)[1] } Write-Host ("Afetr Split " + $splitNameNew) return $splitNameNew } function GetNamePair($name) { return ($name.Split($nameDelimiter, [StringSplitOptions]::RemoveEmptyEntries)) } function IsAvailableForTagging($termVal) { Write-Host($termVal) if($termVal) { $termVal = $termVal.Replace("`"", "").Trim() #" } if ($termVal -eq "FALSE") { Write-Host("Is False") $isAvailable = $FALSE } else { $isAvailable = $TRUE } } function CreateTerm($termName, $termDesc, $termSet, $isAvailable, $termGuid) { write-host ("Term not Found -" + $termName + " " + $isAvailable) if(([string]::IsNullOrEmpty($termGuid)) -eq $false) { Write-Host ($termName + $termGuid) $term = $termSet.CreateTerm($termName, 1033, ([GUID]$termGuid)) } else { $term = $termSet.CreateTerm($termName, 1033) } $term.IsAvailableForTagging = $isAvailable if($termDesc) { $termDesc = $termDesc.Replace("`"", "").Trim() #" } $term.SetDescription($termDesc, 1033) #$term.Description = "$termDesc.Replace("`"", "").Trim()" $termStore.CommitAll() return $term } function ManageTerm($fstTrmId, $termDetail, $termSet) { $newTerm = $null ++$fstTrmId if(($fstTrmId -lt $termDetail.Length) -and ($termDetail[$fstTrmId])) { $newTermNames = GetNamePair ($termDetail[$fstTrmId].Replace("`"", "").Trim()) #" Write-Host ([string[]]$newTermNames)[0] $newTerm = $termSet.Terms[([string[]]$newTermNames)[0]] if($newTerm -eq $null) { $isAvailable = $TRUE $newTermName = GetNewName $newTermNames Write-Host $newTermName Write-Host "New Name ............................" Write-Host $termSet.Name $newTerm = $termSet.Terms[$newTermName] if($newTerm -eq $null) { if ($termDetail[$availableId] -eq "FALSE") { Write-Host("Is False") $newTerm = CreateTerm $newTermName $termDetail[$descId] $termSet $FALSE $termDetail[$lcid] } else { $newTerm = CreateTerm $newTermName $termDetail[$descId] $termSet $TRUE $termDetail[$lcid] } } } elseif (([string[]]$newTermNames).Length -eq 2) { $newTerm.Name = $newTermNames[1] $termStore.CommitAll() } if([string]::IsNullOrEmpty($termDetail[($fstTrmId + 1)])) { DeprecateEnableTerms $newTerm $termDetail } ManageTerm $fstTrmId $termDetail $newTerm CacheTermOrder $newTerm $termSet } else { Write-Host("Not ENTERED") } } function ManageTerms() { $termData = Get-Content $fileName $termSetName = GetNamePair ($termData[1].Split($delimiter)[0].Replace("`"", "").Trim()) #" $termSetDesc = $termData[1].Split($delimiter)[1].Replace("`"", "").Trim() #" write-host ("Creating TermSet " + ([string[]]$termSetName)[0]) -backgroundcolor blue if ($termStoreGroup -ne $null) { write-host "TermGroup Found -"$termStoreGroupName $termSet = $termStoreGroup.TermSets[([string[]]$termSetName)[0]] if ($termSet -eq $null) { $termNewName = GetNewName $termSetName $termSet = $termStoreGroup.TermSets[$termNewName] if($termSet -eq $null) { $termSet = $termStoreGroup.CreateTermSet($termNewName) #$termSet.SetDescription($termSetDesc, 1033) $termStore.CommitAll() write-host ("Created the TermSet - " + $termSetName) } else { write-host "TermSet Found with new name -"$termSetName } } elseif (([string[]]$termSetName).Length -eq 2) { write-host "Renaming Term from - " + $termSetName[0] + " to " + $termSetName[1] $termSet.Name = $termSetName[1] $termStore.CommitAll() } else { write-host "TermSet Found -"$termSetName } $i = 0 foreach($line in $termData) { if($i -eq 0) { $i++ continue } $termDetail = $line.Split($delimiter) $isTermAvailable = $termDetail[$availableId].Replace("`"", "").Trim() #" $termNames = GetNamePair ($termDetail[$fstTrmId].Replace("`"", "").Trim()) #" $term = $termSet.Terms[([string[]]$termNames)[0]] if ($term -eq $null) { $termNewName = GetNewName $termNames $term = $termSet.Terms[$termNewName] if ($term -eq $null) { Write-Host $termNames Write-Host $termNewName if ($termDetail[$availableId] -eq "FALSE") { Write-Host("Is False") $term = CreateTerm $termNewName $termDetail[$descId] $termSet $FALSE $termDetail[$lcid] } else { $term = CreateTerm $termNewName $termDetail[$descId] $termSet $TRUE $termDetail[$lcid] } } else { write-host "TermSet Found with new name -"$termName } } elseif (([string[]]$termNames).Length -eq 2) { write-host "Renaming Term from - " + $termNames[0] + " to " + $termNames[1] $term.Name = $termNames[1] $termStore.CommitAll() } else { write-host "Term already present- "$termName -foregroundcolor green ManageTerm $fstTrmId $termDetail $term } if([string]::IsNullOrEmpty($termDetail[($fstTrmId + 1)])) { Write-Host "True Found" Write-Host $termDetail DeprecateEnableTerms $term $termDetail CacheTermOrder $term $termSet } $i++ } } else { write-host "TermStore Group Not Found-"$termStoreGroupName -foregroundcolor red } } ManageTerms #Update the Term Store $termStore.CommitAll() Write-Host "Taxonomy created" ApplyOrdering ClearAll
Here’s the link to download the full script.
And here’s the link to download the sample csv file, which is in the required input format.
Key Takeaways
- The option of restoring the TermSets with a pre-defined Guid is not mandatory. If the corresponding column is kept blank in the CSV file, then the TermSets will be created with a new Guid assigned by the SharePoint.
- Custom sorting, by default, will be applied to all the TermSets. So ordering of TermSets is very important here as it is prime objective of the script to import the Terms in the exact order.
- The script has been tested and found working in both SharePoint 2010 as well as SharePoint 2013 on-premise.
- For SharePoint 2010, if the installed version of PowerShell is 2 then each time before running the script, re-start the management shell. There’s a known issue of memory leak in powershell for the given version where the objects memory does not get properly released This, however, is not required for the management shell 2013.
Great script. Works like a charm.
LikeLike
Hi, arrived in your article, looking how to export and import term sets and terms, preserving their Guids.
I think there is a mistake in the script and the corresponding csv file of yours. You fill the Guids at the LCID column of the csv file. This column is for storing the Language LCID.
I have tried to use the names columns (format ‘Name | GUID’), for adding the Guid, as the article suggests: https://docs.microsoft.com/en-us/powershell/module/sharepoint-pnp/import-pnptermset?view=sharepoint-ps . But the import mechanism does not use the provided Guid.
Still searching for the solution…
LikeLike