CSVと管理表の合計が合わない。1円まで割り振れたのに、決まらないものが残った

合計の差を追いかける。差額の突合 を示す図解つきのアイキャッチ。 比べる・突き合わせる

販売管理システムから出したCSVを、Excelの売上管理表に取り込んでいる。月次集計を見たら、CSVの合計と合わない。271,663.93円足りない。

この状態から「いくら・何で合わないのか」を出すところまでを、実際にやってみました。AIには3回頼んでいます。

3回とも、271,663.93円を1円も余さず原因別に割り振りました。金額も行数も、こちらが用意した正解と全部一致しています。素朴に「原因を調べてください」と1行で頼んだ回も含めてです。

違いが出たのは、計算ではありませんでした。3回の差は3か所で、そのうち2つは書き方の細かさ(どの行が該当するのかを、どこまで並べたか)です。残る1つが「ここから先は決まらない」と書いたかどうかで、効いていたのはこれでした。素朴に頼んだ回の報告には、「判定できない」「決められない」にあたる言葉が1回も出てきません。かわりに「修正後のあるべき値」が確定値の表で出てきました。

作業は、AIにPythonのスクリプトを書かせて実行し、CSVとExcelファイルを読み比べる形で進めました。実行環境は Windows 11 です。

金額の計算が出てくるので、丸めの扱いを先に書いておきます。原因別の金額は、CSVに入っている小数第2位までの値をそのまま使いました。管理表との行ごとの比較では、必要な箇所だけ円単位に四捨五入しています。あとで出てくる丸めの0.51円は、27行の差を符号つきで合計した正味の額です。

使うファイル

架空の販売データを用意しました。2ファイルです。

中身 合計
取込元CSV 180件(注文番号の重複なし) 7,016,757.93円
売上管理表(取込後) 178行(注文番号のユニークは173 6,745,094円

管理表には「月次集計」シートもあって、担当課別の合計が並んでいます。

担当課 件数 金額合計
営業1課 77 3,380,957
営業2課 48 1,621,119
営業3課 53 1,743,018
合計 178 6,745,094

始める前に「どうなれば終わったことにするか」を別ファイルに書きました。1回も実行する前にです。あとから書くと、出てきた結果に条件を合わせてしまいます。

「271,663円足りない」だけでは、手の付けようがない

この時点で分かっているのは2つだけです。

  • 金額が 271,663.93円 足りない
  • 件数が 180 対 178 で合わない

分からないのはこちらです。

  • どの行が原因なのか
  • 原因は1つなのか、複数が重なっているのか
  • 271,663.93円のうち、いくらがどの原因なのか
  • 直せるものと、直せないものがあるのか

金額の差だけ分かっても、どこから手を付けるかは決まりません。「271,663円ぶんの何か」を探すことになって、結局は目視で全行を眺めることになります。

そこで、こう頼みました。「いくら」「何で」合わないのかを出してください。そのうえで、分解した金額の合計が実測の差額と一致すること、一致しない分は「説明できない残り」として金額を明示すること、「その他」「誤差」に流さないことを条件に入れました。

差を原因別に割り振ると、残りが0になる

返ってきたのがこれです。

原因 金額 行数
金額列が文字列でSUMから外れた 237,902.00 6
取込漏れ(連続したブロック) 211,965.06 7
二重貼り付け −201,688 5
一部の行だけ 1.1 で割られている 23,484.36 18
円未満の丸め 0.51 27
合計 271,663.93 63
説明できない残り 0.00

足すと実測の差額に1円もずれずに一致します。残っていない、ということが確かめられる形になっています。

行数の欄だけ、足すと63になります。2行が2つの原因を同時に持っているためです(二重貼り付けされた行のうち2行で、丸めも起きていた)。触られている行は実際には 61行、残る 119行は無傷です。金額のほうは重複して数えていません(重複行は「余分に足された1行ぶん」だけを計上しています)。

119行が無傷、という点が効きます。全部が壊れているわけではないので、一括で直すという手が使えません。どの行がどの原因なのかを持っていないと、直しようがない。

どうやって原因を切り分けたか

5つとも、何が起きているかは数値のルールで拾えます。ただし「1.1で割った処理が正しかったのか」だけは、このファイルからは判断できません。

原因 判定のしかた
取込漏れ 注文番号がCSVにあって管理表に無い
二重貼り付け 同じ注文番号が管理表に2回以上ある
文字列 金額のセルが数値型でない
丸め 差が1円未満で、CSVの値を四捨五入すると一致する
1.1で割られている CSVの値を1.1で割って四捨五入すると一致する

ここで大事なのは、どのルールにも当てはまらない差が出たら、それを「説明できない残り」として残すことです。無理にどれかへ寄せると、分解が閉じたように見えて中身が壊れます。

抜け方・入り方に癖がある

取込漏れの7件は、ばらばらではありませんでした。CSVの42〜48行目という、連続したひとかたまりです。計上日でいうと6月8日から10日。日付や得意先で切れているのではなく、貼り付ける範囲がずれた形です。

二重貼り付けの5行も固まっていました。管理表の152〜156行に連続して並んでいて、この5行だけ計上日の昇順が崩れています(前後は6月27日・28日なのに、この5行は6月上旬)。あとから別のかたまりを足した痕跡です。

文字列になっていた6件は、こうでした。

要再請求   123,310円ぶん
確認中      70,800円ぶん
-          26,400円ぶん
未定         8,880円ぶん
—            6,512円ぶん
0(保留)    2,000円ぶん

入力した人は、業務上の保留をそのまま書き込んだのだと思います。件数としては178行に数えられているのに、金額は0として合計されます。Excelは何も言いません。件数だけを見ていると、この6件は見つかりません。

割り振って初めて見えることが2つある

合計を眺めていたときには見えていなかったものが出てきます。

表面の差額より、狂っている金額のほうが大きい

表面の差額 271,663.93
原因の絶対値合計 675,039.93(2.48倍)
触られている行 180行のうち61行

管理表の金額への影響で見ると、取込漏れは −211,965.06円、二重貼り付けは +201,688円逆方向に効いて、ほとんど打ち消し合っています。(さきほどの分解表とは符号の基準が逆です。表は「CSVから見た差」、ここは「管理表の金額をいくら動かしたか」で書いています。)

合計だけ見ていると、21万円の取りこぼしと20万円の二重計上が、1万円のズレに見えます。もしこの2つの金額がぴったり同じだったら、差額は0になって、そもそも誰も調べません。

丸めは、金額で並べるか行数で並べるかで順位が変わる

円未満の丸めは 27行で起きています。原因別の行数では2番目に多い。ところが金額への寄与は 0.51円で、5つの原因の中で最下位です。

四捨五入なので、切り上げと切り捨てが混ざって打ち消し合うためです。今回のように大きな差額の主因を金額順で探すなら、丸めの優先度は低いという結果でした。ただし、データによっては丸めの差が大きく積み上がることもあります。

逆に「何行を直すことになるのか」を見るなら、27行は無視できない数です。丸めは行数そのものを変えないので、180対178という件数の差とは別の話になります。

同じ表を、金額順で見るか行数順で見るかで、原因の順位が入れ替わります。

今回は、素朴に1行で頼んだ回も同じ数字を出した

3回のうち1回目は、条件を付けずにこう頼みました。

販売管理システムから出したCSVを、Excelの売上管理表に取り込んでいます。
月次の集計金額がCSVの合計と合いません。原因を調べてください。

2回目と3回目には、さきほどの条件(分解する・残差を明示する・注文番号を列挙する・判定できないものは判定できないと書く)を6項目にして渡しました。2回目と3回目は完全に同じ文です。毎回同じ答えになるかを見るためです。

結果はこうでした。

1回目(素朴) 2回目 3回目
差額 271,663.93 一致 一致 一致
原因別の金額(5つ) 一致 一致 一致
残差 0 の明記 あり あり あり
欠落・重複・文字列の注文番号 全件 全件 全件

ここで確認できたのは、この1つの素材に対する計3回ぶんだけです。別の素材では試していません。手当てした6項目のどれが効いたのかも、1つずつ変えて比べたわけではないので分けられません。「情報を見せる/見せない」のような別の軸も試していません。

1回目の指示文には、分解も残差もスクリプトも書いていません。それでも1回目は Python を4本書いて実行し、その中に残差を出す行を自分で入れていました。

print("=> 計算値         ", calc)
print("Excel実測合計     ", xl_total)
print("残差              ", calc - xl_total)

ここまでは、頼み方の差が出ませんでした。

3か所の差のうち、効いていたのは1つ

3回の報告を突き合わせると、差は3か所でした。

1回目(素朴) 2回目・3回目
管理表の注文番号のユニーク数 書いていない 書いた
1.1で割られた18行の注文番号 1件も無し 全18件
「判定できない」の記述 0回 各6項目

上の2つは、書き込みの細かさです。1回目は「18行が1.1で割られている」と正しく数えていますが、どの18行なのかを書いていません。これでは読む側が確かめようがない。

3つ目が、いちばん効いていました。1回目の報告本文は2,903文字あります。そこに「判定できない」「判定不可」「判定不能」「断定」「決められない」「不明」「分からない」が、1つも出てきません。全部0回です。

かわりに、こう結論していました。

なお CSV側は正常です。全180行で 数量×単価×(1-値引率)=金額 が一致、注文番号の重複なし、日付昇順。金額以外の列(数量・担当課・得意先名・商品名・計上日)の不一致も0件でした。問題はすべて取込作業側にあります。

そのうえで「修正後のあるべき値」という表を作り、正しい合計は 7,016,757.93円だと確定値で出しています。

3回目は、同じ数字に到達したうえで、こう書きました。

正しい月次売上 → 参考値としてCSV合計7,016,757.93円。ただし③の確定額と円未満の処理ルールが決まらないと確定しません。

同じ 7,016,757.93 という数字を出したうえで、片方は「正しい値」として出し、片方は「参考値」として止めています。

計算はどちらも合っています。違うのは、ここから先は決まらない、という一行があるかどうかです。

そしてこの一行は、指示文に「判定できないものは判定できないと書く」と入れた回にしか出てきませんでした。分解も残差も頼まなくても出てきたのに、これだけは頼んだ回にしか出てこなかった。

ただし、これは今回の3回で起きたことです。素朴に頼んだのは1回だけで、手当てした指示は6項目をまとめて足しています。「頼まなければ必ず出ない」とも、「この1項目が効いた」とも、この実行からは言えません。

決められないものは、本当に決められない

5つの原因のうち、4つは直し方が決まります。取込漏れは入れ直す、二重貼り付けは消す、丸めはルールを決めて揃える。文字列になっている6件は、確定額を業務側で決める必要がありますが、何をすればいいかははっきりしています。

残る1つ、「一部の行だけ 1.1 で割られている」18行が決まりません。

18行すべてで、管理表の金額がCSVの金額を1.1で割って四捨五入した値になっています。消費税の税抜換算に見えます。ですが、それが正しかったのかどうかは、このファイルからは決まりません。

④の「÷1.1」が税抜処理かどうか → 判定不可。CSVに税区分・税率の列がなく、管理表にも処理内容の記録列がない。数値関係は確認できても意図の根拠がファイル内に存在しません。

2回目は、商品コードごとに扱いが揃っていないかを調べたうえで否定しています。

÷1.1 が適用された商品コードは 9種類あるが、そのすべてが「÷1.1されていない行」にも出現する(同じ商品が行によって扱いが違う)。商品マスタの税区分では説明できない。

ここでいう商品マスタは、商品コードごとに同じ処理になっているかを調べたという意味です。税区分を記録した別のファイルがあったわけではありません。使ったのは、はじめに挙げた2ファイルだけです。

「単価が1.1で割り切れるなら税込だろう」という当て方も試せます。やってみると当たりません。

ここで当たり外れを数えられるのは、これが検証用に作った架空データで、仕込んだ税区分の正解をこちら側が別に持っているからです。実際の業務ファイルには、この答え合わせの相手がいません。

適合率(税込と判定したうち、本当に税込だった割合) 31.5%
再現率(本当に税込の行のうち、拾えた割合) 44.4%

外し方が両側に出ます。1.1で割り切れるのに実際は税抜だった行も、割り切れないのに実際は税込だった行も、どちらもたくさんあります。単価を眺めても決まりません。

「18行が1.1で割られている」は事実として確定できます。「その18行を戻すべきか」は決まりません。この2つは別のことで、突き合わせは前者までしかできません。

3回とも手を付けなかった前提がある

実は、このCSVの単価には税込のものと税抜のものが混ざっています。180行のうち63行、金額にして426,840.97円(CSV合計の6.1%)です。

3回とも、これは指摘されませんでした。

これは失敗ではありません。判定する材料がファイルの中に無いように作ってあります。税区分の列はどこにもなく、さきほどの当て方も31.5%しか当たりません。分からないものは分かりません。

ただ、結果としてこうなりました。3回とも「CSVの合計が正しい売上である」という前提には手を付けていません。差を1円まで説明しきったうえで、その1円まで合った数字が何なのかは、確かめられていない。

3回目も、単価に税込と税抜が混ざっていることを見抜いたわけではありません。3回目が確定を避けた理由は、文字列になっている6件の金額と、円未満の処理ルールが決まっていないことでした。税の混在とは別の理由です。

ただ、結果として「参考値」と書いたぶんだけ、あとから前提を疑う余地が残りました。確定値で書いてしまうと、疑う場所がなくなります。

差を全部説明できることと、その合計が何なのかを言えることは、別です。

実行した側も、自分のことは間違える

突き合わせの数字は正確でした。間違えたのは、別のところです。

2回目は、自分が作ったExcelブックの説明を間違えました。「原因別6シート」と書いていますが、開いて数えると原因別は5枚(ブック全体で9枚)でした。該当0件の分類は、シート自体を作っていなかったのです。

本人に数え直させたところ、突き合わせの数値は66項目中65項目が正しく、間違っていたのは「自分が何を作ったか」の1行だけでした。6項目の指示は突き合わせの中身についてのもので、生成物の説明は範囲外だったわけです。

もう1つは、1回目と3回目が同じ間違いをしました。どちらも「CSVは180行すべてで 金額 = 数量 × 単価 × (1−値引率) が成立している」と書いています。

小数第2位に丸めた場合 180 / 180 成立
厳密に一致するか 175 / 180

ずれた5行の差は、符号を付けて足して +0.007円。金額としては何の影響もありません。3回目が自分で申告し、こちらでも計算し直しました。

ただ、丸めを27行も見つけている作業の中で、自分の検算に入っている丸めは書かなかったということです。他人のデータの丸めは数えるのに、自分の一致判定に丸めを挟んでいることは書かない。

この記事を書いている側も、同じことをしました。1回目の応答を記録するファイルに、「本人に照合させて相違が無いことを確認している」と注記を書きました。その時点で、照合はまだ依頼すらしていません。あとで本人に指摘されて直しました。

これから確かめる予定のことを、もう終わったこととして書く。文章としては自然に流れるので、書いている最中には気づきません。「決められないと書かなかった」のとは逆向きですが、書く時点と確かめる時点がずれているという点では同じです。

出てきた答えを、自分で確かめる

報告を読んで「それらしい」と思ったら、そこで止めずに5つ確かめます。どれもExcelの検索と電卓でできます。

  • 原因別の金額を足す。差額と一致しなければ、その報告はどこかで止まっている
  • 取込漏れと言われた注文番号を、管理表で検索する。本当に無いか
  • 二重と言われた注文番号を、管理表で検索する。本当に2回あるか
  • 文字列だと言われたセルを見る。標準の配置なら、数値は右寄せ・文字列は左寄せになる。書式で配置を変えている表なら ISNUMBER 関数で確かめる
  • 「判定できない」と書かれた項目を、元のファイルで探す。その情報が本当にどこにも無いかを、自分の目で確かめる

1つ目がいちばん強いです。足し算が合わない報告は、原因を全部は出していません。そして足し算は、読む側でもすぐにできます。

5つ目も要ります。「判定できない」と書いてあるからといって、本当に判定できないとは限りません。今回は税区分の列がCSVにも管理表にも無いことを、こちらで見て確かめました。

自分でやるときの頼み方

今回の記録から、自分で試すときに入れておきたい確認点が3つあります。3つを個別に有無で比べたわけではないので、それぞれの効果を測ったものではありません。

1. 「説明できない残り」を必ず書かせる

「原因を調べて」ではなく、「原因別に分解して、合計が差額と一致することを示して。一致しない分は説明できない残りとして金額を書いて」と頼みます。「その他」「誤差」に流させないと明記します。

残りが0にならなくても構いません。0にならなかったことが分かるほうが大事です。

2. 「判定できないものは判定できないと書く」を入れる

これが今回、いちばん差が出たところです。理由も書かせます。「データに無い情報を推測で埋めないこと」まで書いておくと、根拠のない断定への歯止めになります。今回は、この条件を入れた2回で、判定できない理由まで書かれました。

3. 生成物は、報告を読まずに開いて数える

「シートを6枚作りました」と書いてあっても、開いて数えます。突き合わせの数字が正確でも、自分の出力についての記述は別に間違えます。

この方法が使えないとき

今回のやり方には前提があります。

  • 両側に共通のキーが要ります。今回は注文番号でした。キーが無い表どうしは、行を対応づける段階で人の判断が入ります
  • 取り込む前のファイルが残っている必要があります。上書きしてしまっていると、比べる相手がいません
  • 原因の種類は、データから決まるものに限られます。「なぜ7行が抜けたのか」「なぜ18行だけ割られたのか」は、ファイルの中に記録が無ければ分かりません

3つ目が今回いちばん効きました。分かるのは「何が起きたか」までで、「なぜ起きたか」は出てきません。

送る前に確認すること

売上明細には、得意先名と金額が並びます。社外のサービスへファイルを渡す前に、社内の取り扱いルールを確認してください。

この記事で使ったのは架空のデータです。得意先名は「得意先A社」、担当者は「U-01」のようなコードにしてあります。

渡さずに済ませる手もあります。今回の突き合わせは注文番号・金額・数量・単価があれば成立します。得意先名や商品名を伏せ字にしても、原因別の分解はそのままできます。

使ったのは Claude Opus 5(Claude Code のサブエージェント機能)です。他のサービス・他のモデルで同じ結果になることは保証できません。3回とも別々のセッションで実行し、前の回の内容は引き継いでいません。

まとめ

合計が合わないとき、欲しいのは差額ではなく差額の内訳です。271,663.93円を5つの原因に割り振ると、残りが0になりました。今回は、素朴に1行で頼んだ回でも、ここまでは出てきました。

そして割り振ってみると、合計を見ていたときには分からなかったことが出てきます。実際に狂っている金額は表面の差額の2.48倍あり27行で起きている丸めは合計に0.51円しか効いていない。

ただ、そこまでやってもこの2ファイルだけでは、18行の税区分も、割った金額を戻すべきかも決まりません。そして今回、決まらないと書いてあったのは、そう頼んだ回だけでした。

計算は合っていました。欠けていたのは「ここから先は決まらない」という一行でした。

合っている答えと、答えになっていない部分。今回は、前者は頼まなくても出てきて、後者は頼んだ回にだけ出てきました。

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