Created
December 28, 2024 20:27
-
-
Save sarajoha/a33df7b93355beb6b8b47bc2df8e374e to your computer and use it in GitHub Desktop.
Appscript to record purchases with credit card
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function extractBankEmailData() { | |
const subjectKeyword = "emailLabel"; // Replace with your Gmail label | |
const sheetName = "sheetName"; // Replace with your sheet name | |
// Calculate dates for filtering emails | |
const today = new Date(); | |
const yesterday = new Date(today); | |
yesterday.setDate(today.getDate() - 1); | |
// Format dates as YYYY/MM/DD for Gmail search | |
const formattedToday = formatDate(today); | |
const formattedYesterday = formatDate(yesterday); | |
// Search for emails with the specified subject | |
// const searchQuery = `subject:${subjectKeyword} after:${formattedYesterday}`; | |
const searchQuery = `subject:${subjectKeyword} after:${formattedYesterday} before:${formattedToday}`; | |
const threads = GmailApp.search(searchQuery, 0, 10); // Get the latest 10 threads matching the subject | |
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName); | |
// Get the current exchange rate from COP to EUR | |
const exchangeRate = getExchangeRate("COP", "EUR"); | |
if (threads.length === 0) { | |
Logger.log("No emails found with the specified subject."); | |
return; | |
} | |
// Find the last non-empty row in columns A to F | |
let currentRow = findLastNonEmptyRow(sheet, 1, 6) + 1; // Start at the next available row | |
threads.forEach((thread) => { | |
const messages = thread.getMessages(); | |
messages.forEach((email) => { | |
const body = email.getPlainBody(); | |
// Regular expression to extract data | |
const amountMatch = body.match(/(?:COP|\$)([\d.,]+)/); | |
const date = email.getDate(); | |
const merchantMatch = body.match(/en (.+?) con tu T\.Cred/); | |
if (amountMatch && date && merchantMatch) { | |
const amount = amountMatch[1].replace(".", "").replace(",", "."); | |
const formattedDate = formatDateMDY(date) | |
const amountEUR = exchangeRate ? (amount * exchangeRate).toFixed(2) : null; | |
const merchant = merchantMatch ? merchantMatch[1] : "Unknown"; | |
const category = categorizeMerchant(merchant); | |
// Append to the spreadsheet | |
sheet.getRange(currentRow, 1, 1, 6).setValues([[formattedDate, amount, amountEUR, null, category, merchant]]); | |
currentRow++; | |
} | |
}); | |
}); | |
} | |
function formatDate(date) { | |
const year = date.getFullYear(); | |
const month = String(date.getMonth() + 1).padStart(2, "0"); | |
const day = String(date.getDate()).padStart(2, "0"); | |
return `${year}/${month}/${day}`; | |
} | |
function formatDateMDY(date) { | |
const year = date.getFullYear(); | |
const month = String(date.getMonth() + 1).padStart(2, "0"); | |
const day = String(date.getDate()).padStart(2, "0"); | |
return `${month}/${day}/${year}`; | |
} | |
// Utility function to find the last non-empty row in a specific column range | |
function findLastNonEmptyRow(sheet, startCol, endCol) { | |
const range = sheet.getRange(2, startCol, sheet.getLastRow(), endCol - startCol + 1); | |
const values = range.getValues(); | |
for (let row = values.length - 1; row >= 0; row--) { | |
if (values[row].some((cell) => cell !== "")) { | |
return row + 2; // Adjust for row index starting from 2 | |
} | |
} | |
return 1; // Return 1 if no non-empty rows are found | |
} | |
// Fetch the exchange rate using a public API | |
function getExchangeRate(base, target) { | |
const url = `https://api.exchangerate-api.com/v4/latest/${base}`; | |
try { | |
const response = UrlFetchApp.fetch(url); | |
const data = JSON.parse(response.getContentText()); | |
return data.rates[target]; | |
} catch (error) { | |
Logger.log(`Error fetching exchange rate: ${error}`); | |
return null; | |
} | |
} | |
function categorizeMerchant(merchant) { | |
if (/Mercado/i.test(merchant)) { | |
return "Comida"; | |
} | |
if (/salud/i.test(merchant)) { | |
return "Salud"; | |
} | |
// Add more categories as needed | |
return "Salida"; // Default category | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment