Copy form section to another view

chazz1
Mega Contributor

Is there a quick/easy way to copy a section of a form view to another?

I have created a number of sections for the emergency change form and now i want the same sections on my standard change form(with a couple tweaks). Am i stuck rebuilding the sections?

13 REPLIES 13

davidmcdonald
Kilo Guru

Gday guys,



Not sure if you're still after an answer but I wrote a function to copy forms /   sections, because I can't be bothered to copy a form 12 or so times between tables, like CI classes.



It doesn't to related lists, but related lists should be inherited from its parent if a form is opened and that table doesn't have a Related Lists definition for that specific table. Easier doing that, than copying it grammatically.



Let me know if you have any issues. The indentation was lost in the post, sorry it looks like a wall of text.



EDIT: Added support for changing views and removing existing forms / sections



//In this example, I'm copying a form that I've already got (by it's sys_id) for the Server CI table, to the Unix Server CI table


//But first, it removes any forms there to begin with, so it doesn't double up


RemoveForms("cmdb_ci_unix_server");


RemoveSections("cmdb_ci_unix_server");


CopyForm("dff352d84fe1360034e69dde0310c7f6", "cmdb_ci_unix_server");




function CopyForm(sourceFormID, newTableName, newViewName) {


  function _log(msg) {


  gs.print(msg);


  }



  //Settings


  formFieldsToCopy = [


  "roles",


  "sys_user",


  "view_name",


  "sys_domain" //Domain separation support


  ];



  //Get form record


  _log("Getting the existing form record");


  var grFormOld = new GlideRecord("sys_ui_form");


  if (!grFormOld.get(sourceFormID)) throw ("Failed to get form record by ID: "+sourceFormID);



  //Get view record


  var grView = new GlideRecord("sys_ui_view");


  if (JSUtil.nil(newViewName)) {


  _log("No view defined, will use source form's view");


  grView.get(grFormOld.getValue("view"));


  } else {


  _log("Getting view record");


  grView.get("name", newViewName);


  }


  if (!grView.isValidRecord()) throw ("Failed to get view record by name: "+newViewName);



  //Copy form record


  _log("Creating the new the form record");


  var grFormNew = new GlideRecord("sys_ui_form");


  grFormNew.initialize();


  grFormNew.setValue("view", grView.sys_id);


  grFormNew.setValue("name", newTableName); //WARNING: No table name validation! Don't get it wrong


  if (!grFormOld.view_name.nil()) grFormNew.setValue("view_name", newViewName); //Only populate the field view_name if the source had one


  QuickCopyFields(grFormOld, grFormNew, formFieldsToCopy); //Copy all the standard fields


  if (JSUtil.nil(grFormNew.insert())) throw "Failed to create new form record";



  //We've got our form record, loop through the section M2M and replicate them & the sections


  _log("Copying sections");


  var grOldM2M = new GlideRecord("sys_ui_form_section");


  grOldM2M.addQuery("sys_ui_form", grFormOld.sys_id);


  grOldM2M.query();


  while (grOldM2M.next()) {


  _log("Section: "+grOldM2M.sys_ui_section.getDisplayValue());


  var grNewM2M = new GlideRecord("sys_ui_form_section");


  grNewM2M.initialize();


  grNewM2M.setValue("sys_ui_form", grFormNew.sys_id);


  QuickCopyFields(grOldM2M, grNewM2M, ["position", "sys_domain"] );



  //Copy section


  grNewM2M.setValue("sys_ui_section", CopySection(grOldM2M.getValue("sys_ui_section"), newTableName));



  grNewM2M.insert();


  }



  //Done


  _log("Form copy complete");


}




function CopySection(sectionID, newTableName, newViewName) {



  function _log(msg) {


  gs.print(msg);


  }



  //Settings


  var sectionFieldsToCopy = [


  "caption",


  "header",


  "roles",


  "sys_user",


  "title",


  "sys_domain" //Domain separation support


  ];


  var elementFieldsToCopy = [


  "element",


  "position",


  "sys_ui_formatter",


  "sys_user",


  "type"


  ];



  //Get section record


  var grSectionOld = new GlideRecord("sys_ui_section");


  if (!grSectionOld.get(sectionID)) throw ("Failed to find section record by the ID: "+sectionID);


  _log("Got section record");



  //Get view record


  var grView = new GlideRecord("sys_ui_view");


  if (JSUtil.nil(newViewName)) {


  _log("No view defined, will use source form's view");


  grView.get(grSectionOld.getValue("view"));


  } else {


  _log("Getting view record");


  grView.get("name", newViewName);


  }


  if (!grView.isValidRecord()) throw ("Failed to get view record by name: "+newViewName);



  //Copy the section


  _log("Copying section record");


  var grSectionNew = new GlideRecord("sys_ui_section");


  grSectionNew.initialize();


  grSectionNew.setValue("name", newTableName); //WARNING: no table name validation! Don't get it wrong


  grSectionNew.setValue("view", grView.sys_id);


  if (!grSectionOld.view_name.nil()) grSectionNew.setValue("view_name", newViewName); //Only populate the field view_name if the source had one


  QuickCopyFields(grSectionOld, grSectionNew, sectionFieldsToCopy); //Copy all the standard fields



  if (JSUtil.nil(grSectionNew.insert())) throw "Failed to insert the new section record";



  //Have inserted the new section, copy the old one's elements


  _log("Copying section elements");


  var grElementOld = new GlideRecord("sys_ui_element");


  grElementOld.addQuery("sys_ui_section", grSectionOld.sys_id);


  grElementOld.query();


  while (grElementOld.next()) {


  //Copy what's found


  _log("Element: "+(grElementOld.element || grElementOld.type));


  var grElementNew = new GlideRecord("sys_ui_element");


  grElementNew.initialize();


  grElementNew.setValue("sys_ui_section", grSectionNew.sys_id);


  QuickCopyFields(grElementOld, grElementNew, elementFieldsToCopy); //Copy all the standard fields


  if (JSUtil.nil(grElementNew.insert())) throw "Failed to insert a new element";


  }



  _log("Section copy complete");


  return grSectionNew.getValue("sys_id"); //Return the new section's sys_id


}




function QuickCopyFields(grSource, grTarget, fieldArr) {


  for (var i=0; i < fieldArr.length; i++) {


  var fname = fieldArr[i];


  grTarget.setValue(fname, grSource.getValue(fname));


  }


}




function RemoveForms(tableName, viewName) {


  if (viewName == undefined) viewName = "";


  gs.print("WARNING: You are now removing all form records with the table name '"+tableName+"' and the view name '"+viewName+"'");


  gs.print("Note that this will NOT remove sections automatically");


  var grForm = new GlideRecord("sys_ui_form");


  grForm.addQuery("name", tableName);


  grForm.addQuery("view.name", viewName)


  grForm.query();


  if (!grForm.hasNext()) gs.print("No form records to remove, nothing changed");


  while (grForm.next()) {


  gs.print("Removing form record: "+grForm.sys_id);


  grForm.deleteRecord();


  }


}




function RemoveSections(tableName, viewName) {


  if (viewName == undefined) viewName = "";


  gs.print("WARNING: You are now removing all section records with the table name '"+tableName+"' and the view name '"+viewName+"'");


  gs.print("Note that this WILL remove Form Section M2M records automatically");


  var grSection = new GlideRecord("sys_ui_section");


  grSection.addQuery("name", tableName);


  grSection.addQuery("view.name", viewName)


  grSection.query();


  if (!grSection.hasNext()) gs.print("No section records to remove, nothing changed");


  while (grSection.next()) {


  gs.print("Removing any form section M2M records for the section: "+grSection.sys_id);


  var grM2M = new GlideRecord("sys_ui_form_section");


  grM2M.addQuery("sys_ui_section", grSection.sys_id);


  grM2M.query();


  if (!grM2M.hasNext()) gs.print("No M2M records for this section");


  while (grM2M.next()) {


  gs.print("Deleting M2M record: "+grM2M.sys_id);


  gs.print("For form: "+grM2M.sys_ui_form.getDisplayValue());


  grM2M.deleteRecord();


  }



  gs.print("Removing section record: "+grSection.sys_id);


  grSection.deleteRecord();


  }


}


Thanks for this! I tried the Form Designer, but I could not copy a view to a different form (like from cmdb_ci_server to cmdb_ci_unix_server). But your script worked perfectly!

I added functions to copy also Related Lists:

function copyRelList(srcTableName,viewSysId,newTableName) {
	
	//Settings
	rlFtC= [
		//"calculated_name", // create
		"filter",
		//"name", // newTableName
		"order_by",
		"position",
		"related_list",
		"sys_domain",
		"sys_domain_path",
		//"sys_name"UNIX Server - BP2", // create
		"sys_user",
		"view",	//viewSysId
		"view_name"
	];	
	
	rlEFtC = [
		"filter",
		//"list_id",	// sys_id of the related list
		"order_by",
		"position",
		"related_list",
	];
	
	// getting the source RL
	var grSrcRL = new GlideRecord("sys_ui_related_list");
	grSrcRL.addQuery("name",srcTableName);
	grSrcRL.addQuery("view",viewSysId);
	grSrcRL.query();
	if (!grSrcRL.next()) throw ("RL: Failed to get RL by table name:"+srcTableName+" and view ID: " + viewSysId);
	
	// new RL creation
	var grNewRL = new GlideRecord("sys_ui_related_list");
	grNewRL.newRecord(); 
	QuickCopyFields(grSrcRL, grNewRL, rlFtC);
	// changed fields - lets see if calculated_name and sys_name are populated automatically or not...
	grNewRL.name = newTableName;
	if (JSUtil.nil(grNewRL.insert())) throw "RL: Failed to insert a new RL";
	gs.info("RL: added Related List to form: "+newTableName+" and view: "+viewSysId);
	
	// now related list entries...
	var grSrcRLE = new GlideRecord("sys_ui_related_list_entry");
	grSrcRLE.addQuery("list_id",grSrcRL.getValue("sys_id"));
	grSrcRLE.query();
	while (grSrcRLE.next()) {
		var grNewRLE = new GlideRecord("sys_ui_related_list_entry");
		grNewRLE.newRecord();
		QuickCopyFields(grSrcRLE, grNewRLE, rlEFtC);
		grNewRLE.list_id = grNewRL.getValue("sys_id");
		if (JSUtil.nil(grNewRLE.insert())) throw "RL: Failed to insert a new RLE";
		gs.info("RL: added Related List Entry: "+grNewRLE.related_list+" to form: "+newTableName+" and view: "+viewSysId);
	}
	return true;
}

...and another one to save everything to the update set for easy promotion:

function saveFormToUS(formSysId){
	// saving complete form to update set
	
	var um = new GlideUpdateManager2();
	var grForm = new GlideRecord("sys_ui_form");
	if (!grForm.get(formSysId)) throw ("Failed to get form record by ID: " + formSysId);
	// saving sys_ui_form GlideRecord saves all sections also
	um.saveRecord(grForm);
	
	// it is necessary to save all sys_ui_section records though
	var grFS = new GlideRecord("sys_ui_form_section");
	grFS.addQuery("sys_ui_form", formSysId);
	grFS.query();
	while (grFS.next()) {
		var grSect = new GlideRecord("sys_ui_section");
		if (!grSect.get(grFS.getValue("sys_ui_section"))) throw ("Failed to get Section record by ID: " + grFS.getValue("sys_ui_section"));
		//Copy section
		um.saveRecord(grSect);
	}
	
	// now related list
	var grRL = new GlideRecord("sys_ui_related_list");
	grRL.addQuery("name",grForm.getValue("name"));
	grRL.addQuery("view",grForm.getValue("view"));
	grRL.query();
	if (grRL.next()) um.saveRecord(grRL);
	
	return true;
}

rafreig
Kilo Contributor

You can easily use form designer to accomplish this.


Form Designer workds fine ... but only if you are copying within the same scope.

Does not work from scope to scope