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.
// 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.
Any insights or suggestions on how to improve the code would be incredibly helpful!
Thank you in advance for your support.