Skip to content

Instantly share code, notes, and snippets.

@ssimono
Created July 22, 2022 22:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ssimono/48e90b28775deee3e7f2e34a3f1337e1 to your computer and use it in GitHub Desktop.
Save ssimono/48e90b28775deee3e7f2e34a3f1337e1 to your computer and use it in GitHub Desktop.
Export the expenses of a Splittypie event into CSV. Runs on the browser only.
/**
* Usage: Copy this entire snippet and paste it into the developer console.
* A link will appear on the top just above the event title (on Desktop view).
* Just click it to get a CSV containing the expenses.
*
* Please double-check the result as this is made via frontend scrapping and
* can therefore miss edge cases or break upon future changes in the document
* structure.
*/
function collect() {
const selectors = Object.entries({
month: '.month',
day: '.day',
creditor: '.transaction-list-item-description strong',
subject: '.transaction-list-item-description em',
participants: '.transaction-list-item-description small',
amount: '.transaction-list-item-amount strong',
});
const expenses = [];
let year = undefined;
for (let div of document.querySelectorAll('.transaction-list-item')) {
const previousSibling = div.previousElementSibling;
if (previousSibling.classList.contains('transaction-list-date')) {
const yearStr = previousSibling.querySelector('strong').innerText;
year = parseInt(yearStr.replace(/^\D*/g, ''), 10);
}
const expense = Object.fromEntries(selectors.map(([field, selector]) =>
[field, div.querySelector(selector)?.innerText?.trim()]
));
const timestamp = Date.parse(`${expense.month} ${expense.day} ${year}`);
const date = Number.isNaN(timestamp)
? null
: new Date(timestamp).toISOString().substring(0, 10);
if (!expense.participants && /settled up/i.test(div.innerText)) {
expense.subject = 'Settled up';
expense.participants = div.querySelector('strong:last-child').innerText.trim();
}
expenses.push({
creditor: expense.creditor,
subject: expense.subject,
participants: expense.participants?.split(/\s*,\s*/).join('/'),
date,
amount: parseFloat(expense.amount),
});
}
return expenses;
}
const link = document.createElement('a');
document.querySelector('main .container').prepend(link);
link.innerText = 'Scrapping…';
const csvFields = ['creditor', 'subject', 'participants', 'date', 'amount'];
const csvData = [csvFields];
for(let expense of collect()) {
csvData.push(csvFields.map(f => expense[f]));
}
const url = window.URL.createObjectURL(new Blob([csvData.join('\n')], { type: 'text/csv' }));
link.setAttribute('href', url);
link.innerText = 'Download expenses as CSV';
@ssimono
Copy link
Author

ssimono commented Jul 22, 2022

@gauthier12
Copy link

Thank you !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment