Help

Trouble with Mini Extension: CSV Upload to Multiple Tables

Topic Labels: Data
591 2
cancel
Showing results for 
Search instead for 
Did you mean: 
Narcy
4 - Data Explorer
4 - Data Explorer

Hello Airtable Community,

I am new to Airtable and currently working on a custom mini extension in Airtable that aims to upload CSV files into multiple tables within my base automatically. I have written a script for the mini extension to handle the CSV upload and record creation, but I'm encountering some errors.

- The script prompts the user to upload a CSV file using the built-in file picker.
- The CSV file has data that needs to be distributed across different tables, namely: contacts, company, line items, services, and invoices.
- Each table has unique fields and linked records, and the script maps the CSV data to the appropriate fields accordingly.
- I am using native JavaScript to read and parse the CSV content.

Issue:
When testing the mini extension and attempting to upload the CSV file, I encountered the following error: [Describe the specific error message you received, if any].

Code:
Javascript:

// Function to handle file upload
async function handleFileUpload() {
const fileInput = document.createElement('input');
fileInput.type = 'file';

fileInput.addEventListener('change', async (event) => {
const file = event.target.files[0];
if (file) {
const csvContent = await readCSVFile(file);
if (csvContent) {
try {
const tableName = 'Narcy Consulting'; // Replace with the appropriate table name based on user input or selection

let csvRows = parseCSVContent(csvContent);

let newRecords;
switch (tableName) {
case 'contacts':
newRecords = csvRows.map((csvRow) => ({
fields: {
'First Name': csvRow['First Name'],
'Last Name': csvRow['Last Name'],
'Full Name': csvRow['Full Name'],
'Email': csvRow.Email,
'Phone Number': csvRow['Phone Number'],
// Add more fields as needed based on your 'contacts' table
},
}));
break;

case 'company':
newRecords = csvRows.map((csvRow) => ({
fields: {
'Name': csvRow.Name,
// Add more fields as needed based on your 'company' table
},
}));
break;

case 'line items':
newRecords = csvRows.map((csvRow) => ({
fields: {
'Line Item ID': csvRow['Line Item ID'],
// Add more fields as needed based on your 'line items' table
},
}));
break;

case 'services':
newRecords = csvRows.map((csvRow) => ({
fields: {
'Name': csvRow.Name,
// Add more fields as needed based on your 'services' table
},
}));
break;

case 'invoices':
newRecords = csvRows.map((csvRow) => ({
fields: {
'Invoice ID': csvRow['Invoice ID'],
// Add more fields as needed based on your 'invoices' table
},
}));
break;

default:
throw new Error(`Table ${tableName} not found.`);
}

while (newRecords.length > 0) {
const recordsToCreate = newRecords.splice(0, 10);
await createRecordsInBatches(tableName, recordsToCreate);
}

alert(`CSV data successfully uploaded to ${tableName} in Airtable.`);
} catch (error) {
console.error('Error uploading CSV data to Airtable:', error);
alert('An error occurred while uploading CSV data.');
}
}
}
});

// Trigger file input dialog
fileInput.click();
}

// Helper function to read CSV file content
function readCSVFile(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (event) => {
resolve(event.target.result);
};
reader.onerror = (event) => {
reject(event.error);
};
reader.readAsText(file);
});
}

// Helper function to parse CSV content into rows
function parseCSVContent(csvContent) {
const lines = csvContent.split('\n');
const headers = lines[0].split(',');

const rows = [];
for (let i = 1; i < lines.length; i++) {
const line = lines[i].split(',');
if (line.length !== headers.length) {
console.error('Error parsing CSV content: Inconsistent number of columns in row', i + 1);
return null;
}

const row = {};
for (let j = 0; j < headers.length; j++) {
row[headers[j].trim()] = line[j].trim();
}
rows.push(row);
}

return rows;
}

async function createRecordsInBatches(tableName, records) {
const table = base.getTable(tableName);
await table.createRecordsAsync(records);
}

// Add a button or other UI element to trigger the file upload
document.getElementById('uploadCSVButton').addEventListener('click', handleFileUpload);
 
Expected Behavior:

I expect the script to read the CSV file, map the data to the corresponding fields in each table, and create new records accordingly.

Request for Help:
I would greatly appreciate any guidance or assistance with debugging the script and resolving the errors. Specifically, I need help with:
- Parsing the CSV content and ensuring it aligns with the table structures.
- Handling linked records and correctly mapping them from the CSV data.
- Verifying the implementation of each table's fields and data in the script.

Any insights or suggestions on how to improve the code would be incredibly helpful!

Thank you in advance for your support.

Best regards,
Narcy

2 Replies 2
ScottWorld
18 - Pluto
18 - Pluto

Sorry, I don’t know scripting, so other people will need to chime in below to help you with your scripting errors.

However, in the meantime, while you’re waiting for others to help:

If you’d like to skip scripting altogether and do all of this in a no-code/low-code way, there is an easy way to automatically import CSV files into Airtable with no coding at all, along with having all of the data map into the appropriate tables with the appropriate linking.

All of this can be done in a no-code/low-code way with Make’s CSV modules and Make’s Airtable modules.

I just discussed importing CSV files with Make on last week’s episode of the BuiltOnAir podcast, so you can see exactly how it’s done.

(There can be a bit of a learning curve with Make, which is why I created this basic navigation video for Make, along with the links to a few other Make training resources.)

p.s. If you’d like to hire an expert Airtable consultant to help you with any of this, please feel free to contact me through my website: Airtable consultingScottWorld

Hi,
I would suggest to use 

Alexey_Gusev_0-1690961006340.png

because unformatted code is hard to read, so it's a small chance somebody will read it.

But the most important is which part of your code is written by chatbot. Airtable has several contexts for coding, each with it's own little part of commands and ways to manage the data. Chatbot "uses all of them at full power", that means such code has very little chance to run, with significant part of overengineering, and in most cases it's easier to write new from scratch. 

When you open code editor in "Extensions", you can click on Examples and see Spreadsheet Importer, loading single file. I guess you already seen it, but I can't say for sure whether it possible to modify it to load several tables from a single file. 
I think, it's hard to 'explain' built-in file picker that 'here finishes table 1 and table 2 should begin', as such feature doesn't installed in it.