THURSDAY, JANUARY 19, 2017

Enabling Related List Exports in ServiceNow

S

erviceNow lists contain a lot of very nice capability that allow you to display and access data in a lot of different ways. One of these is the ability to right-click a list header and export the list data in a variety of formats…for external reporting or otherwise. For example, this is particularly useful as an admin when you need to export a list of records to XML and move them to another ServiceNow instance.

While this functionality works great on standard lists, it is completely absent on related lists at the bottom of records displayed in the form view. I can’t count the number of times I wished I could export a filtered related list in the same way you can with a standard list. Fortunately, with a few slight adjustments to some context menu actions in the system, there is a way!

Related List Export

The Solution…

Enabling export capability for related list records in your system can be accomplished by creating some new records in the ‘System UI -> UI Context Menus’ module in your left nav. These records are based on their existing, standard list counterparts so I can show you how to add the ‘Export -XML’ option here and you can add additional options for other formats as needed. Below is the configuration setup for the ‘Export’ menu container and the ‘XML’ export menu option.

‘Export’ UI Context Menu
Table: Global
Menu: List header
Type: Menu
Name: Export
Order: 1045
Active: True
Run onShow Script: True
Condition: ListProperties.isRelatedList() && !ListProperties.isRefList()
onShow Script:

/**
 * This client-side script is used to dynamically change the context menu before it is displayed.
 * It is called before showing the context menu if the Run onShow script flag is checked.
 *
 * The following variables are available to the script:
 *    'g_menu' the context menu that is about to be shown
 *    'g_item' the current context menu item
 *    'g_list' the GlideList2 that the script is running against (only valid for List context menus)
 *    'g_fieldName' the name of the field that the context menu is running against (only valid for List context menus)
 *    'g_fieldLabel' the label of the field that the context menu is running against (only valid for List context menus)
 *    'g_sysId' the sys_id of the row or form that the script is running against
 */

 
/*Hide the 'Export' context menu for defined related lists
No 'query' parameter available for accurate exports*/

if(g_list.getListName().indexOf('.REL:') > -1){
    g_menu.setHidden(g_item);
}

Once you’ve added the ‘Export’ menu option for related lists as shown above, you can add options for the specific types of export options within the menu. Here is the setup for the ‘XML’ export option which you can add by navigating to ‘System UI -> UI Context Menus’ in your left navigation pane. Make sure to put it under the correct Parent menu so that it shows up where you expect!

‘XML’ UI Context Menu
Table: Global
Menu: List header
Type: Action
Name: XML
Parent: Export (Reference the record you just created above)
Order: 300
Active: True
Run onShow Script: False
Condition: gs.hasRole(‘admin’);
Action Script:

/**
 * Script executed on the Client for this menu action
 *
 * The following variables are available to the script:
 *    'g_list' the GlideList2 that the script is running against (only valid for List context menus)
 *    'g_fieldName' the name of the field that the context menu is running against (only valid for List context menus)
 *    'g_sysId' the sys_id of the row or form that the script is running against
 *    'rowSysId' is also set to the sys_id of the row to support legacy actions, but g_sysId is preferred
 */

runContextAction();

function runContextAction() {
    /*Alert if context menu for defined related lists
        No 'query' parameter available for accurate exports*/

    if(g_list.getListName().indexOf('.REL:') > -1){
        alert('Related list exports are not supported for custom defined related lists.');
        return false;
    }
    var relField = g_list.getRelated().split(".");
    var sysparm_rows = g_list.grandTotalRows;
    var num_rows = parseInt(sysparm_rows);
    var sysparm_query = relField[1] + "=" + gel('sys_uniqueValue').value + "^" + g_list.getQuery({orderby: true, fixed: true});
   
    var sysparm_view = g_list.view;
    if (num_rows < g_export_warn_threshold) {
        var dialog = new GwtPollDialog(g_list.tableName, sysparm_query, sysparm_rows, sysparm_view, 'unload_xml');
        dialog.execute();
        return;
    }
    var dialog = new GwtExportScheduleDialog(g_list.tableName, sysparm_query, sysparm_rows, sysparm_view, 'unload_xml');
    dialog.execute();
}

That should be it! Once you’ve added the UI context menus as shown above you’ll be able to export from any related list in the system (with one exception noted below). I think that the most common use case is XML exports for admin users. If you want to enable other exports, you can combine the ‘XML’ setup provided above with the out-of-box Context menu items for CSV, XLS, or PDF.

One Exception!!!

I believe one of the reasons that this functionality isn’t included by default is that there are some related lists in the system (Defined Related Lists) that this won’t work for. The reason that Defined related Lists don’t support exports is that they don’t include a query/filter component that you can get to via the context menu. Because of this, you’ll end up exporting all of the records in the table instead of the filtered related list.

I’ve included checks in the UI Context Menu records above to disable this functionality on defined related lists in your system. While these types of lists are extremely useful they’re also much less common so it isn’t much of an issue. Here are a couple of links to help you understand more about Defined Related Lists in ServiceNow.

http://www.servicenowguru.com/system-definition/relationships/defined-related-lists/
http://wiki.servicenow.com/index.php?title=Creating_Defined_Related_Lists

7 Comments

kalai 24-07-2014, 02:32

this is good. but have question though ..
why to create a new one, when we can open the related list in a new window using ‘open new window’ option and export it ?

Reply
Mark Stanger 24-07-2014, 07:20

While it’s true that you can right-click a breadcrumb and open it in a new window, this method is nice because it’s more consistent and intuitive for all users of the system.

Reply
Robert Fedoruk 12-08-2014, 12:34

Not to mention that “open new window” will subvert the context of your main window the next time you refresh.

Reply
Anon 03-10-2014, 11:45

I noticed that if you export to excel it seems to use the columns specified by the system, and not the columns you may have personalized via gear icon.

Reply
Matt 12-11-2014, 09:57

I am also seeing the same issue as Anon. The export appears to be using the personalized columns for the table and not the set personalized for the related list.

Other than that, this is very useful functionality.

Reply
John Stettin 03-02-2016, 14:00

I know this is an old post but figured since it helped me find this solution maybe this will help someone else. I had a need to export a defined related list to CSV. You could also just create an encoded query and poll any table dynamically. You can also just modify the function to accept a view param and pass the view value instead of using the view from the current form.

function doStuff() {
   var sysparm_table = "";
   var sysparm_sys_id = g_form.getValue('u_number');  
   var sysparm_query = "parent=" + sysparm_sys_id;

   //Define the related list table
   sysparm_table = 'my_related_table';
   runContextAction(sysparm_table, sysparm_query);
}

function runContextAction(sysparm_table, sysparm_query) {
  //Obtains the rows number of the current report
  var sysparm_rows1 =$$('.list_row_number_input span')[1].innerHTML;

  //Parses string value into an integer value
  var num_rows = parseInt(sysparm_rows1);

  //Get view name needed to export
  var sysparm_view =gel('sysparm_view').value;

  //Creates export file if rows is less than limit value
  if (num_rows &lt; g_export_warn_threshold) {
     var dialog = new GwtPollDialog(sysparm_table, sysparm_query, sysparm_rows1, sysparm_view, "unload_excel");
     dialog.execute();
     return;
  }
  var dialog = new GwtExportScheduleDialog(gel("sysparm_table").value, sysparm_query, sysparm_rows1, sysparm_view, "unload_excel");
  dialog.execute();
  return;
}
Reply
Mark Stanger 04-02-2016, 16:46

Thanks John!

Reply

Leave a Reply


Latest Comments

  • David: It appears that I can hit sys_properties table with REST. This works, but I haven’t yet discovered the...
  • Mark Stanger: Hey David, It doesn’t surprise me that scoped apps have made this more difficult. I’m not...
  • David: Mark, do you have an example of how to do this in a scoped app? It seems there are many hoops to jump through...
  • Mark Stanger: The only possibility is to create a system property to override this in your application. Check out the...