Blog  |  Support  |  Forums

Search Results for 'form.getRecords'

Tap Forms – Organizer Database App for Mac, iPhone, and iPad Forums Search Search Results for 'form.getRecords'

Viewing 15 results - 106 through 120 (of 141 total)
  • Author
    Search Results
  • #40750

    In reply to: JavaScript API 5.3

    Brendan
    Keymaster

    Hi Rocky,

    No, those haven’t been deprecated. In fact, I recently added the form.getRecordsForSearchTerm() function. The issue is I forgot to add those as keywords to the keywords file that tells the editor what functions to colour.

    For recalculating the form, just click the refresh button at the bottom of the record. Or at the bottom of the records list view.

    #40748
    Rocky Machado
    Participant

    Hi Brendan – I have a couple of questions. Have the following methods been deprecated. form.getRecordsForSearchTerm() and record.setRecordColor() It doesn’t show up in the IntelliSense. Also, in the future will you being adding a feature to recalculate a form via the javascript API?

    Oh, I’m running version 5.3.11 (Build 962)

    thanks,
    rocky

    #40684
    Victor Warner
    Participant

    Sam,

    Thank for the further reply,

    I eventually worked out how to use

    search.getREcords()

    , by replacing:

    for (let rec of form.getRecords()){

    with

    for (let rec of search.getRecords()){

    Just one follow-up question: Does the it only work with an advanced search and not an ordinary search (Command + F)? I have tried with an ordinary search but the script does not operate.

    #40421
    Victor Warner
    Participant

    I am getting the following error:

    02/05/2020, 18:24:01 / Time spent / add 0s to Time charged for (not empty)
    add 0s to Time charged for (not empty): TypeError: value.replace is not a function. (In ‘value.replace(find_text, replace_with)’, ‘value.replace’ is undefined), line:(null)

    when running the following script

    var time_charged_for_id = 'fld-755fd264b59b42e59c7254edf03ea281';
    
    function findAndReplace(find_text, replace_with) {
    	for (let rec of form.getRecords()){
    		let value = rec.getFieldValue(time_charged_for_id);
    		if (value) {	
    			rec.setFieldValue(time_charged_for_id, value.replace(find_text, replace_with));
    		}
    	}
    	form.saveAllChanges();
    	return;
    }
    
    findAndReplace(/[a-zA-Z0-9]*/, '0');
    

    I created a test database and it ran and did what is should. But in a working database it is causing the error. The field type is the same (a number field) in the test database and the working database.

    The code was provided by Daniel Leu in the exchanges at https://www.tapforms.com/forums/topic/find-and-replace-script-to-replace-anything/.

    Because I do not really have any understanding of JavaScript I cannot tell why it is not working.

    I would grateful for any help in identifying what is wrong.

    #40233
    Daniel Leu
    Participant

    Everything is possible with a script, well almost ;-)

    Here is the version that doesn the replacement of strings in a field:

    var field_id = 'fld-64b0b17a635f49b8b40867e45f8d24db';
    
    function findAndReplace(find_text, replace_with) {
    	for (let rec of form.getRecords()){
    		let value = rec.getFieldValue(field_id);
    		if (value) {	
    			rec.setFieldValue(field_id, value.replace(find_text, replace_with));
    		}
    	}
    	form.saveAllChanges();
    	return;
    }
    
    findAndReplace("Ford", 'Tesla');

    And this version replaces an empty field with the replacement text:

    var field_id = 'fld-34fb289f2b124f26982df66430b31fbd';
    
    function findAndReplace(find_text, replace_with) {
    	for (let rec of form.getRecords()){
    		let value = rec.getFieldValue(field_id);
    		if (find_text === ""){	// special case with empty string
    			if (value == undefined){
    				rec.setFieldValue(field_id, replace_with);
    			}
    		} else {
    			if (value){
    				rec.setFieldValue(field_id, value.replace(find_text, replace_with));
    			}
    		}
    	}
    	form.saveAllChanges();
    	return;
    }
    
    findAndReplace("Ford", 'Tesla');

    Enjoy!

    #40227
    Victor Warner
    Participant

    I found the find and replace script posted by Brendan at https://www.tapforms.com/forums/topic/find-and-replace-script/ very helpful, but would like some help in adapting it:

    var field_id = 'fld-64b0b17a635f49b8b40867e45f8d24db';
    
    function findAndReplace(find_text, replace_with) {
    	
    	var records = form.getRecords();
    	
    	for (var index = 0, count = records.length; index < count; index++){
    		var rec = records[index];
    		var value = rec.getFieldValue(field_id);
    		if (value == find_text) {
    			value = replace_with;
    			rec.setFieldValue(field_id, value);
    		}
    	}
    
    	document.saveAllChanges();
    	
    	return;
    }
    
    findAndReplace('Ford', 'Tesla');

    specifically:

    1. at present it searches for a specific item in a specific field. How is it possible to search for anything in that field and replace with specific text (so rather than ‘Ford’ in Brendan’s example, there might be Ford, Mercedes or BMW etc). I have tried adding a wildcard indicator (*), but it does not work.

    2. A variation on 1. is where there is nothing in the specific field. Changing ‘Ford’ in Brendan’s example, to ” also does not work.

    Is this possible with the script?

    Any help would be gratefully received.

    #39822
    Sam Moffatt
    Participant

    If you’re doing an import flow you might want to add a field with a flag on it to control if you already did the search/replace on the record already. Depending on what your search/replace looks for, running it more than once might be problematic for you.

    Another trick you might be interested in is creating a saved search using “date created” to specify when you import the records to ensure that you only select and modify the records that were recently created. A slight change to Brendan’s script is to change:

    var records = form.getRecords();
    

    To something like:

    var records = search.getRecords();
    

    You’ll need to be in the search for the search object to exist but then it’ll only apply the script to the currently searched records.

    #39818
    Brendan
    Keymaster

    The Basic Loop Snippet will get you part of the way. But here’s a more comprehensive example:

    var field_id = 'fld-64b0b17a635f49b8b40867e45f8d24db';
    
    function findAndReplace(find_text, replace_with) {
    	
    	var records = form.getRecords();
    	
    	for (var index = 0, count = records.length; index < count; index++){
    		var rec = records[index];
    		var value = rec.getFieldValue(field_id);
    		if (value == find_text) {
    			value = replace_with;
    			rec.setFieldValue(field_id, value);
    		}
    	}
    
    	document.saveAllChanges();
    	
    	return;
    }
    
    findAndReplace('Ford', 'Tesla');
    #39643
    Sam Moffatt
    Participant

    I’ll walk through this a little as this is my bulk scan script. It’s probably a bit much but it has a bunch of piece that might help.

    document.getFormNamed('Script Manager').runScriptNamed('Prompter Functions');
    

    This is pulling in my Prompter Functions via the Script Manager method. Basically Script Manager is a Tap Forms form named ‘Script Manager’ and then it uses ‘Form Scripts’.

    var tracking_number_id = 'fld-c487390743c947969cbe661cff596855';
    var received_date_id = 'fld-e3e3539ee04f4cc7971c7098c572104d';
    var confirmed_id = 'fld-2adb9ba8cdd048bbbb614d46b415ada5';
    var alternate_tracking_numbers_id = 'fld-cf8718051bea4cc2aba0069ae76f32b7';
    var alternate_tracking_number_id = 'fld-7342203d8f36415191bf8419fb6f70dc';
    var carrier_id = 'fld-0950c430cb0c41f79c51d43a544b366b';
    var zip_code_id = 'fld-4f73faa8937446a0a3b24e6dd4624d6b';
    var shipper_id = 'fld-1789ae45fd1f4f588294eff0c2fb6045';
    

    These are all of the field ID’s I care about, you’ll see them spliced through. Obviously your fields will be different.

    function findRecord(targetTrackingNumber)
    {
    	var targetRecord = null;
    	MainLoop:
    	for(candidateRecord of form.getRecords())
    	{
    		if (targetTrackingNumber == candidateRecord.getFieldValue(tracking_number_id))
    		{
    			targetRecord = candidateRecord;
    			break MainLoop;
    		}
    		
    		
    		for (alternateRecord of candidateRecord.getFieldValue(alternate_tracking_numbers_id))
    		{
    			if (targetTrackingNumber == alternateRecord.getFieldValue(alternate_tracking_number_id))
    			{
    				targetRecord = candidateRecord;
    				break MainLoop;
    			}
    		}
    	}
    	
    	return targetRecord;
    }
    

    This is a quick method to basically brute force scan all of the records and search for them. I mentioned earlier that Brendan is adding a function to make this a little less relevant however what it’s doing is getting a list of all of the records, checking if the tracking number matches (in your case it’ll be your box barcode or item barcode) and it also checks the values of a table field that is in my shipments form. Because there are two levels of loops in this, I use a trick to make sure I break out of them easily. Shipping is fun where a package might have more than one tracking number, hence the crazy setup.

    async function start(){
    	try {
    		while (1)
    		{
    

    This is the start of the meat and it has three things to be interested in. The async keyword is required to get my prompter functions to work properly and enable you to do blocking calls without having to manage the callbacks all yourself. The try is a fallback for an exceptions that might escape and the while (1) is our infinite loop.

    			let zipcode = undefined;
    			let carrier = '';
    			let barcode = '';
    			let scanBarcode = await promptText("Scan Shipment", "Barcode:");
    

    This sets up some variables, in my case I’m tracking zipcode for the package (USPS embed this into their tracking number), a carrier that I can automatically infer (USPS and UPS) and then obviously the core barcode. This uses the promptText function which is in that Prompter Functions I mentioned earlier. It has await prefixed to make it block until we get a response back.

    			if (!scanBarcode)
    			{
    				break;
    			}
    

    This is pretty straight forward, if we don’t get anything back from the barcode then we abort the loop. This is our exit criteria.

    			let matches = scanBarcode.match(/420(9[0-9]{4})(.*)/);
    			if (matches)
    			{
    				carrier = 'USPS';
    				zipcode = matches[1];
    				barcode = matches[2];
    			}
    			else
    			{
    				barcode = scanBarcode;
    			}
    

    This isn’t relevant to you as much but it basically looks for a USPS barcode and extracts the useful information out of it. It resets the barcode to be what the label and tracking number actually is versus the full details that are encoded into the barcode. I’m in California so my zipcode is prefixed with a 9 which is why it looks the way it does.

    			matches = scanBarcode.match(/^1Z/);
    			if (matches)
    			{
    				carrier = 'UPS';
    			}
    

    This also isn’t as relevant but it looks for a UPS style barcode and sets it automatically. Depending on how your barcode generation is done, this might be something you can apply where you have different barcode prefixes for stuff (or not).

    			console.log(barcode);
    			
    			let targetRecord = findRecord(barcode);
    

    I logged the barcode because I wanted to see what it was in the console. This is useful for understanding when something weird happens. This is then fed into that findRecord method before to find a record that matches, or not.

    			if (targetRecord)
    			{
    				// Flip confirmed flag but otherwise leave it alone.
    				targetRecord.setFieldValue(confirmed_id, true);
    				document.saveAllChanges();
    				console.log("Updated existing record for " + barcode);
    			}
    

    For me I’m looking to confirm or create a record that I’m scanning. In this case if for some reason the shipping number already exists and I found a matching record, I just toggle a flag saying that I know it exists and move on.

    			else
    			{
    				let payload = {
    					[tracking_number_id]: barcode,
    					[confirmed_id]: true
    				};
    

    Ok, the else case means this tracking number doesn’t exist already so we need to create it. I start to create a new record here. This syntax with the square brackets is to get the value of tracking_number_id instead of using tracking_number_id as the key.

    				if (carrier)
    				{
    					payload[carrier_id] = carrier;
    					payload[zip_code_id] = zipcode;
    				}
    

    If there is a carrier set then this gets set up as well including the zipcode (USPS).

    				let shipper = await promptText("Enter Shipper Name", "Shipper: ");
    				console.log(shipper);
    				
    				if (shipper)
    				{
    					payload[shipper_id] = shipper;
    				}
    

    I ask for the shipper name in case that’s obvious, again with the promptText method. That’s useful for knowing where something is from if I want to add it in.

    				console.log(JSON.stringify(payload));
    
    				let newRecord = form.addNewRecord();
    				newRecord.setFieldValues(payload);
    				document.saveAllChanges();
    

    I log out what I’m about to create to see what it is during debugging. I then create a new record, use setFieldValues to set up the values and then save the changes. Too easy!

    			}
    		}
    	} catch (error) {
    		console.log("Error: " + error);
    	}
    }
    
    start();

    This is closing everything out and then triggering the script to begin with. The catch is the follow up to the try and is a fail safe to log the message and go from there. It’s closing out the loop so assuming you enter in a valid barcode, it’ll keep looping until it’s done.

    I thought I had another script that handled a little closer to what you were doing but I can’t find where I put it.

    Here’s the script in full:

    document.getFormNamed('Script Manager').runScriptNamed('Prompter Functions');
    
    var tracking_number_id = 'fld-c487390743c947969cbe661cff596855';
    var received_date_id = 'fld-e3e3539ee04f4cc7971c7098c572104d';
    var confirmed_id = 'fld-2adb9ba8cdd048bbbb614d46b415ada5';
    var alternate_tracking_numbers_id = 'fld-cf8718051bea4cc2aba0069ae76f32b7';
    var alternate_tracking_number_id = 'fld-7342203d8f36415191bf8419fb6f70dc';
    var carrier_id = 'fld-0950c430cb0c41f79c51d43a544b366b';
    var zip_code_id = 'fld-4f73faa8937446a0a3b24e6dd4624d6b';
    var shipper_id = 'fld-1789ae45fd1f4f588294eff0c2fb6045';
    
    function findRecord(targetTrackingNumber)
    {
    	var targetRecord = null;
    	MainLoop:
    	for(candidateRecord of form.getRecords())
    	{
    		if (targetTrackingNumber == candidateRecord.getFieldValue(tracking_number_id))
    		{
    			targetRecord = candidateRecord;
    			break MainLoop;
    		}
    		
    		
    		for (alternateRecord of candidateRecord.getFieldValue(alternate_tracking_numbers_id))
    		{
    			if (targetTrackingNumber == alternateRecord.getFieldValue(alternate_tracking_number_id))
    			{
    				targetRecord = candidateRecord;
    				break MainLoop;
    			}
    		}
    	}
    	
    	return targetRecord;
    }
    
    async function start(){
    	try {
    		while (1)
    		{
    			let zipcode = undefined;
    			let carrier = '';
    			let barcode = '';
    			let scanBarcode = await promptText("Scan Shipment", "Barcode:");
    			
    			if (!scanBarcode)
    			{
    				break;
    			}
    
    			let matches = scanBarcode.match(/420(9[0-9]{4})(.*)/);
    			if (matches)
    			{
    				carrier = 'USPS';
    				zipcode = matches[1];
    				barcode = matches[2];
    			}
    			else
    			{
    				barcode = scanBarcode;
    			}
    			
    			matches = scanBarcode.match(/^1Z/);
    			if (matches)
    			{
    				carrier = 'UPS';
    			}
    			console.log(barcode);
    			
    			let targetRecord = findRecord(barcode);
    				
    			if (targetRecord)
    			{
    				// Flip confirmed flag but otherwise leave it alone.
    				targetRecord.setFieldValue(confirmed_id, true);
    				document.saveAllChanges();
    				console.log("Updated existing record for " + barcode);
    			}
    			else
    			{
    				let payload = {
    					[tracking_number_id]: barcode,
    					[confirmed_id]: true
    				};
    				
    				if (carrier)
    				{
    					payload[carrier_id] = carrier;
    					payload[zip_code_id] = zipcode;
    				}
    
    				let shipper = await promptText("Enter Shipper Name", "Shipper: ");
    				console.log(shipper);
    				
    				if (shipper)
    				{
    					payload[shipper_id] = shipper;
    				}
    				
    				console.log(JSON.stringify(payload));
    
    				let newRecord = form.addNewRecord();
    				newRecord.setFieldValues(payload);
    				document.saveAllChanges();
    			}
    		}
    	} catch (error) {
    		console.log("Error: " + error);
    	}
    }
    
    start();
    #39638
    Sam Moffatt
    Participant

    I have recently been working on something like that to scan a bunch of items into boxes and similar. There are a couple of ways of handling it.

    I’m going to rephrase some of your questions:

    Can I pull up a box by scanning it’s barcode?

    This one is relatively straight forward application of the search functionality, that’s easy out of the box regardless of what platform you’re on. On the desktop you’ll need a barcode scanner to make that work but on iOS the built in barcode scanning functionality will make that work for you there.

    Can I scan barcodes of items as I place them into the box?

    The way I did this in January when I was doing a lot of box packing for moving was to create a second form called “Box Items” that is linked from my main “Box” form and then created child records. I was taking pictures of the item and adding some extra metadata in this case so I just used the built in Tap Forms barcode scanner to scan items and used voice to text to quick enter titles (worked enough times to save me having to type).

    Now if you invest in a barcode scanner, you can take it a little bit further and create a prompter loop to scan barcodes and automatically create new child records. You can also pivot and if you’re confident an item will only be in a single box, you can make it’s box barcode a property of the item. I have a prompter loop I use for bulk scanning shipments, I’ll post that on the Script Talk forum later.

    Can I checkout of a box?

    If you go with the Link to Form and enable show inverse relationship (or what ever that checkbox is called), then when you scan in your item in Tap Forms using the search feature it will show you the record and the “Link From Form” will show you the details of the box that it thinks it should be in. In Tap Forms on the desktop you can select this and change it to search for a new box which you should be able to do by barcode for your checkout box or just have a box named “checkout”. By changing the value of the Link from Form field parent will register it to a new box. The iOS version has a similar interaction here but I feel that it isn’t quite as smooth as the desktop more due to the limitations of iOS rather than Tap Forms (the desktop shows a popover which makes it much easier to interact with).

    If you go for the field based approach, you just need to update the field to where ever you put the item.

    In both cases you can script it to handle it easier. Scripting the Link to Form/Link from Form is a little more difficult because in the current production release of Tap Forms there is no search by text via the script interface. Brendan mentioned that he’s adding a form.getRecordsForSearchTerm() to the next beta which would make that easier because the JavaScript API for the link fields works with records. Until then, it’s a little easier to update a simple text field based on a search.

    I have a dedicated barcode scanner for the desktop, I bought a NETUM Bluetooth scanner that has both a USB cable for input and can pair via Bluetooth. I’m not sure I’d recommend it, it works fine in Bluetooth mode but when I plug in the USB cable it mangles the numbers some how (it’s like it’s pressing on the keypad numbers upside down). On the Mac I use Karabiner Elements whose mere existence seemed to make the scanner behave properly.

    #39636
    Sam Moffatt
    Participant

    Off the top of my head, where:

    • players_linked_fieldId is the field ID of the “Link to Form” field in your Classes form.
    • players_fieldId is the field ID of the Players field in your Classes form.
    • players_linked_player_name_fieldId is the field ID of the players-linkedin field in your Players form.

      Three fields: link field, source field and destination field (in destination form).

      var players_linked_fieldId = 'fld-1234';
      var players_fieldId = 'fld-4321';
      var players_linked_player_name_fieldId = 'fld-1337';
      
      for (record in form.getRecords())
      {
        for (player in record.getFieldValue(players_fieldId).split(',').map(p => p.trim()))
        {
          let playerRecord = record.addNewRecordToField(players_linked_fieldId);
          playerRecord.setFieldValue(players_linked_player_name_fieldId, player);
        }
      }
      document.saveAllChanges();
      

      Something like that should work. Outer loop gets all of the records and iterates over them. Inner loop splits the text field on a comma and also trims the string (that’s the map(p => p.trim()) piece). Inside the loop you add a new record to the “Link to Form” field and set the player name on the inside to be the player from the string.

      None of this is tested, provided as is and it should work with a few tweaks. You’ll need to replace the field ID’s with your own values but apart from that it should be good enough to test. I’d recommend having Tap Forms duplicate the document and work from it first to make sure there aren’t any weird side effects.

    #39611
    Bernhard
    Participant

    @Sam: Sounds good – thanks for the advice!
    For the record, here is how it works:

    
    var customerRecordIds = [];
    
    // Callback function of the Prompter call.
    function chooseCustomerCallback() {
    	createInvoice(customerRecordIds[choosenTitle]);
    }
    
    // Do something with the record after the user choose one.
    function createInvoice(recordId) {
    	var customerRecord = form.getRecordWithId(recordId);	
    	...
    }
    
    // The entry function of the script
    function Erstelle_Rechnung() {	
    	var titleFieldId = 'fld-aa817f3bd885458883d3e25802fd4037';
     	var customersForm = document.getFormNamed('Kunden');
     	var customers = customersForm.getRecords();
    	var companyTitles = [];
    	
    	for (var index = 0, count = customers.length; index < count; index++) {
    		const title = customers[index].getFieldValue(titleFieldId);
    		companyTitles.push(title);
    		// Remember the Record ID of this customer record to be used later.
    		customerRecordIds[title] = customers[index].getId();
    	}
    
    	var choosenTitle;
    
    	let prompter = Prompter.new();
    	prompter.addParameter('Kunde', 'choosenTitle', 'popup', companyTitles)
    		.show('Message prompt', chooseCustomerCallback);
    
    	return null;
    }
    
    Erstelle_Rechnung();
    
    #39609
    Bernhard
    Participant

    Sounds good – thanks for the advice!
    For the record, here is how it works:

    
    var customerRecordIds = [];
    
    // Callback function of the Prompter call.
    function chooseCustomerCallback() {
    	createInvoice(customerRecordIds[choosenTitle]);
    }
    
    // Do something with the record after the user choose one.
    function createInvoice(recordId) {
    	var customerRecord = form.getRecordWithId(recordId);	
    	...
    }
    
    // The entry function of the script
    function Erstelle_Rechnung() {	
    	var titleFieldId = 'fld-aa817f3bd885458883d3e25802fd4037';
     	var customersForm = document.getFormNamed('Kunden');
     	var customers = customersForm.getRecords();
    	var companyTitles = [];
    	
    	for (var index = 0, count = customers.length; index < count; index++) {
    		const title = customers[index].getFieldValue(titleFieldId);
    		companyTitles.push(title);
    		// Remember the Record ID of this customer record to be used later.
    		customerRecordIds[title] = customers[index].getId();
    	}
    
    	var choosenTitle;
    
    	let prompter = Prompter.new();
    	prompter.addParameter('Kunde', 'choosenTitle', 'popup', companyTitles)
    		.show('Message prompt', chooseCustomerCallback);
    
    	return null;
    }
    
    Erstelle_Rechnung();
    
    #39608
    Barry Shevlin
    Participant

    I’m almost embarrassed to ask this given it’s probably such a basic question. However, I could well use the following script given as an example in the TF5 manual:

    var records = form.getRecords();
    var revenue_total = 0;

    for (var index = 0, count = records.length; index < count; index++){
    var theRec = records[index];
    var movie_revenue = theRec.getFieldValue(‘fld-987c9aac738a4f0fa1d18395902b3fc1’);
    if (movie_revenue) {
    revenue_total += movie_revenue;
    console.log(‘Revenue: ‘ + movie_revenue);
    }
    }

    revenue_total;

    My question is this: how do I limit the revenue_total return to 2 decimal places (currency)? I am getting this sort of thing: £63.9300000000001.

    Sorry if this time-wasting but I’m sure there’s a quick answer that would save me hours of fruitless futzing. Thanks.

    #39603
    Brendan
    Keymaster

    Hi Bernhard,

    I’m not entirely sure how that would work for your situation other than to program Tap Forms specifically to allow a string / record ID key/value mapping. But then how does Tap Forms know to relate your title field to the record ID? Generic key/value mapping is one thing, but when it relates specifically to fetching a record, it’s tricky.

    However, in the latest beta update I added a new search API that lets you do a generic text search on your records. Like typing into the main Search field. You can now do form.getRecordsForSearchTerm();. You’ll get back an array of records. If there’s only 1 result, you know you’ve got an exact match. Or you can just pull off the record from the first element of the array to get the first occurrence. And if you pass in double-quotes in your search, then Tap Forms will do an exact match search, but the result will still be an array of records. Just one record in that case.

    Thanks,

    Brendan

Viewing 15 results - 106 through 120 (of 141 total)
 
Apple, the Apple logo, iPad, iPhone, and iPod touch are trademarks of Apple Inc., registered in the U.S. and other countries. App Store is a service mark of Apple Inc.