総勘定元帳ビューア - Miller Columnsで仕訳を直感的に閲覧
今日はtax-assistantプロジェクトで、MoneyForwardの仕訳データを閲覧するための総勘定元帳ビューアを開発した。既存のcf-viewer(キャッシュフロービューア)で採用しているMiller Columns UIを流用し、会計データを直感的にドリルダウンできるインターフェースを構築した。
開発の背景
課題
MoneyForwardから出力した仕訳帳CSVは、そのままだと見づらい。特に以下の点が問題だった。
- 勘定科目ごとの取引を一覧で確認しづらい
- 相手勘定でグルーピングして取引パターンを把握したい
- 複合仕訳の内訳が分かりにくい
解決策
cf-viewerで実績のあるMiller Columns UIを採用。3カラム構成で階層的にデータを表示する。
勘定科目 → 取引パターン(相手勘定) → 仕訳一覧
実装内容
ディレクトリ構成
apps/ledger-viewer/
├── data/
│ ├── 仕訳帳.csv # MoneyForwardエクスポート(UTF-8変換済み)
│ ├── bs-master.csv # 貸借対照表勘定科目マスター
│ └── pl-master.csv # 損益計算書勘定科目マスター
├── index.html # メインHTML + Vue.js
└── README.md # 要件定義・設計ドキュメント
データ処理の流れ
1. Shift-JIS → UTF-8 変換
MoneyForwardから出力されるCSVはShift-JIS。UTF-8に変換して読み込む。
# 文字コード変換
iconv -f SHIFT-JIS -t UTF-8 仕訳帳_original.csv > 仕訳帳.csv
2. 勘定科目のソート(B/S → P/L順)
マスターファイルの順序に従い、B/S科目を先に、P/L科目を後に表示。
// マスターから順序を取得
const bsAccounts = bsMaster.map(row => row['勘定科目'])
const plAccounts = plMaster.map(row => row['勘定科目'])
// 仕訳データに存在する科目のみ、マスター順でソート
const sortedAccounts = [...bsAccounts, ...plAccounts]
.filter(acc => existingAccounts.has(acc))
3. 取引パターンの抽出
同一勘定科目の取引を「相手勘定」でグルーピング。複合仕訳の場合は取引Noで紐づけて相手科目を特定。
// 取引Noでグループ化して相手勘定を特定
const transactionGroups = groupBy(entries, '取引No')
entries.forEach(entry => {
const counterEntries = transactionGroups[entry['取引No']]
.filter(e => e !== entry)
entry.counterAccount = counterEntries.map(e => e['勘定科目']).join(', ')
})
UI実装
Miller Columns レイアウト
cf-viewerのCSS設計を流用し、3カラムのMiller Columns UIを実装。
.miller-columns {
display: flex;
height: calc(100vh - 100px);
gap: 2px;
background: #e0e0e0;
}
.miller-column {
flex: 1;
min-width: 300px;
max-width: 400px;
background: white;
overflow-y: auto;
}
キーボードナビゲーション
矢印キーで全ての操作ができるよう実装。
| キー | 動作 |
|---|---|
| ↑↓ | 同一カラム内でアイテム選択 |
| ←→ | カラム間移動 |
| Enter | 選択確定(次カラムへ移動) |
document.addEventListener('keydown', (e) => {
switch(e.key) {
case 'ArrowDown':
selectNext(currentColumn)
break
case 'ArrowUp':
selectPrev(currentColumn)
break
case 'ArrowRight':
moveToNextColumn()
break
case 'ArrowLeft':
moveToPrevColumn()
break
}
})
マトリックス表示(改善版)
当初は取引パターンで補助科目をグルーピングしていたが、複合仕訳の場合に見づらいことが判明。仕訳一覧をマトリックス形式に変更した。
問題点
同じ日付の複合仕訳で複数の補助科目(例: 売掛金のPaypay, メタップスペイメント)を使う場合、補助科目でグルーピングすると関連が分かりにくい。
解決策
縦軸を日付、横軸を補助科目にしたマトリックス形式で表示。
日付 | Paypay | メタップス | 合計
-----------|---------|-----------|------
2025-01-15 | 10,000 | 5,000 | 15,000
2025-01-20 | 8,000 | 12,000 | 20,000
// 日付×補助科目のマトリックスを構築
const matrix = {}
entries.forEach(entry => {
const date = entry['日付']
const subAccount = entry['補助科目'] || '(なし)'
if (!matrix[date]) matrix[date] = {}
matrix[date][subAccount] = (matrix[date][subAccount] || 0) + entry['金額']
})
動作確認
画面遷移
- 勘定科目一覧(B/S順 → P/L順)
- 「売掛金」選択 → 取引パターン一覧
- 「/ 技術売上高」選択 → 仕訳一覧(マトリックス形式)
キーボード操作
- ↓キーで勘定科目を順番に選択
- →キーで取引パターン列に移動
- ↓キーでパターン選択
- →キーで仕訳一覧に移動
全ての操作がキーボードのみで完結できることを確認。
今後の課題
- 仕訳詳細のポップアップ表示
- 期間フィルター機能
- CSVエクスポート機能
- 残高推移グラフ
学んだこと
Miller Columns UIの利点
会計データのような階層構造を持つデータは、Miller Columns UIと相性が良い。勘定科目→取引パターン→仕訳という自然な思考フローでデータを探索できる。
複合仕訳の表示方法
複合仕訳を扱う場合、単純なグルーピングでは関連が見えにくくなる。マトリックス形式にすることで、同一日付の取引を横並びで確認できるようになった。
キーボードファーストの設計
会計データの確認作業は大量のデータを素早く確認する必要がある。マウス操作よりもキーボードで完結できる設計が重要。