Script to copy records from one form to another

Tap Forms – Organizer Database App for Mac, iPhone, and iPad Forums Script Talk Script to copy records from one form to another

Viewing 8 reply threads
  • Author
    Posts
  • September 17, 2019 at 12:56 AM #36782

    Sam Moffatt
    Participant

    Over on the main forum is a topic about move records from one form to another which I was curious about being able to solve.

    This gives the user a list of forms excluding the currently selected one, checks to see if at least each of the fields in the source record are available in the destination and then creates a new record. In my limited testing it seems to work properly though by design it only copies records, it doesn’t delete the original so you need to do that after verification (trust, but verify).

    I went through and put some comments in it that will hopefully make sense. There are two functions: the copyHandler is a callback that does the heavy lifting and the Copy_Record_To_Form function sets up the initial form list and prompter.

    // Handler for prompter callback
    var copyHandler = function()
    {
    	// Validate that we got a form name passed in.
    	if (typeof formName == 'undefined' || formName.trim() == '')
    	{
    		console.log('Empty or undefined formName sent, cancelling.');
    		return;
    	}
    
    	// Mapping of source field to target field
    	// - the key will be source field and the value will be target field.
    	var fieldMap = {};
    
    	// List of fields in the source form that weren't found in the target form.
    	var missingFields = [];
    
    	// We shouldn't be here but let's check again.
    	if (form.name == formName)
    	{
    		Utils.alertWithMessage('Unable to copy record to self', 'Please use the duplicate button to create a new record in the same form');
    		return;
    	}
    
    	// Get the target form.
    	var target = document.getFormNamed(formName);
    	
    	// Get the source fields.
    	var sourceFields = form.getFields();
    	
    	// Iterate through each of them.
    	for (sourceId in sourceFields)
    	{
    		// Look for a target field with the same name as the source field.
    		var targetField = target.getFieldNamed(sourceFields[sourceId].name);
    		if (targetField == null)
    		{
    			// If a targetField is missing, add the source field to the missing field list.
    			missingFields.push(sourceFields[sourceId].name);
    		}
    		else
    		{
    			// Map the source field ID to the target field ID.
    			fieldMap[sourceFields[sourceId].getID()] = targetField.getID();
    		}
    	}
    	
    	// If we had any missing fields.
    	if (missingFields.length)
    	{
    		// Prompt a message with the missing fields and let the user know it's aborted.
    		var fullMessage = ["The following fields weren't found in the target form:", "", ...missingFields];
    		Utils.alertWithMessage('Copy Aborted!', fullMessage.join("\n"));
    		return;
    	}
    	
    	// Create the record data object and start to iterate through the field map.
    	var recordData = {};
    	for (sourceFieldId in fieldMap)
    	{
    		// Set in the record data the field ID of the target field as the key
    		// and then get the current value of the source field.
    		recordData[fieldMap[sourceFieldId]] = record.getFieldValue(sourceFieldId);
    	}
    	
    	// Don't know if this works, set a secret value to the original record URL for linking.
    	recordData['copy-source'] = record.getUrl();
    	
    	// Add a new record to the target form.
    	var targetRecord = target.addNewRecord();
    	
    	// Set the field values for the newly created record.
    	targetRecord.setFieldValues(recordData);
    	
    	// Save the data and log some values for reference.
    	document.saveAllChanges();
    	console.log('Original URL: ' + record.getUrl());
    	console.log('Destination URL: ' + targetRecord.getUrl());
    }
    
    function Copy_Record_To_Form() {	
    	// Get all of the forms.
    	var forms = document.getForms();
    	
    	// A place to store a list of form names for the prompter.
    	var formNames = [];
    
    	// Iterate through all of the forms.
    	for(var formId in forms)
    	{
    		// Ignore the currently selected form from the list.
    		if (forms[formId].name == form.name)
    		{
    			continue;
    		}
    		
    		// Append this form name to the list of form names for the prompter.
    		formNames.push(forms[formId].name);
    	}
    	
    	// Create a new prompter anddisplay the form list.
    	var formPrompter = Prompter.new();
    	formPrompter.cancelButtonTitle = 'Cancel';
    	formPrompter.continueButtonTitle = 'Copy record';
    	formPrompter.addParameter('Destination Form: ', 'formName', 'popup', formNames)
    		.show('Select form to copy record: ', copyHandler);
    }
    
    Copy_Record_To_Form();
    
    September 17, 2019 at 2:27 AM #36784

    Brendan
    Keymaster

    That’s Brilliant Sam!

    September 17, 2019 at 5:20 PM #36799

    Daniel Leu
    Participant

    Wow, that’s a very elegant solution, Sam!

    September 17, 2019 at 11:27 PM #36805

    Sam Moffatt
    Participant

    Thanks! It turned out to be reasonably straight forward, the Javascript API having the flexibility to do it all is the neat bit for me. If there were document level scripts then you could have it run on any form without having to add it per form.

    April 18, 2020 at 9:12 AM #40354

    John Wiggins
    Participant

    Hi Sam,

    Nice script, but perhaps there has been a change in the syntax.
    Looks like line 44 needs the change in two places ‘ID’ -> ‘Id’.

    Thanks,
    John

    4/18/20, 11:58:17 AM / Movies not owned / SamsUnmodifiedScript
    SamsUnmodifiedScript: TypeError: sourceFields[sourceId].getID is not a function. (In ‘sourceFields[sourceId].getID()’, ‘sourceFields[sourceId].getID’ is undefined), column:41, line:44

    April 18, 2020 at 10:43 AM #40355

    Daniel Leu
    Participant

    Yes, a while ago, there was an API harmonization. getID is now constantly getId.

    April 18, 2020 at 11:22 PM #40356

    Sam Moffatt
    Participant

    Unfortunately I can’t edit old posts to fix them either, but a simple fix either way. Probably should use links to gists and maybe see if Brendan can enable gist embedding somehow.

    September 17, 2023 at 3:40 PM #49861

    Brian Lennon
    Participant

    I fixed the ID to Id thingy and the script seems to run start to finish producing URLs (that I don’t understand yet).  BUT, there is no copying of records from the source form to the target form.  Is there something I’m missing?

    My target form is a duplicate of the source form.

    (Very much a beginner with Javascript but making progress thanks to Sam’s videos!)

    September 20, 2023 at 9:17 AM #49886

    Glen Forister
    Participant

    I’ve been looking for a Script like this that doesn’t need modification to work in any database and copy records from one to another.  I hope any bugs that exist get worked out.  I’m not a scripter so wouldn’t be able to modify it to work in my environment.

    Thanks guys.

Viewing 8 reply threads

You must be logged in to reply to this topic.