Monday, August 8, 2016

Convert SharePoint list column / field to a Managed Metadata term set, then update source list to have a taxonomy field with that same value.

We have a few lists that have been around for years at my current client that we needed to reference in many other lists, forms, and applications. Ours was a list of customers. My admin said he wished we had a managed metadata term store with the list of values to be shared across apps, forms, Farms, and even other platforms. So I wrote a quick script to do just that. This is a console application that needs to run on the server.

Here's what it does:
  1. Compliments you on how good you look today.
  2. Asks you for a list of information it needs to run.
    • Url of the Site that has the list, that has the field/column you want to convert to a term set
    • Name of the list that has the field/column that has the values you want to convert to a term set
    • Name of your existing term store (The name of the service application)
    • Name of existing term group the new term set should get created in
    • Name you want the new term set to be called
    • Name of the Managed Metadata column the script will create and populate the value of in the list.
  3. Creates a TaxonomySession, gets a handle on the Termstore and group, and then creates the termset.
  4. Creates the new TaxonomyField (Managed Metadata Column) on the list
  5. Iterates through the list items, grabs the value from the field you want to convert to a termset, creates the term, then populates the MM column.
  6. Outputs errors
So that's it, HTH. If this saves you thousands of hours of copy and paste, click a banner ad, or something ;)

Example of inputs: 

static void Main(string[] args)
        {
            Console.WriteLine("Looking good today, is that a new shirt? Paste in URL of web that hast the customers list we need to use to pupulate the termset please.");
            string sUrl = Console.ReadLine();
            Console.WriteLine("What is the name of list with the column we are converting to a term set?");
            string sListName = Console.ReadLine();
            Console.WriteLine("What is the name of the column we are converting?");
            string sOriginalFieldName = Console.ReadLine();
            Console.WriteLine("What is the name of your termstore? (name of MM service app)");
            string sTermStore = Console.ReadLine();
            Console.WriteLine("Which existing term group do you want the term set in?  (i'll ask for termset name next)");
            string sGroupName = Console.ReadLine();
            Console.WriteLine("What do you want the term set to be called?");
            string sSetName = Console.ReadLine();
            Console.WriteLine("What do you want the new taxonomy column named in the source list?");
            string sColumnName = Console.ReadLine();
            Console.WriteLine();

            //Cache errors to show later
            List errors = new List();

            //Get the site object for the TaxonomySession constructor
            using (SPSite oSPsite = new SPSite(sUrl))
            {
                TaxonomySession ts = new TaxonomySession(oSPsite);

                //Get the termstore and group
                TermStore termStore = ts.TermStores[sTermStore];
                Group group = termStore.Groups[sGroupName];

                //Create the termset and a test term to be sure we're good permissions wise...
                TermSet termSet = group.CreateTermSet(sSetName);
                Term termToDelete = termSet.CreateTerm("temp1", 1033);
                termStore.CommitAll();
                Console.WriteLine("OK term set is created, adding column to list now.");

                //Now get a handle on the list and add the taxonomy field 
                using (SPWeb web = oSPsite.OpenWeb())
                {
                    web.AllowUnsafeUpdates = true;
                    SPList list = web.Lists[sListName];
                    bool fieldExists = list.Fields.ContainsField(sColumnName);
                    if (!fieldExists)
                    {
                        TaxonomyField field = list.Fields.CreateNewField("TaxonomyFieldType", sColumnName) as TaxonomyField;
                        field.SspId = termSet.TermStore.Id;
                        field.TermSetId = termSet.Id;
                        field.TargetTemplate = string.Empty;
                        field.AllowMultipleValues = false; //if you switch this to true, you'd have to change to TaxonomyFieldValueCollection
                        field.CreateValuesInEditForm = true;
                        field.Open = true;
                        field.AnchorId = Guid.Empty;
                        list.Fields.Add(field);
                        list.Update();
                        web.Update();
                        //get a new handle on the list since the schema changed.
                        list = web.Lists[sListName];
                    }

                    //now get a handle on it from the list context for edit later
                    TaxonomyField taxonomyField = list.Fields[sColumnName] as TaxonomyField;

                    foreach (SPListItem item in list.Items)
                    {
                        //get the field value from the list, then create the term with the name
                        string sCustomer = item[sOriginalFieldName].ToString();
                        Console.WriteLine("Creating term for {0}.", sCustomer);
                        //surrond with try/catch incase you have duplicates (the code will let you know at the end)
                        try
                        {
                            Term termCustomer = termSet.CreateTerm(sCustomer, 1033);
                            termStore.CommitAll();

                            //now that ther term exists in the term store, set the value of the new taxonomy field in the listitem
                            TaxonomyFieldValue taxonomyFieldValue = new TaxonomyFieldValue(taxonomyField);
                            taxonomyFieldValue.TermGuid = termCustomer.Id.ToString();
                            taxonomyFieldValue.Label = termCustomer.Name;

                            item[sColumnName] = taxonomyFieldValue;
                            item.SystemUpdate();
                            list.Update();
                        }
                        catch (TermStoreOperationException ex)
                        {
                            errors.Add("Error with " + sCustomer + " - Msg:" + ex.Message);
                        }
                        catch (Exception x)
                        {
                            errors.Add("Error with " + sCustomer + " - err:" + x.Message);
                        }
                    }
                    web.Update();
                    web.AllowUnsafeUpdates = false;
                }//dispose web
            }//dispose site

            Console.WriteLine("Done. Hit Enter to see list of errors we ran into.");
            Console.ReadLine();
            foreach (string er in errors)
            {
                Console.WriteLine(er);

            }
            Console.WriteLine("that's it, hit enter to end program.");
            Console.ReadLine();
        }