Programmatically: Create multiple term sets from one csv file
Taxonomy is just one of my favorites in SharePoint 2010. Microsoft have done a good work by listing to what customers wanted for years
In my case I wanted to create metadata tree programmatically and started to look at different options:
- I could use XML and PowerShell as Ben Robb did.
- Or using the taxonomy API as Cawood did on his great article
For me I thought that it would be much easier to a SharePoint site admin to create a CSV file and keep track on taxonomy changes. And it is also easier for the developer to create a feature based on that.
The TechNet article “Managed metadata input file format” will show exactly how CSV import file should be and describes how to create a simple organized hierarchy. I did not find on that article something about creating many term sets from just one CSV file and that was because i did ignore the first line
Managed metadata in SharePoint Server 2010 is imported from a comma-separated values (csv) file. Each file must contain one term set, and the terms within the term set may be nested as many as seven levels deep.
I refused to believe that this file could just create one term set at the time. I was thinking that there is no way that Microsoft would put such limitation on such a good feature
So I tried many different ways to edit this file to be able to import many term sets. My way to tested was to upload the file manually using Central Administration Term Store Management Tool. I got always this error:
After couple of wasted hours I realized that I have to accept that this is actually a limitation of this feature so I came with a workaround. My workaround is basically adding a separator inside the CSV file, in my example <NewTerm>. The CSV file will look like this:
"Term Set Name,"Term Set Description","LCID","Available for Tagging","Term Description","Level 1 Term","Level 2 Term","Level 3 Term","Level 4 Term","Level 5 Term","Level 6 Term","Level 7 Term" "Countries","Counties in North Europe",,True,,"Norway",,,,,, ,,,True,,"Denmark",,,,,, ,,,True,,"Sweden",,,,,, ,,,True,,"Finland",,,,,, ,,,True,,"Island",,,,,, <NewTerm> "Term Set Name,"Term Set Description","LCID","Available for Tagging","Term Description","Level 1 Term","Level 2 Term","Level 3 Term","Level 4 Term","Level 5 Term","Level 6 Term","Level 7 Term" "Currency","Currencies in North Europe.",,True,,"Krone",,,,,, ,,,True,,"Krona",,,,,, ,,,True,,"Euro",,,,,, <NewTerm> "Term Set Name,"Term Set Description","LCID","Available for Tagging","Term Description","Level 1 Term","Level 2 Term","Level 3 Term","Level 4 Term","Level 5 Term","Level 6 Term","Level 7 Term" "Government types","Government types in North European countries",,True,,"Monarchy",,,,,, ,,,True,,"Republic",,,,,, <NewTerm>
By the way, there is a good macro enabled template that will help you create this file faster. Check Wictor Wilén blog on that.
Add this method to your code, such as feature activation.
protected bool CreateTaxonomyTermSets(string CSVFilePath)
{
try
{
TaxonomySession Taxosession = new TaxonomySession(myportalsite);
if (Taxosession.TermStores.Count != 0)
{
TermStore termStore = Taxosession.TermStores[NameofDefaultTermStore];
Microsoft.SharePoint.Taxonomy.Group termGroup;
try
{
// Create Term Group with properties
termGroup = termStore.CreateGroup(NameOfTermStoreGroup);
termGroup.Description = "Group description";
termGroup.AddGroupManager("Domain\\User");
termGroup.AddContributor("Domain\\User");
}
catch (ArgumentException)
{
// Group name already exists
termGroup = termStore.Groups[NameOfTermStoreGroup];
foreach (TermSet termSet in termGroup.TermSets)
{
termSet.Delete();
}
}
// Add termsets and terms to the term store from a CSV file
FileStream TermsFile = new FileStream(CSVFilePath, FileMode.Open, FileAccess.Read);
reader = new StreamReader(TermsFile);
string[] TermsInCSVFile = Regex.Split(reader.ReadToEnd(), "\r\n");
//ImportManager impmanager = termGroup.TermStore.GetImportManager();
foreach (string term in TermsInCSVFile)
{
ImportManager impmanager = termGroup.TermStore.GetImportManager();
StringReader termreader = new StringReader(term);
impmanager.ImportTermSet(termGroup, termreader, out allTermsAdded, out errorMessage);
if (!allTermsAdded)
{
// report failure and rollback changes if not all terms are added correctly
EventLog.WriteEntry("CSV File Import", errorMessage, EventLogEntryType.Error, 101);
termStore.RollbackAll();
return false;
}
}
termStore.CommitAll();
}
return true;
}
catch (Exception ex)
{
<pre>// report failure on exception</pre>
EventLog.WriteEntry(ex.Source, ex.Message, EventLogEntryType.Error, 101);
return false;
}
finally
{
if (reader != null)
{
reader.Close();
}
}
}
