I'm working with a Google Sheets script that extracts data from email bodies. While the script successfully pastes data from most columns, it fails to paste the values from columns G and H. These columns contain text with hyperlinks to google drive.
Expected Behavior:
The script should copy and paste the complete value from columns G and H, including the text and the associated hyperlink.
Current Behavior:
The script doesn't even copy the plain text portion of the values in columns G and H, omitting the hyperlinks altogether.
Mail Body Example:
SUPPLIER: {cacho}
SERVICE_TYPE: {CD-001 Media buying (TV, press, Radio etc...)}
PROFORMA: {x}
INVOICE: {x}
UPLOADED_DATE: {15/07/2024}
In this example, 'x' represents the text with a hyperlink (To google drive) attached. The script should copy and paste the entire value, including 'x' and the hyperlink.
function processEmails() { try { var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); if (!sheet) { throw new Error('Active sheet not found'); } Logger.log('Opened active spreadsheet successfully.'); // Get unread messages from the "PRUEBAS" label var label = GmailApp.getUserLabelByName('PRUEBAS'); if (!label) { throw new Error('Label "PRUEBAS" not found'); } Logger.log('Retrieved label successfully.'); var threads = label.getThreads(); Logger.log('Found ' + threads.length + ' threads.'); for (var i = 0; i < threads.length; i++) { var thread = threads[i]; var messages = thread.getMessages(); // Sort the thread messages by date, from oldest to most recent messages.sort(function(a, b) { return a.getDate() - b.getDate(); }); var combinedData = {}; for (var j = 0; j < messages.length; j++) { var message = messages[j]; // Only process unread messages if (!message.isUnread()) { continue; } var body = getMessageBody(message); if (!body) { continue; } Logger.log('Message body: ' + body); // Log the entire message body var events = extractEvents(body, message); Logger.log('Extracted ' + events.length + ' events from message body.'); events.forEach(function(data) { var key = data['EVENT_NAME'] + data['SUPPLIER'] + data['UPLOADED_DATE']; if (!combinedData[key]) { combinedData[key] = data; Logger.log('Added data for key: ' + key); } else { combinedData[key] = mergeData(combinedData[key], data); Logger.log('Merged data for key: ' + key); } }); // Mark message as read after processing message.markRead(); Logger.log('Marked message as read: ' + message.getSubject()); } for (var key in combinedData) { var data = combinedData[key]; var rowToUpdate = findRow(sheet, data); if (rowToUpdate === -1) { updateSheet(sheet, data); Logger.log('Appended new row for key: ' + key); } else { updateRow(sheet, rowToUpdate, data); Logger.log('Updated row ' + rowToUpdate + ' for key: ' + key); } } } } catch (e) { Logger.log('Error: ' + e.message); } } function getMessageBody(message) { var body = message.getPlainBody(); Logger.log('Plain body: ' + body); // Log the plain body if (!body) { body = message.getRawContent(); Logger.log('Raw content: ' + body); // Log the raw content if (body) { body = convertHtmlToPlainText(body); Logger.log('Converted HTML to plain text: ' + body); // Log the converted plain text } } if (!body) { Logger.log('Message body is empty.'); return null; } Logger.log('Retrieved message body.'); return body; } function convertHtmlToPlainText(html) { var plainText = HtmlService.createHtmlOutput(html).getContent().replace(/<[^>]*>?/gm, ''); Logger.log('Converted HTML to plain text: ' + plainText); return plainText; } function extractEvents(body, message) { var events = []; Logger.log('Starting to extract events from body'); var sections = body.split(/SUPPLIER: \{/); Logger.log('Number of sections found: ' + sections.length); if (sections.length < 2) { Logger.log('No supplier sections found in the body.'); return events; } let globalEventData = {}; let firstSectionLines = sections[0].split('\n'); firstSectionLines.forEach(function(line) { let parts = line.split(':'); if (parts.length === 2) { let key = parts[0].trim().toUpperCase().replace(/ /g, '_'); let match = parts[1].match(/\{\s*([^}]+)\s*\}/); if (match) { globalEventData[key] = match[1].trim(); } } }); let eventName = globalEventData['EVENT_NAME']; // Get the EVENT_NAME once for (var i = 1; i < sections.length; i++) { let section = sections[i]; let data = Object.assign({}, globalEventData); section = 'SUPPLIER: {' + section; // Re-add the split string let lines = section.split('\n'); lines.forEach(function(line) { let parts = line.split(':'); if (parts.length === 2) { let key = parts[0].trim().toUpperCase().replace(/ /g, '_'); let match = parts[1].match(/\{\s*([^}]+)\s*\}/); if (match) { let value = match[1].trim(); if (key === 'UPLOADED_DATE' || key === 'DATE_OF_EXCHANGE' || key.startsWith('PAYMENT_DATE')) { value = parseDate(value); } data[key] = value; } } }); data['EVENT_NAME'] = eventName; // Apply the EVENT_NAME to each supplier if (data['SUPPLIER'] && data['UPLOADED_DATE']) { events.push(data); } else { Logger.log('Missing SUPPLIER or UPLOADED_DATE in section'); } } Logger.log('Extracted ' + events.length + ' events from message body.'); return events; } function mergeData(oldData, newData) { var merged = {}; for (var key in oldData) { merged[key] = oldData[key]; } for (var key in newData) { if (newData[key] && (!oldData[key] || newData[key] !== oldData[key])) { merged[key] = newData[key]; } } Logger.log('Merged data.'); return merged; } function findRow(sheet, data) { var range = sheet.getDataRange(); var values = range.getValues(); var targetDate = formatDate(new Date(data['UPLOADED_DATE'])); // Format date to dd/MM/yyyy for (var i = 1; i < values.length; i++) { if (values[i][1] === '') { // Stop checking if the row is empty break; } var eventName = values[i][1]; var supplier = values[i][4]; var uploadedDate = formatDate(new Date(values[i][9])); // Format date to dd/MM/yyyy Logger.log('Checking row ' + (i + 1) + ': EVENT_NAME=' + eventName + ', SUPPLIER=' + supplier + ', UPLOADED_DATE=' + uploadedDate); if (eventName === data['EVENT_NAME'] && supplier === data['SUPPLIER'] && uploadedDate === targetDate) { Logger.log('Found existing row for data at row ' + (i + 1) + '.'); return i + 1; } } Logger.log('No existing row found for data: EVENT_NAME=' + data['EVENT_NAME'] + ', SUPPLIER=' + data['SUPPLIER'] + ', UPLOADED_DATE=' + targetDate); return -1; } function updateSheet(sheet, data) { var lastRow = sheet.getLastRow(); var range = sheet.getRange(2, 2, lastRow, 1); // Check from column B onwards var values = range.getValues(); for (var i = 0; i < values.length; i++) { if (values[i][0] === '') { // Check if column B is empty var row = sheet.getRange(i + 2, 2, 1, 26); // From column B to AA row.setValues([[ data['EVENT_NAME'], // B '', // C (keep empty) data['OFFER_STATUS'] || '', // D data['SUPPLIER'], // E data['SERVICE_TYPE'] || '', // F data['PROFORMA'] || '', // G data['INVOICE'] || '', // H data['COORDINATOR'], // I formatDate(new Date(data['UPLOADED_DATE'])), // J (formatted to dd/MM/yyyy) data['EXCHANGE_ISO_A3_CODE'] || '',// K data['DATE_OF_EXCHANGE'] || '', // L data['ORIGINAL_CURRENCY'] || '', // M data['AMOUNT_IN_EUROS'] || '', // N data['PAYMENT_REASON'] || '', // O data['AMOUNT_EURO_1'] || '', // P data['AMOUNT_ORIGINAL_CURRENCY_1'] || '', // Q data['PAYMENT_METHOD'] || '', // R data['PAYMENT_LINK'] || '', // S data['PAYMENT_DATE_1'] || '', // T data['AMOUNT_EURO_2'] || '', // U data['AMOUNT_ORIGINAL_CURRENCY_2'] || '', // V data['PAYMENT_METHOD_2'] || '', // W data['PAYMENT_LINK_2'] || '', // X data['PAYMENT_DATE_2'] || '', // Y data['COMMENTS'] || '', // Z '' // AA (PAYMENT_STATUS) ]]); Logger.log('Added new row at position ' + (i + 2)); return; } } // If no empty row is found, append to the end var appendedRow = sheet.appendRow([ data['EVENT_NAME'], // B '', // C (keep empty) data['OFFER_STATUS'] || '', // D data['SUPPLIER'], // E data['SERVICE_TYPE'] || '', // F data['PROFORMA'] || '', // G data['INVOICE'] || '', // H data['COORDINATOR'], // I formatDate(new Date(data['UPLOADED_DATE'])), // J (formatted to dd/MM/yyyy) data['EXCHANGE_ISO_A3_CODE'] || '',// K data['DATE_OF_EXCHANGE'] || '', // L data['ORIGINAL_CURRENCY'] || '', // M data['AMOUNT_IN_EUROS'] || '', // N data['PAYMENT_REASON'] || '', // O data['AMOUNT_EURO_1'] || '', // P data['AMOUNT_ORIGINAL_CURRENCY_1'] || '', // Q data['PAYMENT_METHOD'] || '', // R data['PAYMENT_LINK'] || '', // S data['PAYMENT_DATE_1'] || '', // T data['AMOUNT_EURO_2'] || '', // U data['AMOUNT_ORIGINAL_CURRENCY_2'] || '', // V data['PAYMENT_METHOD_2'] || '', // W data['PAYMENT_LINK_2'] || '', // X data['PAYMENT_DATE_2'] || '', // Y data['COMMENTS'] || '', // Z '' // AA (PAYMENT_STATUS) ]); Logger.log('Appended new row to sheet.'); } function updateRow(sheet, rowToUpdate, data) { var currentRow = sheet.getRange(rowToUpdate, 1, 1, sheet.getLastColumn()).getValues()[0]; var row = sheet.getRange(rowToUpdate, 2, 1, 26); row.setValues([[ data['EVENT_NAME'] || currentRow[1], // B currentRow[2], // C (keep empty) data['OFFER_STATUS'] || currentRow[3], // D data['SUPPLIER'] || currentRow[4], // E data['SERVICE_TYPE'] || currentRow[5], // F data['PROFORMA'] || currentRow[6], // G data['INVOICE'] || currentRow[7], // H data['COORDINATOR'] || currentRow[8], // I formatDate(new Date(data['UPLOADED_DATE'])) || currentRow[9], // J (formatted to dd/MM/yyyy) data['EXCHANGE_ISO_A3_CODE'] || currentRow[10], // K data['DATE_OF_EXCHANGE'] || currentRow[11], // L data['ORIGINAL_CURRENCY'] || currentRow[12],// M data['AMOUNT_IN_EUROS'] || currentRow[13], // N data['PAYMENT_REASON'] || currentRow[14], // O data['AMOUNT_EURO_1'] || currentRow[15], // P data['AMOUNT_ORIGINAL_CURRENCY_1'] || currentRow[16], // Q data['PAYMENT_METHOD'] || currentRow[17], // R data['PAYMENT_LINK'] || currentRow[18], // S data['PAYMENT_DATE_1'] || currentRow[19], // T data['AMOUNT_EURO_2'] || currentRow[20], // U data['AMOUNT_ORIGINAL_CURRENCY_2'] || currentRow[21], // V data['PAYMENT_METHOD_2'] || currentRow[22], // W data['PAYMENT_LINK_2'] || currentRow[23], // X data['PAYMENT_DATE_2'] || currentRow[24], // Y data['COMMENTS'] || currentRow[25], // Z currentRow[26] // AA (PAYMENT_STATUS) ]]); Logger.log('Updated row ' + rowToUpdate + ' in sheet.'); } function formatCurrencyColumns(sheet, rowIndex, data) { const currencyColumns = ['N', 'P', 'Q', 'U', 'V']; currencyColumns.forEach(col => { let cell = sheet.getRange(col + rowIndex); let value = data[col]; if (!isNaN(parseFloat(value)) && isFinite(value) && value !== '') { cell.setValue(parseFloat(value)); cell.setNumberFormat('#,##0.00"€"'); // Use this format for point as thousand separator and comma as decimal } }); } function formatDate(date) { var day = ('0' + date.getDate()).slice(-2); var month = ('0' + (date.getMonth() + 1)).slice(-2); var year = date.getFullYear(); return day + '/' + month + '/' + year; } function parseDate(input) { var formats = [ {regex: /^\d{2}[-\/.]\d{2}[-\/.]\d{4}$/, format: 'dd/MM/yyyy'}, // European format {regex: /^\d{4}[-\/.]\d{2}[-\/.]\d{2}$/, format: 'yyyy/MM/dd'}, // American format ]; for (var i = 0; i < formats.length; i++) { if (formats[i].regex.test(input)) { var parts = input.split(/[-\/.]/).map(part => part.trim()); if (formats[i].format === 'dd/MM/yyyy') { return new Date(parts[2], parts[1] - 1, parts[0]); } else if (formats[i].format === 'yyyy/MM/dd') { return new Date(parts[0], parts[1] - 1, parts[2]); } } } Logger.log('Invalid date format for input: ' + input); return new Date('Invalid Date'); }
Execution Log:
0:52:01 Información Checking row 2: EVENT_NAME=PRUEBA, SUPPLIER=cacho, UPLOADED_DATE=15/07/2024
0:52:01 Información Found existing row for data at row 2.
0:52:02 Información Updated row 2 in sheet with PROFORMA: undefined, INVOICE: undefined
0:52:02 Información Updated row 2 for key: PRUEBAcachoMon Jul 15 2024 00:00:00 GMT+0200 (Central European Summer Time) with PROFORMA: undefined, INVOICE: undefined
Any help will be highly appreciated!!!!!!!!!
User | Count |
---|---|
25 | |
15 | |
4 | |
3 | |
3 |