資金繰り予測を自動化しても、最後は残高照合が要る|完了した月で予測と実績を突き合わせる

資金繰り予測を自動化しても、最後は残高照合が要る|完了した月で予測と実績を突き合わせる 経理・数字の自動化

資金繰り表も、月末の着地予想も、Pythonで自動化しました。毎月決まった時間に動いて、Slackに表が届きます。それでも、その表の数字が正しいかどうかは、表自体では確かめられません。

結論を先に書きます。自動化できるのは「増減の計算」までで、起点になる実際の残高だけは人が入れるしかありません。そして計算そのものが壊れていないかは、すでに終わった月で「予測=実績」になるかを見るのがいちばん確実です。実際うちは、この検算で1件、静かに間違っていた集計を見つけました。

私は清掃業を経営していて、プログラマーではありません。この記事は、うちのMacで実際に動いている資金繰りと着地予想のスクリプトを読み返して書いています。金額は社外に出せないので、数字そのものではなく、確かめ方だけを書きます。


自動計算は「差」しか作れない

うちの資金繰り表は、12か月ぶんの月末残高を並べます。中身はこれだけです。

bal = 期首現金残高
for 月 in 予定期間:
    bal += その月の収支
    print(bal)

見てのとおり、スクリプトが計算しているのは「増えるか減るか」だけです。売上も経費も税金も、全部エクセルから読んで積み上げられます。けれど 期首現金残高 だけは、どこにも書いていません。それは銀行の通帳にしか存在しないからです。

正直に書きます。うちの前提ファイルは、今もここが 0 のままです。

# 2026年8月1日時点の現預金残高(全口座合計)。
# 0のままだと資金繰り表の残高欄が意味を持たない。
期首現金残高 = 0

0のまま動かすと何が起きるか。表はちゃんと出ます。月ごとの残高が12個並び、「資金繰りの底はこの月です」という警告まで出ます。ぱっと見、完成しています。

でもその「残高」は、ゼロから数えた増減の累計であって、口座にいくらあるかではありません。手元に十分な現金があれば底は問題になりませんし、逆に薄ければ表が示すより早く行き詰まります。数字の形は正しいのに、意味だけが空っぽという状態です。

だからこの表には、残高の行のすぐ下に 「★ 期首現金残高に実額を入力すること」 と印字させています。埋まっていないことを、表を見た人が必ず目にする場所に出す。入力し忘れを防ぐのではなく、忘れたまま信じてしまうのを防ぐためです。

ここは自動化できません。銀行の残高をスクリプトから取ってくる仕組みをうちは持っていませんし、持っていたとしても、月初に一度は人が通帳と突き合わせるべき場所だと思っています。資金繰り表が当たっているかどうかは、最終的に「口座にいくらあるか」でしか答え合わせできないからです。


完了した月なら、予測は実績と一致するはず

もうひとつの自動化が、月末の着地予想です。計算はこれだけです。

着地予想 = 累計 ÷ 経過日数 × その月の日数

ここに、ただで手に入る検算が隠れています。

すでに終わった月を指定すると、経過日数とその月の日数が同じになります。つまり掛け算と割り算が打ち消し合って、予測値は定義上ぴったり実績と一致します。予測の精度の問題ではありません。一致しなかったら、それは予測が外れたのではなく、集計が壊れているということです。

うちでは、正解の数字を経理のルールを書いたファイルに残してあります。

## 検算のしかた(結論を出す前に必ず)

完了した月で「着地予想 = 実績」になるか確かめる。

  6月の正解値: 売上 ●,●●●,●●● / 利益 ●,●●●,●●●

`predict.py 6` がこの値と一致しなければ、ロジックが壊れている。

これを書いておく意味は大きいです。正解が手元に無いと、出てきた数字がおかしいかどうか誰にも判断できません。「なんとなく去年よりいい気がする」で通ってしまいます。一度きちんと数えた月を1つ、動かない正解として持っておく。これだけで、以後すべての計算に合否がつきます。

ずれ方でだいたい原因も見当がつきます。

完了月なのに起きること たいていの原因
予測が実績より小さい 読めていないデータがある(シート名が違う等)
予測が実績より大きい 経過日数を少なく数えている(休業日を除いた等)
ぴったり合わない端数が出る 月末の数日が未入力のまま日割りされている

実際に見つかった間違い:全角の「7月」

この検算で、2026年8月に1件見つかりました。エラーは一度も出ていませんでした。

うちの利益表は、拠点ごと・月ごとにシートが分かれています。スクリプトは 7月○○ という名前のシートを探しに行きます。ところが実際のシート名には、人が手で作った揺れが混ざっていました。

  • 末尾に半角スペースが付いているもの(8月下呂 )
  • 月の数字が全角のもの(7月沼津)

当時のスクリプトは空白しか吸収していませんでした。全角の「7」は半角の「7」と別物なので一致せず、その月の2拠点が丸ごと集計から抜け落ちました。

怖いのは、抜けても表は普通に出ることです。残りの拠点で合計が作られ、桁も並びも自然で、赤い文字も出ません。実績と突き合わせて初めて「小さすぎる」と分かりました。手で数えた正解を持っていなければ、そのまま通っていたと思います。

直し方は1行

照合する前に、全角を半角にそろえます。Pythonの標準機能でできます。

import unicodedata

def soroeru(s):
    """シート名を突き合わせ用にそろえる(全角数字→半角、空白を除去)"""
    return unicodedata.normalize("NFKC", s).replace(" ", "").replace(" ", "")

NFKC は「全角の英数字や記号を半角の姿にそろえる」という指定です。これを通してから比べるだけで、7月沼津 も 7月沼津 も同じものとして扱えます。

まず、自分のシート名を目で見る

直す前に、手元のファイルが実際どうなっているか見てください。そのまま貼って動きます(このMacは /usr/bin/python3 が動かないので、venvのPythonを使っています)。

cd ~/作業フォルダ && ~/scripts/keiri/.venv/bin/python - <<'EOF'
import openpyxl, unicodedata
wb = openpyxl.load_workbook("利益表.xlsx", read_only=True)
for s in wb.sheetnames:
    seiki = unicodedata.normalize("NFKC", s).replace(" ", "").replace(" ", "")
    印 = "  ← 揺れあり" if s != seiki else ""
    print(repr(s), 印)
EOF

repr() で表示しているのがポイントです。ふつうに表示すると、末尾のスペースも全角の数字も見た目でほぼ分かりません。repr() ならクォートで囲まれて、スペースがどこまであるかがはっきり見えます。


「見つからなかった」は、合計の隣に出す

実は当時のスクリプトも、シートが見つからないときに「○○: シート未作成」という注意書きは出していました。それでも気づけませんでした。理由は置き場所です。

  • 注意書きは、長い表のいちばん最後に並ぶ
  • Mac通知に出るのは、レポートから「合計」の行だけを抜き出したもの

つまり、合計は毎回目に入り、注意書きは一度も目に入らない構造でした。書いてあることと、届いていることは別です。

ここから学んだのはひとつです。欠けの警告は、数字と同じ場所に出さないと意味がありません。レポートの末尾に小さく書くのではなく、合計行そのものに印を付けるか、いっそ欠けがあるなら合計を出さないほうが安全です。人は必ず合計しか見ないからです。


帳簿が2つあると、どちらかは間違っている

もうひとつ、突き合わせて初めて分かったことがあります。

うちには数字の出どころが2つあります。日々の作業を日次で入力する表と、請求書ベースの売上帳です。ある拠点について、この2つを月ごとに並べてみました。

結果、日次の表のほうが、毎月4割前後少なかったのです。しかも金額がぶれているのではなく、4か月とも同じくらいの割合で少ない。ランダムな入力ミスなら、こうはなりません。

調べると、その拠点だけ請求項目がいくつか日次の表に入っていませんでした。入力ミスではなく、そもそも表の設計に入っていなかったわけです。片方だけを自動化して眺めていたら、たぶん一生気づきませんでした。

同じ会社の同じ月の売上が、2つの帳簿で違う。これは異常ではなく、むしろ普通に起きます。大事なのは、違うことを知らないまま片方で判断しないことです。

この差が分かってから、その拠点の利益率を他と並べて評価するのをやめました。数字が間違っていると知っていれば、間違ったまま使わずに済みます。いちばん危ないのは、間違っていることを知らないことのほうです。


明日やるなら、この順番で

  1. 資金繰り表の期首残高の欄を開く。実際の口座残高が入っているか、0のままか確かめる
  2. すでに終わった月を1つ選び、自動計算の結果と、手で数えた実績を並べる
  3. その月の正解値を、ルールを書いたファイルに文字で残す。次からはこれが合否の基準になる
  4. 「データが見つからない」ときの注意書きが、通知や要約にちゃんと載るか確かめる。載っていなければ合計行に印を付ける
  5. 別の帳簿が手元にあるなら、1か月ぶんだけ突き合わせてみる

2と3は、慣れれば30分で終わります。いちばん効くのは3番です。正解を書き残していないと、次に誰かが計算式を「改善」したとき、それが良くなったのか壊れたのか誰にも判定できません。


まとめ

  • 自動計算が作れるのは増減だけ。起点になる実際の残高は、人が銀行から入れるしかない
  • 期首残高が0のままでも表は完成した顔で出る。形が正しくて意味が空っぽな数字がいちばん危ない
  • 未入力の欄があるなら、数字のすぐ隣に「未入力」と印字させる
  • 完了した月では、日割りの予測は定義上ぴったり実績と一致する。これがただで手に入る検算になる
  • 一致しないのは予測が外れたのではなく、集計が壊れているということ
  • 正解の数字を1か月ぶん、文字で書き残す。正解が無ければ、おかしいかどうか誰にも判断できない
  • シート名の照合は全角と半角、末尾のスペースを必ずそろえてから。合わないと、その分が黙って合計から消える
  • 欠けの警告は合計と同じ場所に出す。末尾に書いても人は読まない
  • 帳簿が2つあるなら1か月ぶん突き合わせる。割合が毎月同じくらいずれていたら、それは設計の抜け

そもそも資金繰り表をどう組み立てるか、前提の数字をどこに置くかは 資金繰り予測をPythonで自動化する|コードと設計の考え方 に書いています。これから作るなら、検算の手順を最初から一緒に組み込んでおいてください。後から足すと、どこまでが正しかったのか分からなくなります。

コメント

タイトルとURLをコピーしました