Google Apps Script はマジですごい。自分でサーバーを持たず、定期的に Gmail のメールを集計することができる
最近知ったがGoogle Apps Scriptはだいぶいろいろなことができてすごい。
ので、とりあえず楽天カード (今話題) の売上情報メールを集計して家計簿に記録していくみたいなスクリプト (Google Apps Script で使用する言語は JavaScript) を書いてみた。
Google SpreadSheet を開き、ツール → スクリプトエディタ で開かれるエディタに以下をコピペして、run 関数を実行すると、Gmail のメール直近1ヶ月のうち、楽天カードの売上メールから決済情報を抜きだし、シートに転記することができる。手動で実行してもいいが、定期的に実行することもできるみたいだ。
また、ウェブアプリも作ることができて、CSVのインポート画面を作ることもできそうなので作ってみてる。銀行のサイトでブックマークレットを実行すると CSV をつくってインポート画面を開く、みたいなことができそうだ。現金記録用のアプリだけ何か良さそうなのを見つければ、あとはほぼ自動で家計簿的なものを作れそうだと思う。
Google Apps Script はカレンダーの予定とかもいじれるようなので、例えば旅行の予定を入れておけば、自動でそれらも纏めて家計簿の備考欄に追記できると思う。大変夢が広がる。
ただしいくつか欠点もありそうだと思う。
- ウェブアプリは大変遅い
- スクリプト実行6分の時間制限
- Google に完全にロックインされる (もはや抜けようがない)
function run () {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var exists = {};
var values = sheet.getDataRange().getValues();
for (var i = 0, row; row = values[i]; i++) {
exists[ [ row[0], row[1], row[4] ].join(':') ] = true;
}
var rakuten = getRakutenCardData(new Date(new Date().getTime() - (1000 * 60 * 60 * 24 * 30)));
for (var i = 0, it; it = rakuten[i]; i++) {
var debit = guessTitle(it.place);
var credit = "クレジット (楽天)";
var row = [it.date, it.place, debit, credit, it.amount, "支払い予定日: " + [it.pay_date.getYear(), it.pay_date.getMonth() + 1, it.pay_date.getDate()].join('/') ];
if (exists[ [ row[0], row[1], row[4] ].join(':') ]) continue;
sheet.appendRow(row);
}
sheet.sort(1);
function guessTitle (name) {
if (/ガス|ガス|スイドウ|スイドウ|水道|デンキ|電力/.test(name)) {
return "光熱費";
} else
if (/ユニクロ/.test(name)) {
return "衣服費";
} else
if (/スーパー/.test(name)) {
return "食費";
} else
if (/KDDI/.test(name)) {
return "通信費";
} else
if (/SONY ONLINE SERVICES|デイ-エムエム/.test(name)) {
return "娯楽費";
} else {
return "";
}
}
}
var regexp = new RegExp('<tr><td align="center" bgcolor="#ffff00"><font size="-1"><input type="checkbox" name="uriage\\[\\]" value="[0-9]+"></font></td><td align="center"><font size="-1">([0-9]+)/([0-9]+)/([0-9]+)</font></td><td align="left"><font size="-1">([^<]+)</font></td><td align="center"><font size="-1">[^<]+</font></td><td align="right"><font size="-1">([0-9,]+) 円</font></td><td align="center"><font size="-1">([0-9]+)/([0-9]+)</font></td><td align="right"><font size="-1">[0-9]+ ポイント</font></td><td align="right"><font size="-1">[0-9]+/[0-9]+</font></td></tr>', 'g');
function getRakutenCardData (fromDate) {
var result = [];
var newer = [fromDate.getYear(), fromDate.getMonth() + 1, fromDate.getDate()].join('/');
var threads = GmailApp.search('subject:"【売上情報】カード利用お知らせメール" newer:' + newer, 0, 50);
for (var i = 0, it; it = threads[i]; i++) {
var messages = it.getMessages();
for (var j = 0, message; message = messages[j]; j++) {
var matched = [];
message.getBody().replace(regexp, function (_, year, month, date, place, amount, pay_year, pay_month) {
Logger.log([ year, month, date, place, amount ]);
matched.push({
date : new Date(+year, +month - 1, +date),
pay_date : new Date(+pay_year, +pay_month - 1, 27),
place : place,
amount : +(amount.replace(/,/g, ''))
});
});
if (matched.length) {
result = result.concat(matched);
} else {
Logger.log("unmatched: %s (%s)", message.getId(), message.getSubject());
}
}
}
Logger.log(result);
return result;
}