Dr.WalletのデータからCSVを作る(解説編)
「実践編」からの続き。
2016/11/03:Chrome拡張機能ができました。期間を指定して一括取得できます。
Dr.WalletにはCSV出力(エクスポート)機能がないので、自分でやってしまおうという話です。
前回紹介したプログラムの解説編です。あんまり解説してません。
ソースを貼っておきますので、自由に改変して使いやすいようにしてどうぞ。当たり前だけど商用利用とかしないでね。他のウェブサイトにまるまるコピペするのも悲しいのでやめてね。
転載する場合は、このページを貼ってくださるとニッコリします。
Sponsored Link
ただしjavascript書いたのも久しぶりなので、基本的にクソコードです。「undefined?よくわかんね。」レベルなので変なところは多めに見てね。最近VBAerなので、にじみ出ているかもしれません。
※支出と収入のラベルがあべこべになっていましたので、修正しました。
<textarea id="jinput" placeholder='{ "aaData":[[ ... というようなDr.Walletのデータをペーストして下さい。'></textarea><br>
<input id="outputsColumnName" value="true" type="checkbox" checked="checked"/>列名を出力する<br/>
<input id="splitsInOut" value="true" type="checkbox" checked="checked"/>収支は別の列に出力する(割引(マイナスの支出)とかのデータも、よくわからないのでそのまま出力します。)<br/>
<input id="outputsItems" value="true" type="checkbox" checked="checked"/>明細を出力する(明細を出力しないの場合、複数カテゴリーがあるときは「食費/日用雑貨」という形になります。)<br/>
<input id="outputsTransfers" value="true" type="checkbox" checked="checked"/>振替を出力する<br/>
<input value="CSVにしてみる" onclick="joutput.value = dw_parse()" type="button"><br>
<textarea id="joutput" placeholder="ここにCSVが出力されます。"></textarea></p>
<script>var dw_parse = function() {
//unicodeをデータをデコードして、JSONをパースする
var data = JSON.parse( uDecode( document.getElementById('jinput').value) );
//明細に突合させるためのレシートデータ
var receiptList = {};
//CSVを作るための連想配列オブジェクト
var csvData;
//csvDataのリスト
var csvList = [];
//処理対象の年月
var currentYM;
//JSONデータのaaData (レシートデータ)
for(var i in data.aaData){
//transferのデータが、当月以外も取得されているので、
//当月のデータのみCSVにする。
//receiptが存在せず、transferしかない場合は、たぶんうまく動かない。
if(!currentYM){
currentYM = data.aaData[i][0].substr(0,7);
}else if(currentYM != data.aaData[i][0].substr(0,7)){
continue;
}
if(data.aaData[i][8] == 'receipt') {
var receiptData = new Object();
receiptData['date'] = data.aaData[i][0];
receiptData['store'] = data.aaData[i][1];
receiptData['amount'] = data.aaData[i][2];
receiptData['category'] = data.aaData[i][3];
receiptData['assets'] = data.aaData[i][4];
receiptData['sortkey'] = data.aaData[i][5];
receiptData['isexpense'] = data.aaData[i][6];
receiptList[data.aaData[i][5]] = receiptData;
}else if(data.aaData[i][8] == 'transfer'){
if(document.getElementById('outputsTransfers').checked) {
csvData = new Object();
csvData['date'] = data.aaData[i][0];
csvData['store'] = data.aaData[i][1];
csvData['item'] = '';
csvData['amount'] = data.aaData[i][2];
csvData['category'] = data.aaData[i][3];
csvData['assets'] = data.aaData[i][4];
csvData['sortkey'] = data.aaData[i][5];
csvData['isexpense'] = (data.aaData[i][6] == null) ? '' : data.aaData[i][6];
csvList.push(csvData);
}
}
};
if(document.getElementById('outputsItems').checked) {
//JSONデータのtransactions (明細データ)
for( var t in data.transactions){
for( var u in data.transactions[t]){
csvData = new Object();
csvData['date'] = receiptList[t]['date'];
csvData['store'] = receiptList[t]['store'];
csvData['item'] = (data.transactions[t][u]['name'] == null) ? '' : data.transactions[t][u]['name'];
csvData['amount'] = data.transactions[t][u]['amount'];
csvData['category'] = data.transactions[t][u]['category_name'];
csvData['assets'] = receiptList[t]['assets'];
csvData['sortkey'] = u;
csvData['isexpense'] = data.transactions[t][u]['is_expense'];
csvList.push(csvData);
};
}
}else{
//明細不要の場合はreceiptListをそのままcsvDataに追加
for( r in receiptList){
csvData = new Object();
csvData['date'] = receiptList[r]['date'];
csvData['store'] = receiptList[r]['store'];
csvData['item'] = '';
csvData['amount'] = receiptList[r]['amount'];
csvData['category'] = receiptList[r]['category'].replace(/<br>/g, '/');
csvData['assets'] = receiptList[r]['assets'];
csvData['sortkey'] = receiptList[r]['sortkey'];
csvData['isexpense'] = receiptList[r]['isexpense'];
csvList.push(csvData);
}
}
//ソートしてみる
csvList.sort(function(a, b){
if(a['date'] < b['date']) {return -1;}
if(a['date'] > b['date']) {return 1;}
if(a['sortkey'] < b['sortkey']) {return -1;}
if(a['sortkey'] > b['sortkey']) {return 1;}
});
var ret = '';
//列名の出力
if(document.getElementById('outputsColumnName').checked){
ret += '日付,口座,店名,';
if(document.getElementById('outputsItems').checked){
ret += '品名,';
}
ret += 'カテゴリー,';
if(document.getElementById('splitsInOut').checked){
ret += '支出金額,収入金額';
}else{
ret += '収支,金額';
}
ret += '\r\n';
}
//CSV出力
for( var c in csvList ){
ret += escapeComma(csvList[c]['date']) + ',';
ret += escapeComma(csvList[c]['assets']) + ',';
ret += escapeComma(csvList[c]['store']) + ',';
if(document.getElementById('outputsItems').checked){
//明細
ret += escapeComma(csvList[c]['item']) + ',';
}
ret += escapeComma(csvList[c]['category']) + ',';
if(document.getElementById('splitsInOut').checked){
//収支を別の列に出力
if(csvList[c]['isexpense'] === true){
ret += escapeComma(csvList[c]['amount']) + ',';
}else if(csvList[c]['isexpense'] === false){
ret += ',' + escapeComma(csvList[c]['amount']);
}else{
//振替
ret += escapeComma(csvList[c]['amount']) + ',' + escapeComma(csvList[c]['amount']);
}
}else{
//収支の別を出力
if(csvList[c]['isexpense'] === true){
ret += '支出';
}else if(csvList[c]['isexpense'] === false){
ret += '収入';
}else{
ret += '';
}
ret += ',' + escapeComma(csvList[c]['amount']);
}
ret += '\r\n';
}
return ret;
};
//unicode表現の文字列をデコードする
var uDecode = function(str) {
return str.replace(/\\u([a-fA-F0-9]{4})/g, function(a, b) {
return String.fromCharCode(parseInt(b, 16));
});
};
//カンマを全角にする
var escapeComma = function(str){
return String(str).replace(',', ',');
};
</script>
Sponsored Link
- JSONは、aaDataとtransactionsに大きく分かれています。
- aaDataはレシートデータと口座連携データ。
- 2重配列で、コアのデータは引用符付きのCSVのようです。
- CSVなのでどういう意味のデータかは想像する必要がありました。間違ってたらごめんね!
- 「分析編」の通り、当月以外の口座連携データが含まれています。なぜ…。
- transactionsは、aaDataに対応する明細データ。
- こちらはaaDataのコアデータの一つの項目がキーとなっており、突合できるようになっています。
- 深部まで潜っていくと、こちらは連想配列になっています。なぜこっちはCSV…。
- aaDataはレシートデータと口座連携データ。
- javascriptで複数項目でソートできるの初めて知った。気持ちいい!
- CSV出力の部分、ごり押しです。ごめんね!
実践編はこちら↓です。ブラウザ上で動作します。
以上!







ディスカッション
コメント一覧
まだ、コメントがありません