Dec 01, 2020 12:50 AM
Hi guys,
I am just starting with the scripting and I am really trying my best. I have learned a lot just by trying out different submissions from the community and by doing that I understand how a script is structured etc.
I am currently focused on 3 specific scripts that was contributed to this community.
The first one is automatically setting up a field from a table to link all records from a view based on another table. It worked.
let mstTable = base.getTable('$MST');
let mstView = base.getTable('$MST').getView('TEST');
let mstQuery = await mstView.selectRecordsAsync();
let mstRecords = mstQuery.records;
let invsumTable = base.getTable('$INV: SUM');
let invsumQuery = await invsumTable.selectRecordsAsync();
let invsumRecords = invsumQuery.records;
let d = []
invsumRecords.forEach(c => d.push({id: [c.id](http://c.id/)}));
let updateRecords = mstRecords.map(c=> ({id:c.id,fields:{'$INV: SUM': d}}));
while (updateRecords.length > 0) {
await mstTable.updateRecordsAsync(updateRecords.slice(0,50));
updateRecords = updateRecords.slice(50);
}
output.markdown('# Done 🚀')
I encountered an error when linking records above 50. After searching and trying to understand the limit and how to control it, I added these to the code and it is working fine now.
await mstTable.updateRecordsAsync(updateRecords.slice(0,50));
updateRecords = updateRecords.slice(50);
}
Extracting an image from a URL and attaching it to an attachment field.
// Change the names of this table/fields according to your base.
let submissionsTable = base.getTable('$MST');
let urlField = submissionsTable.getField('URL: QR Code | 64px');
let attachmentField = submissionsTable.getField('ATH: QR Code | 64px');
let submissionsQuery = await submissionsTable.selectRecordsAsync();
let updates = [];
for (let record of submissionsQuery.records) {
let url = record.getCellValue(urlField);
let attachments = record.getCellValue(attachmentField);
// If this record already has an attachment, skip it.
if (url === null || attachments !== null) {
continue;
}
// Otherwise, attach the image at the URL.
updates.push({
id: record.id,
fields: {
[attachmentField.id]: [{url: url}]
}
});
}
// Update records in batches of 50.
while (updates.length > 0) {
await submissionsTable.updateRecordsAsync(updates.slice(0, 50));
updates = updates.slice(50);
}
This is one of the first few scripts that I encountered here on the community and I noticed when reviewing my saved snippets that there was the while (updates.length > 0) lines included already so I searched airtable for the documentation and I was studying it as well. This is working fine as well with more than 50 records.
let config = input.config()
let table = base.getTable("$MST")
let query = await table.selectRecordsAsync()
let record = query.getRecord(config.recordID)
// Collect record data
let newPrefix = record.getCellValue("MST_CODE")
let newExtension = record.getCellValue("ATH: Calling Card | File Name")
let files = record.getCellValue("ATH: QR Code | 512px")
// Get the extension and add it to the new name
let newFiles = []
for (let file of files) {
let fileNumber = "0" + (files.indexOf(file) + 1)
let newName = `${newPrefix}_${fileNumber}${newExtension}`
newFiles.push({url: file.url, filename: newName})
}
// Reattach the item with the new filename
await table.updateRecordAsync(record, {
"ATH: QR Code | 512px": newFiles
})
^^ I have been trying to add the while update slice 50 lines and I cant seem to make it work.
I have also studied and experimented with Jeremys post (https://community.airtable.com/t/scripting-block-a-hopefully-helpful-batching-function/27757). I am thankful for this that I am able to understand it but I am just assuming that the code for Script #3 is structured differently thats why I cant seem to include the while update records slice command that I keep on seeing from different posts.
Can anyone please help me so that I can add the while slice code to the Script #3 to prevent errors? I have tried to modify this multiple times already. I just cant seem to make it work. :frowning:
I would appreciate any assistance guys! And also, credits to the original contributors of these snippets. I am very thankful. I am very eager to understand the process as well so that I can understand it even more.
Dec 01, 2020 10:11 AM
Your first two scripts update a batch of records with updateRecordsAsync()
, Note the s
at the end of “records”.
However, your third script is not a batch operation. It updates only one record with updateRecordAsync
. Note the lack of an s
at the end of “record”. You cannot change this line to run on batches of 50 because updateRecordAsync
is designed to run on only one record. This automation script looks like it is designed to update only one record–the triggering record. In order to update multiple records, the script runs multiple times–once for each triggering record.
Dec 01, 2020 06:41 PM
Hi @kuovonne
Thank you for your detailed response. I appreciate the effort into explaining the theory as well. I understand it more now that the design is different and yes it is run through automation not like compared to the other 2 which is run through the script application.
The reason why I asked this, is that I am encountering a few errors “Error: network timeout at: https://api.airtable.com/v2/bases/appcgCGOdXru0MAwg/tables/tbl2tMlL5NSEpHIAf/records/update” for some records in the table being updated. There are 62 records on the table and most work fine but there are some inconsistencies. Is there a way to modify this script to be more reliable before I deploy it?
I also read this thread which was helpful, but sadly I dont know how to optimize this script even more. Automations: Scripting Actions Error from @Jeremy_Oglesby.
I just need advice on how to tweak this to run for large tables with hundreds or thousands of records.
Thank you so much!
Dec 01, 2020 08:45 PM
When a script works for some records, but not others, I recommend looking for what is different about the records that fail. For example, this script will probably fail if the “ATH: QR Code | 512px” field is blank, although it is hard to tell without seeing the data and the field types.
Also keep in mind that the Amazon AWS outage last week affected Airtable attachments, but those issues should now be resolved.
BTW, your screen capture shows several input variables for the automation script, but you use only one of them (the recordId).
Dec 03, 2020 02:42 AM
Hi @kuovonne
Thank you for still replying and trying to help me out. I have taken your response and I have been studying it. So what I did was to try to combine the 2nd script and 3rd script. I have tried to adjust it as well.
What I want to happen is:
Its quite a success already but when it comes to the stability, there a few errors and they are really random at times.
The error is,
Error: network timeout at: https://api.airtable.com/v2/bases/appFZ1FheZKBic29q/tables/tblkHJXbEg8lt9xzG/records/update
at main on line 45
Out of 60 records tested. There is 1 error like this. Also, sometimes there will be 2? Sometimes a record worked properly, then when I try to rerun it again, that record would show an error.
This is used in an automation. The only variable is recordID for your reference.
I know that I am a bit close, just need some more tips. :slightly_smiling_face:
Thank you so much!
Here is the code.
let config = input.config()
let submissionsTable = base.getTable('$MST');
let urlField = submissionsTable.getField('URl: $MST | Profile Pic');
let attachmentField = submissionsTable.getField('ATH: $MST | Profile Pic');
let query = await submissionsTable.selectRecordsAsync()
let record = query.getRecord(config.recordID)
let submissionsQuery = await submissionsTable.selectRecordsAsync();
let updates = [];
for (let record of submissionsQuery.records) {
let url = record.getCellValue(urlField);
let attachments = record.getCellValue(attachmentField);
// If this record already has an attachment, skip it.
if (url === null || attachments !== null) {
continue;
}
// Otherwise, attach the image at the URL.
updates.push({
id: record.id,
fields: {
[attachmentField.id]: [{url: url}]
}
});
}
// Update records in batches of 50.
while (updates.length > 0) {
await submissionsTable.updateRecordsAsync(updates.slice(0, 50));
updates = updates.slice(50);
}
let newPrefix = record.getCellValueAsString('PROD_CODE | FileName')
let newExtension = String('.png')
let files = record.getCellValue("ATH: $MST | Profile Pic")
// Get the extension and add it to the new name
let newFiles = []
for (let file of files) {
let newName = `${newPrefix}${newExtension}`
newFiles.push({url: file.url, filename: newName})
}
// Reattach the item with the new filename
await submissionsTable.updateRecordAsync(record, {
"ATH: $MST | Profile Pic": newFiles
});
Dec 03, 2020 09:45 AM
It sounds like the problem is that it takes too long to retrieve the attachment from Airtable.
Have you tried running the script in Scripting App from a button, instead of an automation? Automation scripts have time limitations.