Skip to content

Instantly share code, notes, and snippets.

@xkikeg
Created September 24, 2021 15:45
Show Gist options
  • Save xkikeg/12c6b72801706b90d3e425757ae83a20 to your computer and use it in GitHub Desktop.
Save xkikeg/12c6b72801706b90d3e425757ae83a20 to your computer and use it in GitHub Desktop.
Create ledger text out of Money forward (https://moneyforward.com/)
// ==UserScript==
// @name Moneyforward to ledger
// @version 1
// @grant GM.setClipboard
// @require https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js
// @match https://moneyforward.com/accounts/show/*
// ==/UserScript==
function runReport(node) {
var result = [];
$('#cf-detail-table > tbody > tr').each(function(i, trnode) {
result.push(convertTransaction(trnode));
});
result.reverse();
GM.setClipboard(result.join(''));
}
class Post {
constructor(account, amount, comment=null) {
this.account = account;
this.amount = amount;
this.comment = comment;
}
print() {
var res = ' ' + this.account + ' ' + this.amount;
if (this.comment) {
res += ' ; ' + this.comment;
}
return res;
}
}
function convertTransaction(trnode) {
var date;
var code;
var payee;
var amount;
var srcAccount;
var destAccount;
$(trnode).find('td').each(function(i, td) {
let tdtext = $(td).text().trim();
switch (i) {
case 0:
// do nothing
break;
case 1:
let datetext = $(td).data('table-sortable-value');
let match = /(\d+\/\d+\/\d+)-(\d+)/.exec(datetext);
if (!match) {
console.error('failed to match date: ', datetext);
} else {
date = match[1];
code = match[2];
}
break;
case 2:
payee = $(td).find('div span').text().trim();
break;
case 3:
amount = $(td).find('span.offset').text().trim();
break;
case 4:
let srcData = $(td).data('original-title');
if (srcData.startsWith('みずほ銀行 北沢支店 普通')) {
srcAccount = 'Assets:Banks:Mizuho:Kitazawa';
} else if (srcData.startsWith('みずほ銀行 兜町支店 普通')) {
srcAccount = 'Assets:Banks:Mizuho:Kabuto';
}
let dstBox = $(td).find('.transfer_account_box');
if (dstBox) {
switch(dstBox.text().trim()) {
case '三井住友カード':
destAccount = 'Liabilities:ANA Card';
break;
case 'セゾンカード':
destAccount = 'Liabilities:Mizuho Card';
break;
}
}
break;
case 6:
switch (tdtext) {
case '生命保険':
destAccount = 'Expenses:Insurances:Life';
break;
case 'その他保険':
destAccount = 'Expenses:Insurances:Medical';
break;
case '学費':
destAccount = 'Liabilities:Fixed:JASSO';
break;
case 'その他税・社会保障':
destAccount = 'Expenses:Tax:Income';
break;
}
break;
}
});
return [
'',
date + ' * (' + code + ') ' + payee,
new Post(srcAccount, amount + ' JPY').print(),
new Post(destAccount, negateAmount(amount) + ' JPY').print(),
'',
].join('\n');
}
function negateAmount(v) {
if (v[0] == '-') {
return v.slice(1);
}
return '-' + v;
}
window.addEventListener('load', init, false);
function init() {
var r= $('<input type="button" value="new button"/>');
$("#ttl_genyokinbreak_table").prepend(r);
r.on('click', runReport);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment