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出力の部分、ごり押しです。ごめんね!
実践編はこちら↓です。ブラウザ上で動作します。
以上!
ディスカッション
コメント一覧
まだ、コメントがありません