Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

How to create several catalog item requests from one form?

gunishi
Tera Guru

Hi all, 

 

I have a requirement where there on a catalog item request form there is an attachment (of excel format). 

 

If there is one row I want to autofill a field on the form with that item. If there are multiple rows I want to create several catalog item requests that have the same 'requested for' value, but are then filled in with the value of the row in the excel spreadsheet. 

 

I am very confused as to how to go about this and would appreciate any pointers, hints or tips.

 

Thank you, 

G

1 ACCEPTED SOLUTION

Brad Bowman
Kilo Patron
Kilo Patron

One approach is to populate a MRVS from the Excel contents.  Use a script like this as a workflow Run Script activity at the beginning of your workflow.

var att = new GlideRecord('sys_attachment');
//att.addQuery('file_name', 'serial number import.xlsx'); //use this line if the attachment will always have a known/same name
att.addQuery('content_type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
att.addQuery('table_sys_id', current.sys_id);
att.orderByDesc('sys_created_on');
att.query();
if(att.next()){
	var imp = new sn_impex.GlideExcelParser();
	var attachment = new GlideSysAttachment();
	var attachmentStream = attachment.getContentStream(att.sys_id.toString());
	imp.parse(attachmentStream);
    var headers = imp.getColumnHeaders();
	var model = headers[0];
	//var snt = headers[1]; use lines like this if you have multiple columns in the spreadsheet
    var mrvs = current.variables.network_gear_asset_mrvs; //internal name of your MRVS
	var newRow = '';
	while(imp.next()) {
		var row = imp.getRow();
        newRow = mrvs.addRow();
		newRow.v_mrvs_model = row[model];
	}
}

Now you have the REQ that was created when the Catalog Item was submitted, and ONE RITM with a MRVS populated for the one or many rows of the attached Excel file.  Next, use a workflow Run Script to update the one RITM to autofill a variable, if you want to do that, based on the first or only row in the MRVS, then create a new RITM under the same REQ for each subsequent row in the MRVS.  A script something like this will do that:

var ritmsysid = '';
var mrvs = current.variables.network_gear_asset_mrvs; //internal name of your MRVS
var rowCount = mrvs.getRowCount();

//get the sysid of EVERY Catalog Item variable that will need to be populated on new RITM(s)
var v_db_cat = '9f29df1bdbe48f004a29df6b5e9619c3';
var v_integration_status = 'bbfcbc9cdb298b00262950a45e961958';

//autofill the desired variable on the one, existing RITM
var row = mrvs.getRow(0);	
current.variables.variable_name = row.v_mrvs_var_name; //use your Catalog Item and MRVS variable names				

//if there is more than one row in the MRVS, create a new RITM under the same REQ for all of the other rows
if (rowCount > 1) {
    for (var i = 1; i < rowCount; i++) {
        var row = mrvs.getRow(i);	
        var ritm = new GlideRecord('sc_req_item');
        ritm.initialize();
        ritm.request = current.request;
        ritm.cat_item = current.cat_item;
        ritm.opened_by = current.opened_by;
        ritm.short_description = current.short_description;
        //Add variables to the new RITMs  
        addVariable(sysID, v_db_cat, row.v_mrvs_var_name,1); //the same variable autofilled above  
        addVariable(sysID, v_integration_status, current.variables.v_integration_status,2); //one line for every other variable to be populated on the new RITM  
    }  
    //Start the workflow on all the new RITMs  
    startWf(current.request);  
}  

function addVariable(ritm,varID,value,order) {  
	var variable = new GlideRecord('sc_item_option');  
	variable.initialize();  
	variable.item_option_new = varID;  
	variable.value = value;  
	variable.order = order;  
	var sysID = variable.insert();  

	var itemm2m = new GlideRecord('sc_item_option_mtom');  
	itemm2m.initialize();  
	itemm2m.request_item = ritm;  
	itemm2m.sc_item_option = sysID;  
	itemm2m.insert();  
}  

function startWf(request) {  
	var ritm = new GlideRecord('sc_req_item');  
	ritm.addQuery('request',request);  
	ritm.addQuery('sys_id','!=',current.sys_id);  
	ritm.addNullQuery('context');  
	ritm.query();  

	while (ritm.next()) {  
		ritm.setForceUpdate(true);  
		ritm.update();  
	}  
}

View solution in original post

6 REPLIES 6

Brad Bowman
Kilo Patron
Kilo Patron

One approach is to populate a MRVS from the Excel contents.  Use a script like this as a workflow Run Script activity at the beginning of your workflow.

var att = new GlideRecord('sys_attachment');
//att.addQuery('file_name', 'serial number import.xlsx'); //use this line if the attachment will always have a known/same name
att.addQuery('content_type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
att.addQuery('table_sys_id', current.sys_id);
att.orderByDesc('sys_created_on');
att.query();
if(att.next()){
	var imp = new sn_impex.GlideExcelParser();
	var attachment = new GlideSysAttachment();
	var attachmentStream = attachment.getContentStream(att.sys_id.toString());
	imp.parse(attachmentStream);
    var headers = imp.getColumnHeaders();
	var model = headers[0];
	//var snt = headers[1]; use lines like this if you have multiple columns in the spreadsheet
    var mrvs = current.variables.network_gear_asset_mrvs; //internal name of your MRVS
	var newRow = '';
	while(imp.next()) {
		var row = imp.getRow();
        newRow = mrvs.addRow();
		newRow.v_mrvs_model = row[model];
	}
}

Now you have the REQ that was created when the Catalog Item was submitted, and ONE RITM with a MRVS populated for the one or many rows of the attached Excel file.  Next, use a workflow Run Script to update the one RITM to autofill a variable, if you want to do that, based on the first or only row in the MRVS, then create a new RITM under the same REQ for each subsequent row in the MRVS.  A script something like this will do that:

var ritmsysid = '';
var mrvs = current.variables.network_gear_asset_mrvs; //internal name of your MRVS
var rowCount = mrvs.getRowCount();

//get the sysid of EVERY Catalog Item variable that will need to be populated on new RITM(s)
var v_db_cat = '9f29df1bdbe48f004a29df6b5e9619c3';
var v_integration_status = 'bbfcbc9cdb298b00262950a45e961958';

//autofill the desired variable on the one, existing RITM
var row = mrvs.getRow(0);	
current.variables.variable_name = row.v_mrvs_var_name; //use your Catalog Item and MRVS variable names				

//if there is more than one row in the MRVS, create a new RITM under the same REQ for all of the other rows
if (rowCount > 1) {
    for (var i = 1; i < rowCount; i++) {
        var row = mrvs.getRow(i);	
        var ritm = new GlideRecord('sc_req_item');
        ritm.initialize();
        ritm.request = current.request;
        ritm.cat_item = current.cat_item;
        ritm.opened_by = current.opened_by;
        ritm.short_description = current.short_description;
        //Add variables to the new RITMs  
        addVariable(sysID, v_db_cat, row.v_mrvs_var_name,1); //the same variable autofilled above  
        addVariable(sysID, v_integration_status, current.variables.v_integration_status,2); //one line for every other variable to be populated on the new RITM  
    }  
    //Start the workflow on all the new RITMs  
    startWf(current.request);  
}  

function addVariable(ritm,varID,value,order) {  
	var variable = new GlideRecord('sc_item_option');  
	variable.initialize();  
	variable.item_option_new = varID;  
	variable.value = value;  
	variable.order = order;  
	var sysID = variable.insert();  

	var itemm2m = new GlideRecord('sc_item_option_mtom');  
	itemm2m.initialize();  
	itemm2m.request_item = ritm;  
	itemm2m.sc_item_option = sysID;  
	itemm2m.insert();  
}  

function startWf(request) {  
	var ritm = new GlideRecord('sc_req_item');  
	ritm.addQuery('request',request);  
	ritm.addQuery('sys_id','!=',current.sys_id);  
	ritm.addNullQuery('context');  
	ritm.query();  

	while (ritm.next()) {  
		ritm.setForceUpdate(true);  
		ritm.update();  
	}  
}

Hi @Brad Bowman  , 

 

Thank you so much for your response. I will have a go at implementing this and update you on how I get on. I also really appreciate your answers from other posts; I'm at the beginning of my servicenow journey and your comments/articles have been really useful.

 

Kind regards, 

G

I appreciate hearing that!  I'm happy to help out where I can!

Hi @Brad Bowman  

 

I'm still trying to peice together my workflow and was wondering if you could explain the last line of code in the first section:

newRow.v_mrvs_model = row[model];

 

I saw on another post of yours that v_mrvs_model is a varaible on the cmdb_model table, however, on my PDI I can't seem to find this. Would I replace this with the target variable on my MRVS, or would I replace this with the field name of the field on the catalog item request form that I want it to populate. 

 

Thank you, 

G