会計ソフトの仕訳データから年次推移表を自動生成する
朝、会計ソフトAのスプレッドシートに並ぶ仕訳データを眺めていた。このデータからBS+PLの年次推移表を毎回手で組むのをやめたい。gen-annual-tableスクリプトを書き始めたところから、気づけばExcel版とGoogle Sheets版の二系統が動くようになるまで丸一日が過ぎた。
gen-annual-table: Excel版の開発
BS+PLの構造設計
年次推移表の構造を固めるのに時間をかけた。ヘッダー行の下に個別科目が並び、小計・合計・チェック行が続く。2022年度から2028年度まで7年分を横に展開する。
合計行の数式で最初につまずいた。科目のpruning(ゼロ行の非表示化)を入れると、行番号がずれて SUM(B10:B25) のような固定範囲指定が壊れる。sum_named 方式に切り替えて、名前付き範囲で集計対象を指定するようにした。pruning後もインデックスが正しく動く。
PLの経常利益・税引前利益は単純なSUMでは出せない。営業利益に営業外損益を加減する計算式を pl_calc として定義し、合計行から参照する形にした。
チェック行で不整合を検知する
BSの末尾にチェック行を置いた。「資産合計 - 負債純資産合計 = 0」を数式で計算し、ゼロ以外の値が出たらセルが赤く光る。このチェック行のおかげで、後工程で科目の配置を変えたときに即座にずれを検知できた。
入力データをExcel内に同梱する
生成したExcelに「入力_MF仕訳」シートを追加し、元データをそのまま貼り付けた。インプットとアウトプットが1ファイルで完結するので、後から「この数字はどこから来たか」を追うときにファイルを行き来しなくて済む。
Google Sheets版の新規開発
共通コアモジュールの切り出し
Excel版が動いた後、同じロジックをGoogle Sheetsにも出したくなった。最初はExcel版のスクリプトをコピーして書き換え始めたが、科目構造の定義やpruningロジックが丸ごと重複していることに手が止まった。
gen_annual_table_core.py として共通データモジュールを切り出すリファクタリングを実行した。BS・PLの科目構造、合計行の数式定義、pruningロジックをここに集約する。Excel版 (gen_annual_table.py) とSS版 (gen_annual_table_ss.py) は、このコアモジュールを import して、出力先だけを差し替える構造にした。
リファクタリング後、Excel版の出力結果が変わっていないことを確認してからSS版の開発に入った。
SS版: Google Sheets APIでの書き込み
SS版では gws CLI経由でGoogle Sheets APIを叩く。シート作成、セル書き込み、IB書式適用の3ステップを1つのシェルスクリプト gen_annual_table_ss.sh にまとめた。
命名規則は CF_年次推移表_{ソースSS名} とした。--title オプションで明示的にタイトルを指定できるが、未指定時はソーススプレッドシートのタイトルを自動取得して埋め込む。Google Sheetsにはバージョン履歴があるため、Excel版と違ってファイル名にタイムスタンプを入れる必要がない。
Excel版とSS版の値照合
両方の出力が揃った時点で、全セルの値を突き合わせた。Pythonスクリプトで Excel の各セル値と Google Sheets の各セル値を比較し、差分があれば報告する仕組みを組んだ。最初の照合で数箇所の不一致が見つかり、SS版の数式変換ロジックにバグがあったことが判明した。修正後、全セル一致を確認。
勘定科目マスターのJSON化
年次推移表の科目名をハードコードしていると、科目が増えたときに複数箇所を修正する必要が出る。会計ソフトAの勘定科目マスター(223件)をスプレッドシートから読み取り、scripts/cf-materials/mf-account-master.json に書き出した。
{
"accounts": [
{
"code": "110",
"name": "現金",
"category": "asset",
"parent": null
},
{
"code": "110-001",
"name": "小口現金",
"category": "asset",
"parent": "110"
}
]
}
親子関係(勘定科目と補助科目)を parent フィールドで保持している。このJSONをコアモジュールから参照すれば、科目の追加・変更がJSON1箇所の編集で済む。
返済予定表の合計行バグ修正
年次推移表を眺めていて、支払利息の数字に違和感を覚えた。返済予定表の合計と突き合わせたところ、3,750円の差がある。
原因を追うと、TPL_返済予定表の合計行 =SUM(E20:E501) がRow 19を含んでいなかった。Row 19は初回返済時の据置期間利息3,750円が入っている行だ。=SUM(E19:E501) に修正し、D・E・F列すべてで開始行を揃えた。利息合計が156,188円から159,938円に変わり、返済予定表の個別行合計と一致した。
3,750円のずれは合計額に対して小さいが、チェック行がなければ気づかなかった。
書式の仕上げ
数値の見た目を整える作業にも手を入れた。
- 数値カラムの列幅を18.125に統一し、スペーサー列は1.5に絞った
- 全セルに上下中央揃え(vertical center)を適用
- チェック行のA列を右寄せにして、ラベルと数値の視線が揃うようにした
- 一部のセルで数値が
stringValueとして格納されていたのをnumberValue/formulaValueに修正。文字列のままだとSUM関数が無視するため、これも照合時に発覚した
振り返り
一日で一番時間を使ったのは、共通コアモジュールの切り出しだった。Excel版が動いている状態でリファクタリングするのは勇気が要る。しかし、コピペで2つ目を作り始めた瞬間に「これは後で必ず片方だけ修正して不整合が出る」と手が止まった。結果的に、リファクタリングしてからSS版を作ったことで、照合時のバグ修正がコアモジュール1箇所の修正で両方に反映された。
返済予定表のバグは、年次推移表の数字を睨んでいて偶然見つけた。合計行のSUM範囲が1行ずれているだけで3,750円の差が出る。金額が小さいから放置してもよさそうだが、帳簿の信頼性は「全部合っている」前提で成り立つ。1円でもずれていたら他の数字も疑わなければならない。チェック行を入れておいてよかった。