Skip to content

Instantly share code, notes, and snippets.

@sarajoha
Created December 28, 2024 20:27
Show Gist options
  • Save sarajoha/a33df7b93355beb6b8b47bc2df8e374e to your computer and use it in GitHub Desktop.
Save sarajoha/a33df7b93355beb6b8b47bc2df8e374e to your computer and use it in GitHub Desktop.
Appscript to record purchases with credit card
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