How to Get Multi Row variable set name dynamically

suryareddyn
Giga Expert

Below script provides muti row variable set value. How to get Multi Row Variable set internal name dynamically?

 

Example:

1. Multi Row variable set Internal name : account_details

Variables : first_name and  last_name

 

How to get MVR internal name "account_details" dynamically?

==================================================

var now_GR = new GlideRecord('sc_req_item');
now_GR.get('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');

var vars = now_GR.variables.getElements(true);

for (var i=0; i<vars.length; i++) {
    var now_V = vars[i];
    if (now_V.isMultiRow()) {
        gs.info(now_V);
       
    }
}
====================
Script Output:
 

 

[ {
  "first_name" : "User 1 First name",
  "last_name" : "User 1 last name"
}, {
 "first_name" : "User 2 First name",
"last_name" : "User 2 last name" }, { "first_name" : "User 3 First name",
"last_name" : "User 3 last name" } ]
3 REPLIES 3

aasch
Kilo Sage

Hi,
I found myself asking the same question and I'd like to propose a solution.
Tl;dr at the end.

Unfortunately documentation (https://docs.servicenow.com/bundle/washingtondc-application-development/page/script/server-scripting...) goes only so far.
We have no insight into all the specs of GlideRecord.variables and GlideElementVariable.


For a a property to be accessible via dot-notation (e.g. "current.prop_name"), the property has to be present at the object itself or at an object in its prototype chain. That means, we should be able to retrieve its name via Object.keys or even Object.getOwnPropertyNames.


Documentation tells us that MRVSs are present at "current.variables" as properties: "current.variables.table_var".
So in order to retrieve an MRVS' name, we can use Object.getOwnPropertyNames (I checked it; the properties are located at "current.variables" directly, no Object.keys needed) to retrieve the name.

 

Another Community member found out, that you can access the names of regular variables via "current.getElements()[<index>].name":
https://www.servicenow.com/community/developer-articles/for-requested-items-sc-req-item-getting-addi...

We're able to find out all the regular variable's names and we have access to the full list of all variable names including MRVSs.

That means we can loop over the regular variables and remember their names. Then we get the full list of all variable names, filter out the regular variables' names and are left (hopefully) with just the names of the MRVSs.

Disclaimer:
I did test this, it seems to work. We need to be careful though, since this isn't documented well enough.
------

Tl;dr:
Retrieve all regular variables' names via "current.variables.getElements()[<index>].name" (in a proper loop, etc.) and save them.
Retrieve the full list of variable names via "Object.getOwnPropertyNames(current.variables)".
Filter out all regular variables' names from the full list.
-> You're now left with the list of names of all MRVSs of a record.

Sorry, my previous answer is only partially correct.
"Object.getOwnPropertyNames(current.variables)" gives us the names of all Variables and Variable Sets. Not just MRVSs.

But I found decent way to get to MRVSs:

 

 

var allVariableNames = Object.getOwnPropertyNames(current.variables);

var mrvsNames = allVariableNames.filter(function(variableName){

var isMutiRow = ritm.variables[variableName].isMultiRow();

if(isMultiRow){
return variableName;
}

});

 

 

 
"ritm.variables[variableName].isMultiRow()" seems to be possible on its own. You don't have to use .getElements().
Instead of the filter function you could also use a regular for-loop. I just prefer it this way.

With "mrvsNames" you can do "current.variables[mrvsNames[i]]" to get the value of an MRVS.

To transfer the MRVS value to the client, apparently you have to use .toString() on the value you get with "current.variables[mrvsNames[i]]".
Otherwise it shows up as "{}" if you do JSON.stringify on the return variable (or value) of your Script Include.

Hope it helps. Took me some figuring out.
I don't get why handling variables is so mega clunky.

praestegaard
Tera Contributor

I investigated this while searching high and low for a way to recreate a requested item by inserting the original Catalog item variables options and answers as cart variables rather than copying the variables to the new requested item. Reading this article will explain the output format of the multi-set variables.

 

 

function getOriginalRequestOptionAndAnswers(requested_item_id) {

	try {
		var itemVariables = {};
		var itemVariablesArray = [];

		// Iterate option variables (simple)
		var scItemOption = new GlideRecord('sc_item_option_mtom');
		var encodedQuery = 'sc_item_option.value!=NULL^request_item.sys_id=' + requested_item_id;
		scItemOption.addEncodedQuery(encodedQuery);
		scItemOption.query();
		while (scItemOption.next()) {
			var variableName = scItemOption.sc_item_option.item_option_new.name;
			var variableValue = scItemOption.sc_item_option.value.getDisplayValue().trim('"');
			itemVariables[variableName] = variableValue;
		}

		/* Group sc_multi_row_question_answer records by variable_set 
		using GlideAggregate (in case more than one) */
		var mrvsGa = new GlideAggregate('sc_multi_row_question_answer');
		mrvsGa.addQuery('parent_id', requested_item_id);
		mrvsGa.groupBy('variable_set');
		mrvsGa.query();
		while (mrvsGa.next()) {
			var variableSetId = mrvsGa.variable_set.toString();
			var internal_name = mrvsGa.variable_set.internal_name.toString();

			//  Next sub-group sc_multi_row_question_answer by row_index using GlideAggregate
			var mrvsRowsGa = new GlideAggregate('sc_multi_row_question_answer');
			mrvsRowsGa.addAggregate('COUNT');
			mrvsRowsGa.addQuery('parent_id', requested_item_id);
			mrvsRowsGa.addQuery('variable_set', variableSetId);
			mrvsRowsGa.groupBy('row_index');
			mrvsRowsGa.query();
			while (mrvsRowsGa.next()) {
				var keyValuePairs = {};

				var rowIndex = mrvsRowsGa.row_index.toString();

				// Lastly read each option and variablevalue to rebuild multi-row variable as JSON object
				var mrqaVariableSetRowGr = new GlideRecord('sc_multi_row_question_answer');
				mrqaVariableSetRowGr.addQuery('row_index', rowIndex);
				mrqaVariableSetRowGr.query();
				while (mrqaVariableSetRowGr.next()) {
					var optionName = mrqaVariableSetRowGr.item_option_new.name.toString();
					var variableValue = mrqaVariableSetRowGr.value.toString();
					keyValuePairs[optionName] = variableValue;
				}

				/*  Add to the array of key-value pairs. Structure ends like this:
					[{ "key1": "value1", "key2": "value2" }, { "key1": "value1", "key2": "value2" }, {..}] */
				itemVariablesArray.push(keyValuePairs);

			}
			/*  Create a key with the stringified JSON array as value. Structure ends like this:
				'<multi-row variable name>': '[ { "key1":"value1","key2":"value2" },{ "key1":"value1","key2":"value2" },{..}]' */
			itemVariables[internal_name] = JSON.stringify(itemVariablesArray);
		}
		return itemVariables;
	}
	catch (e) {
		gs.error('Script Include: "ServerSideUtil", function "getOriginalRequestOptionAndAnswers": Error: "{0}"', e.message);
	}
}