Grouptabs – Export as CSV
One advantage of using the same software again and again is that the process and toolsets are already established and proven. Grouptabs uses CouchDB as its backend, a database that I have been using for various purposes for a long time. I have toolset and process for CouchDB.
In this case, I wanted a way to download or export all the transactions in a tab/group such as CSV. Our flow here involves utilizing CouchDB's REST APIs to retrieve the data, formatting it in Javascript, and then downloading it as a CSV. We do this using Greasemonkey/Violentmonkey—yet another familiar tool.
We use AJAX to call CouchDBs _all_docs API endpoint, and we will get the complete document.
function grouptabs() {
// GM.notification("grouptabs", "start");
var url = document.URL;
var extractedValue = url.split('/').pop();
// GM.notification("grouptabs",extractedValue);
var db_path ="https://backend.grouptabs.net/tab%2F"+extractedValue+"/_all_docs?include_docs=true"
var csv_file = extractedValue +".csv"
var xhr = new XMLHttpRequest();
xhr.open("GET",db_path, true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var jsonResponse = JSON.parse(xhr.responseText);
var csvData = jsonToCsv(jsonResponse.rows);
download(csvData,csv_file, "text/csv");
}
};
xhr.send();
}
Grouptabs has two types of documents defined by an attribute type; it can have two values: info or transaction. We are interested in transaction types of documents. Then, we convert the participants into rows (see getParticipantsData function) and create a CSV.
function getParticipantColumns(rows) {
const participantColumns = new Set();
rows.forEach(row => {
row.doc.participants.forEach(p => participantColumns.add(p.participant));
});
return Array.from(participantColumns);
}
function getParticipantsData(participants, participantColumns) {
const participantData = {};
participantColumns.forEach(col => {
participantData[col] = 0; // Initialize all columns with 0
});
participants.forEach(p => {
if (participantData.hasOwnProperty(p.participant)) {
participantData[p.participant] = p.amount;
}
});
return participantColumns.map(col => participantData[col]);
}
function jsonToCsv(rows) {
// Filter only "transaction" objects
rows = rows.filter(row => row.doc.type === "transaction");
// Extract columns from the first row
const columns = ["_id", "type", "timestamp", "transactionType", "description", "date"];
const csvRows = [];
const participantColumns = getParticipantColumns(rows);
// Add header
columns.push(...participantColumns);
csvRows.push(columns.join(","));
// Add rows
rows.forEach(row => {
const doc = row.doc;
const participantsData = getParticipantsData(doc.participants, participantColumns);
const values = [
doc._id,
doc.type,
doc.timestamp,
doc.transactionType,
doc.description,
doc.date,
...participantsData
];
csvRows.push(values.join(","));
});
return csvRows.join("\n");
}
Then, we form a blob and download it.
function download(data, filename, type) {
var file = new Blob([data], { type: type });
var a = document.createElement("a"),
url = URL.createObjectURL(file);
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
setTimeout(function() {
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
}, 0);
}
All of this is enabled only for the Grouptabs URL using Greasemonkey @match. And that's it. Our user script is ready to be used. You can import from here and use it.
1 Response
[…] I wrote a blog post about the bill-splitting apps I have used. I also released a userscript to add Download/Export as a CSV feature to Grouptabs. […]