Here is my problem:
I need the following to happen every time an email arrives in the “PRUEBA” label/folder in GMAIL:
The data from the email body should be copied to a Google Sheets document in predefined fields.
If the row does not already exist in Google Sheets, then it should create the row immediately below an existing row.
If the row already exists because it was created earlier (by checking for matches in columns B, E, I), the existing row should be updated if there is new information in the email thread.
Conditional formatting and column A should not be considered when verifying if the row is empty.
Question: Is it possible to have a template for the email with defined fields for the user to fill in to simplify the process? Or is it better for the user to write the names of the fields manually one by one followed by a colon and then the information to be copied?
Below is the script I have developed. I am stuck and don’t know how to proceed.
Thank you in advance
// Function to find the first empty row, ignoring rows with validations but no data
function getFirstEmptyRow(sheet) {
var data = sheet.getDataRange().getValues();
for (var i = 1; i < data.length; i++) { // Start at 1 to ignore headers
if (isRowEmpty(data[i])) {
return i + 1;
}
}
return data.length + 1; // If no empty row is found, return the next available row
}
// Function to check if a row is empty, ignoring data validations
function isRowEmpty(row) {
for (var i = 1; i < row.length; i++) { // Start at 1 to ignore the index column
if (row[i] !== '') {
return false;
}
}
return true;
}
// Function to extract data from email and copy it to Google Sheets in specific columns
function extractDataFromEmail() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
if (!spreadsheet) {
Logger.log('No active spreadsheet found.');
return;
}
var sheet = spreadsheet.getActiveSheet();
if (!sheet) {
Logger.log('No active sheet found.');
return;
}
// Adjust search to include unread emails in the "PRUEBAS" label
var threads = GmailApp.search('label:PRUEBAS is:unread');
Logger.log('Number of threads found: %s', threads.length);
if (threads.length == 0) {
Logger.log('No unread emails found in the "PRUEBAS" label.');
return;
}
// Get existing data to check for duplicates
var dataRange = sheet.getDataRange();
var dataValues = dataRange.getValues();
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
Logger.log('Number of messages in thread %s: %s', i, messages.length);
// Only process the first message in the thread
var message = messages[0];
var body = message.getBody();
var subject = message.getSubject();
var from = message.getFrom();
var date = message.getDate();
Logger.log('Processing message %s from thread %s', 0, i);
Logger.log('Subject: %s', subject);
Logger.log('From: %s', from);
Logger.log('Date: %s', date);
var data = {
eventName: '',
offerStatus: '',
supplier: '',
fullPaymentDueDate: '',
originalCurrency: '',
amountInEuros: '',
payment1: '',
amount1: '',
paymentMethod: '',
paymentLink: ''
};
var lines = body.split('n');
Logger.log('Lines from the email body: %s', JSON.stringify(lines));
for (var k = 0; k < lines.length; k++) {
if (lines[k].includes('EVENT NAME:')) {
data.eventName = lines[k].split('EVENT NAME:')[1].trim();
Logger.log('Extracted EVENT NAME: %s', data.eventName);
}
if (lines[k].includes('OFFER STATUS:')) {
data.offerStatus = lines[k].split('OFFER STATUS:')[1].trim();
Logger.log('Extracted OFFER STATUS: %s', data.offerStatus);
}
if (lines[k].includes('SUPPLIER:')) {
data.supplier = lines[k].split('SUPPLIER:')[1].trim();
Logger.log('Extracted SUPPLIER: %s', data.supplier);
}
if (lines[k].includes('FULL PAYMENT DUE DATE:')) {
data.fullPaymentDueDate = lines[k].split('FULL PAYMENT DUE DATE:')[1].trim();
Logger.log('Extracted FULL PAYMENT DUE DATE: %s', data.fullPaymentDueDate);
}
if (lines[k].includes('ORIGINAL CURRENCY:')) {
data.originalCurrency = lines[k].split('ORIGINAL CURRENCY:')[1].trim();
Logger.log('Extracted ORIGINAL CURRENCY: %s', data.originalCurrency);
}
if (lines[k].includes('AMOUNT IN EUROS:')) {
data.amountInEuros = lines[k].split('AMOUNT IN EUROS:')[1].trim();
Logger.log('Extracted AMOUNT IN EUROS: %s', data.amountInEuros);
}
if (lines[k].includes('PAYMENT % N°1:')) {
data.payment1 = lines[k].split('PAYMENT % N°1:')[1].trim();
Logger.log('Extracted PAYMENT % N°1: %s', data.payment1);
}
if (lines[k].includes('AMOUNT N° 1:')) {
data.amount1 = lines[k].split('AMOUNT N° 1:')[1].trim();
Logger.log('Extracted AMOUNT N° 1: %s', data.amount1);
}
if (lines[k].includes('PAYMENT METHOD:')) {
data.paymentMethod = lines[k].split('PAYMENT METHOD:')[1].trim();
Logger.log('Extracted PAYMENT METHOD: %s', data.paymentMethod);
}
if (lines[k].includes('PAYMENT LINK:')) {
data.paymentLink = lines[k].split('PAYMENT LINK:')[1].trim();
Logger.log('Extracted PAYMENT LINK: %s', data.paymentLink);
}
}
Logger.log('Extracted data: %s', JSON.stringify(data));
var foundRow = -1;
for (var row = 1; row < dataValues.length; row++) {
if (dataValues[row][1] == data.eventName && dataValues[row][4] == data.supplier) { // Assuming column B (index 1) is EVENT NAME and column E (index 4) is SUPPLIER
foundRow = row + 1;
break;
}
}
if (foundRow == -1) {
var newRow = [
date,
data.eventName,
'',
data.offerStatus,
data.supplier,
'',
'',
'',
'',
data.fullPaymentDueDate,
'',
'',
data.originalCurrency,
data.amountInEuros,
'',
data.payment1,
data.amount1,
data.paymentMethod,
data.paymentLink,
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
''
];
// Find the first empty row
var firstEmptyRow = getFirstEmptyRow(sheet);
Logger.log('Adding new row at position: %s', firstEmptyRow);
try {
sheet.getRange(firstEmptyRow, 1, 1, newRow.length).setValues([newRow]); // Add the new row in the first empty row
Logger.log('Row added successfully');
} catch (e) {
Logger.log('Error adding row: %s', e.message);
}
} else {
var rowToUpdate = sheet.getRange(foundRow, 1, 1, dataRange.getLastColumn()).getValues()[0];
if (data.eventName !== '') rowToUpdate[1] = data.eventName; // Column B
if (data.offerStatus !== '') rowToUpdate[3] = data.offerStatus; // Column D
if (data.supplier !== '') rowToUpdate[4] = data.supplier; // Column E
if (data.fullPaymentDueDate !== '') rowToUpdate[9] = data.fullPaymentDueDate; // Column J
if (data.originalCurrency !== '') rowToUpdate[12] = data.originalCurrency; // Column M
if (data.amountInEuros !== '') rowToUpdate[13] = data.amountInEuros; // Column N
if (data.payment1 !== '') rowToUpdate[15] = data.payment1; // Column P
if (data.amount1 !== '') rowToUpdate[16] = data.amount1; // Column Q
if (data.paymentMethod !== '') rowToUpdate[17] = data.paymentMethod; // Column R
if (data.paymentLink !== '') rowToUpdate[18] = data.paymentLink; // Column S
Logger.log('Updating existing row: %s', JSON.stringify(rowToUpdate));
// Update the existing row with new data
try {
sheet.getRange(foundRow, 1, 1, rowToUpdate.length).setValues([rowToUpdate]);
Logger.log('Row updated successfully');
} catch (e) {
Logger.log('Error updating row: %s', e.message);
}
}
message.markRead();
}
}
MJB is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.