開発未分類アクティブ
キャッシュフロー精算表ビューアをVue.jsで実装した開発記録
ExcelのキャッシュフローCF精算表をWebアプリケーションとして再現するプロジェクトの開発記録。仕訳データからCF精算表を自動生成し、計算チェックまで行う仕組みを構築した。
背景と目的
Excelで管理していたキャッシュフロー精算表をWebアプリに移植することで、以下を実現したかった。
- 仕訳データの編集がリアルタイムで精算表に反映される
- 計算チェック(各行の合計=0)の自動検証
- 複数の事例を切り替えて表示できるUI
使用したExcelファイル
2つのExcelファイルを使い分けた。
| ファイル | 用途 |
|---|---|
| キャッシュフロー仕訳のコンテンツ案_仮説検証用_20240418_1200.xlsx | コンテンツ用の仕訳データソース |
| GS連結CS_202309-4Q_20240325_0900.xlsx | 計算ロジック・Excel数式の参照用 |
コンテンツ用のExcelにはQ3-2などの事例別シートがあり、各シートに仕訳データが格納されている。計算ロジック参照用のExcelからは、現金及び預金の振替列やバランスチェックの数式を参考にした。
実装した機能
1. キャッシュフロー精算表の表示
精算表の列構成は以下の通り。
| 列 | 内容 |
|---|---|
| 勘定科目 | B/S科目名 |
| 期首残高 | 前期末の残高 |
| 期末残高 | 当期末の残高 |
| 増減 | 期末 - 期首 |
| CF調整項目 | 税引前当期純利益、棚卸資産の増減、仕入債務の増減など |
| 現金及び預金の振替 | 現預金の増減を相殺する調整 |
| チェック | 各行の合計が0になるかの検証 |
2. 期首残高・期末残高・増減の計算
Q3-2の事例では期首残高を全てゼロとし、前提仕訳「現金及び預金 10,000 / 資本金 10,000」を当期の取引として扱った。
// 仕訳から各勘定科目の増減を計算
const accountBalances = {};
journals.forEach(journal => {
journal.entries.forEach(entry => {
const account = entry.account;
const amount = entry.debit || -entry.credit;
accountBalances[account] = (accountBalances[account] || 0) + amount;
});
});
3. 現金及び預金の振替ロジック
Excelの計算式を参考に、現金及び預金の行だけに振替額を入れ、他のB/S科目の振替は0とした。
// 現金及び預金の振替 = 他のB/S科目の振替合計の逆符号
const cashTransfer = -otherBSTransferTotal;
cashRow.cashTransfer = cashTransfer;
cashRow.rowTotal = cashRow.change + cashRow.cfAdjustment + cashTransfer;
4. 計算チェックの実装
各行の合計(増減 + CF調整 + 現金振替)が0になるかをチェックする。
// 行ごとの計算チェック
const rowTotal = change + cfAdjustment + cashTransfer;
const isValid = Math.abs(rowTotal) < 0.01; // 浮動小数点誤差を考慮
チェック結果の表示は以下のようにした。
- 合計が0の場合: 緑色のチェックマーク
- 合計が0でない場合: 赤色で差額を表示
5. CF計算書への転記
Excelの数式 =IF(AG$3=$D96,AG$86*-1,0) を参考に、精算表の列合計を-1倍してCF計算書に転記するロジックを実装した。
// CF計算書用にcfColumnTotalsを-1倍
const cfStatementItems = cfColumns.map(col => ({
name: col,
total: -cfColumnTotals[col] // 精算表の合計を-1倍
}));
6. 貸借一致チェック
ヘッダー行の「期首残高」「期末残高」「増減」に貸借一致のチェックマークを表示。
// 貸借一致チェック
const beginningDiff = assetsBegin - (liabilitiesBegin + equityBegin);
const endingDiff = assetsEnd - (liabilitiesEnd + equityEnd);
const changeDiff = assetsChange - (liabilitiesChange + equityChange);
// 一致していればチェックマーク、不一致なら差額を表示
テストコードの作成
Vitestを使用してテストコードを作成した。
テスト仕様
// test/cashflow.test.js
describe('キャッシュフロー精算表', () => {
test('各行の合計が0になること', () => {
// 増減 + CF調整 + 現金振替 = 0
});
test('CF計算書の差異が0になること', () => {
// 現金振替合計 - CF計算書の増減 = 0
});
test('期首・期末・増減の貸借が一致すること', () => {
// 資産 = 負債 + 純資産
});
test('仕訳から残高を正しく計算できること', () => {
// 借方合計 = 貸方合計
});
});
テスト実行結果
$ pnpm test
✓ test 1: 資産科目の増減計算
✓ test 2: 負債科目の増減計算
✓ test 3: CF精算表の計算チェック
✓ test 4: CF計算書への転記
✓ test 5: 貸借一致チェック
✓ test 6: 期首・期末・増減の貸借一致
✓ test 7: 仕訳から残高を計算
全7テスト合格
ファイル分離リファクタリング
当初は1つのindex.htmlに全てのコードを記述していたが、保守性向上のためファイルを分離した。
分離前
cashflow-viewer/
├── index.html (HTML + CSS + JS 全て含む)
└── data.json
分離後
cashflow-viewer/
├── index.html (HTMLテンプレートのみ)
├── styles.css (スタイル定義)
├── app.js (Vueアプリケーションロジック)
├── data.json (仕訳データ)
└── test/
└── cashflow.test.js
削除した未使用コード
リファクタリング時に以下の未使用コードを削除した。
beginningBS関連のロジック(前期末B/Sセクションを削除したため)groupedBeginningBSとcategoryLabel.bs-table関連のCSSクラス- 仕訳の参照番号表記(
<*1>など)
仕訳編集とリアルタイム反映
仕訳の金額を編集すると、精算表が自動的に再計算されるようにした。
実装のポイント
triggerRefを使用してVueのリアクティビティを手動でトリガー- サマリーデータではなく仕訳データから直接残高を計算
- P/L科目の残高を利益剰余金として集計
// 仕訳編集時の処理
function finishEdit(entry, field) {
// 値を更新
entry[field] = newValue;
// リアクティビティをトリガー
triggerRef(data);
}
Chrome DevToolsでの動作確認
Chrome DevTools MCPを使用して、仕訳の金額を12,000に変更した際の動作を確認した。
- 仕訳の金額が12,000に更新された
- 精算表の現金及び預金が13,800に変更された
- 貸借一致チェックが緑色のチェックマークで表示された
UIの改善
レスポンシブ対応
- PC幅: 仕訳パネルと精算表パネルを横並び表示
- 狭い画面(900px以下): タブ切り替えUIで「仕訳」と「精算表」を切り替え
財務諸表セクション
CF計算書の下に以下を追加した。
- 損益計算書(P/L): 売上高から当期純利益までの段階損益
- 貸借対照表(B/S): 借方(資産)と貸方(負債・純資産)の2列表示
- 株主資本等変動計算書(S/S): 資本金と利益剰余金の変動
スタイリング
- 数字のフォントをメイリオに統一
- 合計行の背景を薄いグレーに設定
- 外枠を削除してすっきりした見た目に
- カンマ区切りの数字入力に対応
今後の予定
- 他の事例(Q6-9など)への対応
- 共通コンポーネントの切り出し
- 依存関係を減らすリファクタリング
- コンテンツ用Excelの全事例をWebに表示
学んだこと
- Excelの計算式をそのままコードに落とし込むと理解しやすい
- 計算チェックをテストコードにすることで、ロジック変更時の検証が楽になる
- Vueのリアクティビティは深いネストで動作しないことがあるので
triggerRefが必要 - フロントエンド先行で作ると、不要なロジックを早期に発見できる