It is a well known fact that we can import term set in SharePoint using a CSV file. This is particularly helpful when you are working in multiple on-premise environments/multi-tenant environment and you want to replicate a deep and complex term hierarchy everywhere. This can be very tedious if done manually. Also, you may not always have the liberty to use server side code with SharePoint online to export the term set. Here, we'll explore a way to export a term set in CSV file using JavaScript only.
Note, the implementation does not work in IE (I have tested this in IE 9) because of the way we export data to CSV from client-side. But it works very well in Chrome. I did not have much time to explore the reason for this but I plan to do so in the near future :)
The format of CSV which is acceptable during import is provided to us as a sample file in SharePoint. To see the format, navigate to Term store management and click on the Taxonomy node.
The columns in the CSV are in the following order
"Term Set Name", "Term Set Description", "LCID", "Available for Tagging", "Term Description", "Level 1 Term", "Level 2 Term"......"Level 'n' Term".
You can see from the test file to write each term, a proper hierarchy has to be maintained.
For testing purpose, I have created two term groups, one to Export a term set and one to import from CSV. The term set contains 'Regions'
get_pathOfTerm() :
Before going into the code, I want to mention this method which has made writing the hierarchy of term set to CSV so easy !! When we use the "getAllTerms()" method on a term set, the terms are returned without its hierarchy details. So if we have to write the terms according to the hierarchy, we might have to take the longer route and iterate through each term and its children. This is where "get_pathOfTerm()" comes to our rescue. This method returns the hierarchy of a particular term, with each level separated by a semi-colon ';'. What this means is, referring to the above screenshot (term set hierarchy) if I get the path of the term "New York", the value returned is
North America;USA;New York
Now, we anyway need the values as comma separated since we are writing it to a CSV. Just replace the semi-colon with comma and you have the string for the entire hierarchy of a term you want to write.
I have developed a simple SharePoint hosted app to demo this. We will provide the GUID of a term set to our app which then exports that particular term set. To get GUID of a term set, click on the term set that you want to export in Term Management and in the right pane you'll find the unique identifier at the bottom.
Import this into a term set.
Here is the full code of the functionality
I found the method to export data to CSV using JavaScript on Raymond Camden's blog.
Hope this helps !
Note, the implementation does not work in IE (I have tested this in IE 9) because of the way we export data to CSV from client-side. But it works very well in Chrome. I did not have much time to explore the reason for this but I plan to do so in the near future :)
The format of CSV which is acceptable during import is provided to us as a sample file in SharePoint. To see the format, navigate to Term store management and click on the Taxonomy node.
The columns in the CSV are in the following order
"Term Set Name", "Term Set Description", "LCID", "Available for Tagging", "Term Description", "Level 1 Term", "Level 2 Term"......"Level 'n' Term".
You can see from the test file to write each term, a proper hierarchy has to be maintained.
For testing purpose, I have created two term groups, one to Export a term set and one to import from CSV. The term set contains 'Regions'
get_pathOfTerm() :
Before going into the code, I want to mention this method which has made writing the hierarchy of term set to CSV so easy !! When we use the "getAllTerms()" method on a term set, the terms are returned without its hierarchy details. So if we have to write the terms according to the hierarchy, we might have to take the longer route and iterate through each term and its children. This is where "get_pathOfTerm()" comes to our rescue. This method returns the hierarchy of a particular term, with each level separated by a semi-colon ';'. What this means is, referring to the above screenshot (term set hierarchy) if I get the path of the term "New York", the value returned is
North America;USA;New York
Now, we anyway need the values as comma separated since we are writing it to a CSV. Just replace the semi-colon with comma and you have the string for the entire hierarchy of a term you want to write.
I have developed a simple SharePoint hosted app to demo this. We will provide the GUID of a term set to our app which then exports that particular term set. To get GUID of a term set, click on the term set that you want to export in Term Management and in the right pane you'll find the unique identifier at the bottom.
Import this into a term set.
Here is the full code of the functionality
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<asp:Content ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server"> | |
<script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.1.min.js"></script> | |
<script type="text/javascript" src="/_layouts/15/sp.runtime.js"></script> | |
<script type="text/javascript" src="/_layouts/15/sp.js"></script> | |
<script type="text/javascript" src="/_layouts/15/sp.requestexecutor.js"></script> | |
<script type="text/javascript" src="../Scripts/Exporttermset.js"></script> | |
<!-- Your CSS stylesheet and JavaScript references go here --> | |
</asp:Content> | |
<%-- The markup and script in the following Content element will be placed in the <body> of the page --%> | |
<asp:Content ContentPlaceHolderID="PlaceHolderMain" runat="server"> | |
<label>Enter the term set ID : </label> | |
<input id="inputTermSetId"></input> | |
<input type="button" value="Export term set" id="btnExport" onclick="ExportTermSet()"></input> | |
<a id="downloadLink" href="" download="data.csv"/> | |
</asp:Content> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
var hostWebUrl; | |
var appwebUrl; | |
var context; | |
var taxonomySession; | |
var termStore; | |
var termSet; | |
var terms; | |
(function(){ | |
hostWebUrl = decodeURIComponent(GetQueryStringParameter("SPHostUrl")); | |
appwebUrl = decodeURIComponent(GetQueryStringParameter("SPAppWebUrl")); | |
$.getScript(hostWebUrl + "/_layouts/15/SP.RequestExecutor.js",function(){ | |
$.getScript(hostWebUrl + "/_layouts/15/SP.Taxonomy.js",function(){ | |
}) | |
}); | |
})(); | |
function ExportTermSet() | |
{ | |
var termSetID = ""; | |
termSetID = $("#inputTermSetId").val(); | |
if(termSetID !== "") | |
{ | |
context = SP.ClientContext.get_current(); | |
taxonomySession = SP.Taxonomy.TaxonomySession.getTaxonomySession(context); | |
// Using the default term store. This can be modified to get by ID if required. | |
termStore = taxonomySession.getDefaultSiteCollectionTermStore(); | |
// Gets the term set with the specified ID | |
termSet = termStore.getTermSet(termSetID); | |
terms = termSet.getAllTerms(); | |
context.load(termSet); | |
context.load(terms); | |
context.executeQueryAsync(function(){ | |
GenerateCSV(); | |
}, | |
function(sender,args){ | |
alert("An error has occurred while accessing taxonomy term store : " + args.get_message()); | |
}) | |
} | |
else | |
{ | |
alert("Enter a term set ID"); | |
} | |
} | |
function GenerateCSV() | |
{ | |
var downloadLink = $("#downloadLink"); | |
var termSetName = termSet.get_name(); | |
var termSetDescription = termSet.get_description(); | |
var maxLevels = 0; | |
var termValues = []; | |
// For some reason the term set description had newline character appended to it which should be removed. | |
termSetDescription = termSetDescription.replace(/(\r\n|\n|\r)/gm,""); | |
var termEnumerator = terms.getEnumerator(); | |
while(termEnumerator.moveNext()){ | |
var currentTerm = termEnumerator.get_current(); | |
// Path returns the hierarachy of the terms separated by ";" | |
var termPath = currentTerm.get_pathOfTerm(); | |
var termDescription = currentTerm.get_description(); | |
var termAvailable = currentTerm.get_isAvailableForTagging(); | |
var levels = termPath.split(";").length; | |
// Depending on number of ';', we calculate the max depth of the term set. | |
// This will be useful to decide the number of columns in the CSV | |
if(levels > maxLevels) | |
{ | |
maxLevels = levels; | |
} | |
// Replace the ";" character by ','. Since we are writing CSV, this will be helpful | |
var strTermValues = termPath.replace(/;/g, ","); | |
// Generate an array of the terms. | |
termValues.push({Terms:strTermValues, | |
TermDescription:termDescription, | |
TermAvailable:termAvailable, | |
Levels:levels}); | |
} | |
// Sort the array based on levels. This is required to generate the CSV properly | |
// to ensure say term at level 5 does not appear above term at level 3 | |
termValues.sort(function(a,b){ | |
return a.Levels - b.Levels; | |
}); | |
var CSVFirstRow = "Term Set Name,Term Set Description,LCID,Available,Term Description"; | |
for(var i=1;i<maxLevels+1;i++) | |
{ | |
CSVFirstRow += ",Level " + i + " Term"; | |
} | |
// LCID is left blank. | |
// TermValues[0] to write the first term of the term set | |
var CSVSecondRow = termSetName + "," + termSetDescription + "," + "" + "," + termValues[0].TermAvailable + "," + termValues[0].TermDescription + "," + termValues[0].Terms; | |
var csvContent = CSVFirstRow + "\n" + CSVSecondRow + "\n"; | |
// Write remaining terms starting from index 1 | |
for(var j=1;j<termValues.length;j++) | |
{ | |
csvContent = csvContent + " , , ," + termValues[j].TermAvailable + "," + termValues[j].TermDescription + "," + termValues[j].Terms + "\n"; | |
} | |
downloadLink.attr("href", 'data:Application/octet-stream,' + encodeURIComponent(csvContent))[0].click(); | |
alert("Term set '"+ termSetName +"' exported successfully"); | |
} | |
function GetQueryStringParameter(parameterName) | |
{ | |
var params = document.URL.split("?")[1].split("&"); | |
for(var i=0;i<params.length;i++) | |
{ | |
var param = params[i].split("="); | |
if(param[0]==parameterName) | |
return param[1]; | |
} | |
} | |
I found the method to export data to CSV using JavaScript on Raymond Camden's blog.
Hope this helps !