Custom sort order

Aug 2, 2011 at 4:17 AM
Edited Aug 2, 2011 at 4:17 AM

Hi shailensukul,

I'm wondering about the possibility of exporting/importing the custom sort order with the terms. I've found Taxomatic invaluable to backup and restore terms, but after an import the custom sort needs to be set again manually.

Since the custom sort is just a string value applied to each term (signifying the positions of its children), is this something that may be added in future?

I'm considering creating a tool to backup and restore the custom sort values (perhaps just a console app that iterates through each term and backs up the string with the term GUID as a key), but I'm wondering if there's something I'm missing. Is there a reason (apart from development time!) that it's not already included in Taxomatic?

Many thanks!

Coordinator
Aug 18, 2011 at 5:34 PM

Great point! I will have to look into a new release in October as we are expecting a child any time this week and then I will be tied up for a while. If you really need this feature and want to code, I can give you contribute rights to the code. Let me know.

Thanks

Shailen

Aug 24, 2011 at 6:15 AM

Thanks for the reply, and congrats on the baby!

For the time being I've gone with my own solution of a console app to do the order backup/restore and since it was a one-off requirement I no longer have a pressing need for it.

Thanks again, and good luck!

Coordinator
Aug 24, 2011 at 7:28 AM
Edited Aug 24, 2011 at 2:00 PM

Thanks.

Please post the code here when you can.

Dec 18, 2012 at 4:18 AM

Hi Shailen,

I missed your last post until now, I'm sorry. This was a rushed job with poor error handling, security, and general inefficiencies. It probably misses tons of edge-cases, but it worked for me the one time I needed it. But you might find the general gist of it useful.

 

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Xml;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Taxonomy;

namespace CustomSort
{
    internal class CustomSort
    {
        private static void Main(string[] args)
        {
            try
            {
                if (args.Length == 4)
                {
                    if (args[0] == "export")
                    {
                        Export(args[1], args[2], args[3]);
                    }
                    else if (args[0] == "import")
                    {
                        Import(args[1], args[2], args[3]);
                    }
                    else if (args[0] == "exporttask")
                    {
                        string fileName = string.Format("{0}\\customsort_{1}.xml", args[2].TrimEnd('\\'),
                                                        DateTime.Now.ToString("yyyyMMdd'_'HHmmss"));
                        Export(args[1], fileName, args[3]);
                    }
                    else
                    {
                        PrintHelp();
                    }
                }
                else
                {
                    PrintHelp();
                }
            }
            catch (UnauthorizedAccessException)
            {
                Console.WriteLine(
                    "You have insufficient permissions to perform this operation. Please ensure that you have the ability to administer the term store.");
            }
            catch (Exception e)
            {
                Console.WriteLine(e.GetBaseException().Message);
            }

            //Console.WriteLine("{0}Press any key to continue ...", System.Environment.NewLine);
            //Console.ReadKey();
        }

        private static void Import(string siteUrl, string fileName, string termStoreName)
        {
            using (var siteCol = new SPSite(siteUrl))
            {
                Dictionary<string, string> customSort = ReadFromXml(fileName);
                var session = new TaxonomySession(siteCol);
                TermStore termStore = session.TermStores[termStoreName];
                Console.WriteLine("Import started");

                foreach (string termId in customSort.Keys)
                {
                    var termGuid = new Guid(termId);
                    Term term = termStore.GetTerm(termGuid);

                    if (term != null)
                    {
                        Console.WriteLine("Ordering Term: " + term.Name);
                        term.CustomSortOrder = customSort[termId];
                    }
                    else
                    {
                        // it may be a term set
                        TermSet termSet = termStore.GetTermSet(termGuid);

                        if (termSet != null)
                        {
                            Console.WriteLine("Ordering Term Set: " + termSet.Name);
                            termSet.CustomSortOrder = customSort[termId];
                        }
                        else
                        {
                            Console.WriteLine("Term or Set not found: " + termId);
                        }
                    }
                }

                // commit changes
                termStore.CommitAll();
            }
        }

        private static void Export(string siteUrl, string fileName, string termStoreName)
        {
            using (var siteCol = new SPSite(siteUrl))
            {
                var customSort = new Dictionary<string, string>();
                var session = new TaxonomySession(siteCol);

                TermStore termStore = session.TermStores[termStoreName];

                if (termStore != null)
                {
                    Console.WriteLine("Export started");

                    foreach (Group group in termStore.Groups)
                    {
                        if (@group != null)
                        {
                            foreach (TermSet termSet in @group.TermSets)
                            {
                                if (!string.IsNullOrEmpty(termSet.CustomSortOrder))
                                {
                                    Console.WriteLine("Adding TermSet: " + termSet.Name);
                                    customSort.Add(termSet.Id.ToString(), termSet.CustomSortOrder);
                                }

                                foreach (Term term in termSet.Terms)
                                {
                                    TraverseTree(term, customSort);
                                }
                            }
                        }
                    }

                    // write dictionary to xml
                    Console.WriteLine("Writing custom sort information to " + fileName);
                    WriteToXml(customSort, fileName);
                    Console.WriteLine("Done");
                }
                else
                {
                    Console.WriteLine("Term store not found.");
                }
            }
        }

        private static void TraverseTree(Term term, Dictionary<string, string> customSort)
        {
            if (!string.IsNullOrEmpty(term.CustomSortOrder))
            {
                Console.WriteLine("Adding Term: " + term.Name);
                customSort.Add(term.Id.ToString(), term.CustomSortOrder);
            }

            foreach (Term childTerm in term.Terms)
            {
                if (!string.IsNullOrEmpty(childTerm.CustomSortOrder))
                {
                    TraverseTree(childTerm, customSort);
                }
            }
        }

        private static void PrintHelp()
        {
            Console.WriteLine("Usage:");
            Console.WriteLine(@"  customsort <import|export> <xml file> <site collection address> <term store name>");
            Console.WriteLine(@"  customsort export c:\customsort.xml http://sitecol.local ""Managed Metadata Service""");
            Console.WriteLine(@"  customsort exporttask c:\pathonly http://sitecol.local ""Managed Metadata Service""");
        }

        private static void WriteToXml(Dictionary<string, string> customSort, string fileName)
        {
            var writer = new FileStream(fileName, FileMode.Create);
            var ser = new DataContractSerializer(typeof (Dictionary<string, string>));
            ser.WriteObject(writer, customSort);
            writer.Close();
        }

        private static Dictionary<string, string> ReadFromXml(string fileName)
        {
            var fs = new FileStream(fileName, FileMode.Open);
            XmlDictionaryReader reader = XmlDictionaryReader.CreateTextReader(fs, new XmlDictionaryReaderQuotas());
            var ser = new DataContractSerializer(typeof (Dictionary<string, string>));

            // Deserialize the data and read it from the instance.
            var customSort = (Dictionary<string, string>) ser.ReadObject(reader, true);
            reader.Close();
            fs.Close();

            return customSort;
        }
    }
}