Generating Task from Task Template

I’m new to Airtable scripting but I have figured out quite a bit already. Using many different sources I have written a script that copies my task template into my task table bases on picking the name of the template you want to use. Now I’ve been asked to add some additional fields with different types and my script does not work anymore.

Let’s start with the first field type with an issue: Multi-select
Current error:
P: Can’t create records: invalid cell value for field ‘Test Multi-Select Copy’.
Could not find a choice with that ID or name
at main on line 54

To me this error means that the lists aren’t the same but I there are only three and I checked that yesterday

I’m a little confused on how to show everything that someone might need to assist me. I put a screen shot above of my task template and below is my script:

//declares and then gets the project from the select list or from the row the button is on

const projectsTable = base.getTable(“Projects”);

let record = await input.recordAsync(‘Current Record’, projectsTable)

if (!record) {

throw new Error("It looks like you haven't selected a Project record to create tasks for. Is your Projects table empty?")

}

else {

let projectNameString = record.getCellValueAsString("Project Name")

output.text('Project Name: '+projectNameString)

}

let buttonPressedString = record.getCellValueAsString(“Has Button Been Pressed”)

if (buttonPressedString ===‘YES’) {

throw new Error("Looks like you have already generated your tasks from your template and you can not do this twice.")

}

//makes sure that there is a template or it sends back an error

let taskTemplateName = record.getCellValueAsString(“Task Templates”)

if (!taskTemplateName) {

throw new Error("Your Task Template field is empty and this process cannot continue.")

}

else {

output.text('Task Template: '+taskTemplateName)

}

// Look up template records and filter to just the selected Template Header

const taskTemplateTable = base.getTable(“Task Templates”);

let taskTemplateQuery = await taskTemplateTable.selectRecordsAsync();

//trying to filter the results to just the task template header at hand

let filteredRecords = taskTemplateQuery.records.filter(record => {

let filterName = record.getCellValueAsString("Task Header Name");

return filterName === taskTemplateName

});

let recordsToCreate = filteredRecords.map((templateRecord) => ({

fields: {

    "Task Name": templateRecord.getCellValue("Task Name"),

    "Work Days from Start": templateRecord.getCellValue("WORK DAYS FROM START"),

    "Estimated Time (hr:mm)": templateRecord.getCellValue("Estimated Time (hr:mm)"),

    "Assignee": templateRecord.getCellValue("Assigned to"),

    "Task Status": {name: templateRecord.getCellValueAsString("Task Status")},

    "Task Type": {name: templateRecord.getCellValueAsString("Task Type")},

    "Task Notes": templateRecord.getCellValue("Task Notes"),

    "Project": [record],

// “Predecessor Task” : templateRecord.getCellValue(“Task Name (from Predecessor Task)”),

//Below is the way to format a URL field type

// “Test URL Copy”: templateRecord.getCellValue(“Test URL Copy”),

//as of 2021-04-06 I didn’t have this one working yet

//Below is the way to format a Multi-Select field type

   "Test Multi-Select Copy": templateRecord.getCellValue("Test Template Multi-Select Copy")

}}));

//load the templated tasks to the Task Table

const whereToPutTheTasks = base.getTable(“Tasks”);

await whereToPutTheTasks.createRecordsAsync(recordsToCreate);

//updates field that flags that the button has been pressed

await projectsTable.updateRecordAsync(record, {“Has Button Been Pressed” : ‘YES’} )

output.text(“Done!”);

Welcome to the community, @Randi_Travers! :smiley:

I think that I see the problem. You’re directly passing the existing cell value to the new one, which (unfortunately) won’t work with multiple select fields:

(BTW: when sharing code, it’s helpful to format it as preformatted text using the </> button in the post editor toolbar)

Earlier in your script you’re doing the right thing with the {Task Status} and {Task Type} single select fields and passing objects with a name property. Multiple select fields are similar, but they require an array of such objects. To properly set that up, you’ll need to get the names of the chosen items from the original. The original cell value returns an array of objects that also contain an id property, and those IDs are unique to each field.

This should work:

"Test Multi-Select Copy": templateRecord.getCellValue("Test Template Multi-Select Copy") === null
  ? null
  : templateRecord.getCellValue("Test Template Multi-Select Copy").map(item => { return {name: item.name} })

This uses the ternary operator, which is a shortcut way of doing an if...else statement. In short it’s saying, “If the cell is empty, assign an empty value; otherwise map the existing array of objects to a new array of objects that will work for record creation.” (Ternary operators are not often split across multiple lines, but if that weren’t done the whole line would be crazy long. Most of the time for lengthy calculations like this I assign the result to a variable before building the object to use for record creation specifically to avoid such long lines. :slight_smile: )

1 Like

@Justin_Barrett - thank you for your reply. Your line of code does the trick and now I know how to handle other data if we don’t require data to be in the template. Sorry about the messy post I couldn’t figure out why mine looked so different than the other posts but I also couldn’t delete it after I posted it either. Anyways, do you have any recommendations on how to code a linked field for predecessor information. We are planning on having a column in our Template Table to have the user pick (from the drop down) which row is the row before - but then when I use my script to ‘copy’ this over the record id won’t be the same? I’ve started reading through posts in the Airtable community to try to figure this out and I saved some code on Friday that may work but none of it was quite right. Not sure if we even need to have the user do that first part. Anyways - thanks in advance for any advice