T

his post comes in response to a request I received from some of my colleagues at ServiceNow to be able to export a catalog item definition to XML and transport it between instances. I’ve written before about how you can quckly export and import data between ServiceNow instances using the XML export/import context menus. While this works great for a lot of situations, it doesn’t work so great for data that resides in multiple tables, but really makes sense to be exported as a single unit. The components that make up a Catalog item definition are actually stored in over 21 separate tables! It is possible to export a catalog item but you have to do at least 21 separate exports to do it. In this post, I’ll show you how you can set up a UI action to export information from all 21+ tables that make up a catalog item definition…in one click!

Export Full Catalog Item

21+ tables worth of information…in ONE click!

The catalog item export will work for any table extending the ‘sc_cat_item’ table…catalog items, record producers, content items, and order guides! It DOES NOT export associated workflows, delivery plans, or wizard definitions. Workflows can be exported by following the instructions in the Graphical Workflow Export article. The following table information is included.

  • Variables (including question choices)
  • Variable sets (including associated variables, client scripts, and UI policies
  • Client scripts
  • UI policies
  • Additional categories
  • Approved by user and group
  • Available for/Not Available for lists
  • Order guide rule base

The first step is to set up a ‘Processor’ record to handle the export. ServiceNow actually has some built-in code to handle exports like this. You just have to know how to leverage it. Here’s how you would set up a processor for the catalog item export.

‘ExportCatalogItem’ Processor
Name: ExportCatalogItem
Type: Script
Path: export_catalog_item
Script:

(function process(g_request, g_response, g_processor) {
    var sysid = g_request.getParameter('sysparm_sys_id');
    gs.log('** Exporting Catalog Item ' + sysid);
   
    //Name all the related lists
    var exporter = new ExportWithRelatedLists('sc_cat_item', sysid);
    exporter.addRelatedList('item_option_new', 'cat_item');
    exporter.addRelatedList('catalog_script_client', 'cat_item');
    exporter.addRelatedList('catalog_ui_policy', 'catalog_item');
    exporter.addRelatedList('sc_cat_item_category', 'sc_cat_item');
    exporter.addRelatedList('sc_cat_item_catalog', 'sc_cat_item');
    exporter.addRelatedList('sc_cat_item_user_criteria_mtom', 'sc_cat_item');
    exporter.addRelatedList('sc_cat_item_user_criteria_no_mtom', 'sc_cat_item');
    exporter.addRelatedList('sc_cat_item_group_mtom', 'sc_cat_item');
    exporter.addRelatedList('sc_cat_item_group_no_mtom', 'sc_cat_item');
    exporter.addRelatedList('sc_cat_item_company_mtom', 'sc_cat_item');
    exporter.addRelatedList('sc_cat_item_company_no_mtom', 'sc_cat_item');
    exporter.addRelatedList('sc_cat_item_dept_mtom', 'sc_cat_item');
    exporter.addRelatedList('sc_cat_item_dept_no_mtom', 'sc_cat_item');
    exporter.addRelatedList('sc_cat_item_location_mtom', 'sc_cat_item');
    exporter.addRelatedList('sc_cat_item_location_no_mtom', 'sc_cat_item');
    exporter.addRelatedList('sc_cat_item_user_mtom', 'sc_cat_item');
    exporter.addRelatedList('sc_cat_item_user_no_mtom', 'sc_cat_item');
    exporter.addRelatedList('sc_cat_item_app_group', 'sc_cat_item');
    exporter.addRelatedList('sc_cat_item_app_user', 'sc_cat_item');
    exporter.addRelatedList('sc_cat_item_guide_items', 'guide');
    exporter.addRelatedList('pc_vendor_cat_item', 'product_catalog_item');
   
    var catalogID = '';
    var categoryID = '';
    var vsrelID = '';
    var vsID = '';
    var vID = '';
    var qcID = '';
    var uipID = '';
    var actID = '';
    var csID = '';
   
    //Query for Catalogs
    var catalog = new GlideRecord('sc_cat_item_catalog');
    catalog.addQuery('sc_cat_item', sysid);
    catalog.query();
    while(catalog.next()){
        //Get Catalog IDs
        catalogID = catalogID + ',' + catalog.sc_catalog.sys_id.toString();
    }
   
    //Query for Categories
    var category = new GlideRecord('sc_cat_item_category');
    category.addQuery('sc_cat_item', sysid);
    category.query();
    while(category.next()){
        //Get Category IDs
        categoryID = categoryID + ',' + category.sc_category.sys_id.toString();
    }
   
    //Query for variables to get question choices
    var item = new GlideRecord('item_option_new');
    item.addQuery('cat_item', sysid);
    item.query();
    while(item.next()){
        //Query for question choices
        var qc = new GlideRecord('question_choice');
        qc.addQuery('question', item.sys_id.toString());
        qc.query();
        while(qc.next()){
            //Add the variable question sys_id to the variable question string
            qcID = qcID + ',' + qc.sys_id.toString();
        }
    }
   
    //Query for ui catalog ui policies to get policy actions
    var catpol = new GlideRecord('catalog_ui_policy');
    catpol.addQuery('catalog_item', sysid);
    catpol.query();
    while(catpol.next()){
        //Query for ui policy actions
        var uipact = new GlideRecord('catalog_ui_policy_action');
        uipact.addQuery('ui_policy', catpol.sys_id.toString());
        uipact.query();
        while(uipact.next()){
            //Add the ui policy action sys_id to the ui policy action string
            actID = actID + ',' + uipact.sys_id.toString();
        }
    }
   
    //Query for variable set relationships
    var vsrel = new GlideRecord('io_set_item');
    vsrel.addQuery('sc_cat_item', sysid);
    vsrel.query();
    while(vsrel.next()){
        //Add the item set relationship sys_id to the item set string
        vsrelID = vsrelID + ',' + vsrel.sys_id.toString();
        //Get the variable set
        var vs = vsrel.variable_set.getRefRecord();
        if(vs){
            //Add the variable set sys_id to the variable set string
            vsID = vsID + ',' + vs.sys_id.toString();
            //Query for variables in the set
            var v = new GlideRecord('item_option_new');
            v.addQuery('variable_set', vs.sys_id);
            v.query();
            while(v.next()){
                //Add the variable sys_id to the variable string
                vID = vID + ',' + v.sys_id.toString();
                //Query for variable question choices
                var vqc = new GlideRecord('question_choice');
                vqc.addQuery('question', v.sys_id.toString());
                vqc.query();
                while(vqc.next()){
                    //Add the variable question sys_id to the variable question string
                    qcID = qcID + ',' + vqc.sys_id.toString();
                }
            }
           
            //Query for ui policies in the set
            var uip = new GlideRecord('catalog_ui_policy');
            uip.addQuery('variable_set', vs.sys_id.toString());
            uip.query();
            while(uip.next()){
                //Add the ui policy sys_id to the ui policy string
                uipID = uipID + ',' + uip.sys_id.toString();
                //Query for ui policy actions
                var uipa = new GlideRecord('catalog_ui_policy_action');
                uipa.addQuery('ui_policy', uip.sys_id.toString());
                uipa.query();
                while(uipa.next()){
                    //Add the ui policy action sys_id to the ui policy action string
                    actID = actID + ',' + uipa.sys_id.toString();
                }
            }
           
            //Query for client scripts in the set
            var cs = new GlideRecord('catalog_script_client');
            cs.addQuery('variable_set', vs.sys_id.toString());
            cs.query();
            while(cs.next()){
                //Add the client script sys_id to the client script string
                csID = csID + ',' + cs.sys_id.toString();
            }
        }
    }
   
    exporter.addQuerySet('sc_catalog', 'sys_idIN' + catalogID);
    exporter.addQuerySet('sc_category', 'sys_idIN' + categoryID);
    exporter.addQuerySet('io_set_item', 'sys_idIN' + vsrelID);
    exporter.addQuerySet('item_option_new_set', 'sys_idIN' + vsID);
    exporter.addQuerySet('item_option_new', 'sys_idIN' + vID);
    exporter.addQuerySet('question_choice', 'sys_idIN' + qcID);
    exporter.addQuerySet('catalog_ui_policy', 'sys_idIN' + uipID);
    exporter.addQuerySet('catalog_ui_policy_action', 'sys_idIN' + actID);
    exporter.addQuerySet('catalog_script_client', 'sys_idIN' + csID);
    exporter.exportRecords(g_response);
})(g_request, g_response, g_processor);

Once you have your processor set up, you just need to call it. The processor above is called by its path name ‘export_catalog_item’ followed by ‘.do’. It also needs to know what to export so you need to pass it the sys_id of the top-level record that you want to export…in this case, the sys_id of the ‘Catalog item’ record.

‘Export Catalog Item’ UI Action
Name: Export Catalog Item
Table: Catalog Item (sc_cat_item)
Order: 200
Form link: True
Show insert: False
Show update: True
Client True
Hint: Export catalog item definition to .xml file
Onclick callExportCatalogItem();
Condition: gs.hasRole(“admin”)
Script:

function callExportCatalogItem() {
   var url = new GlideURL('export_catalog_item.do');
   url.addParam('sysparm_sys_id', gel("sys_uniqueValue").value);
   var frame = top.gsft_main;
   if (!frame){
      frame = top;
   }

   frame.location = url.getURL();
}

Once you’re done with this, you should have an ‘Export Catalog Item’ UI action context menu item on your ‘Catalog Item’ forms that you can use to transport catalog items, record producers, and order guides in the event that they don’t get captured in an update set.