• #総勘定元帳
  • #Miller Columns
  • #会計
  • #Vue.js
  • #プロトタイプ
開発tax-assistantメモ

総勘定元帳ビューア - 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['金額']
})

動作確認

画面遷移

  1. 勘定科目一覧(B/S順 → P/L順)
  2. 「売掛金」選択 → 取引パターン一覧
  3. 「/ 技術売上高」選択 → 仕訳一覧(マトリックス形式)

キーボード操作

  • ↓キーで勘定科目を順番に選択
  • →キーで取引パターン列に移動
  • ↓キーでパターン選択
  • →キーで仕訳一覧に移動

全ての操作がキーボードのみで完結できることを確認。

今後の課題

  • 仕訳詳細のポップアップ表示
  • 期間フィルター機能
  • CSVエクスポート機能
  • 残高推移グラフ

学んだこと

Miller Columns UIの利点

会計データのような階層構造を持つデータは、Miller Columns UIと相性が良い。勘定科目→取引パターン→仕訳という自然な思考フローでデータを探索できる。

複合仕訳の表示方法

複合仕訳を扱う場合、単純なグルーピングでは関連が見えにくくなる。マトリックス形式にすることで、同一日付の取引を横並びで確認できるようになった。

キーボードファーストの設計

会計データの確認作業は大量のデータを素早く確認する必要がある。マウス操作よりもキーボードで完結できる設計が重要。