電話番号の表記がバラバラな名簿を直す。Excelの数式とAIで何が違ったか

Excel管理表で電話番号の形式が混在する原因と、半角数字とハイフンで統一する方法 のアイキャッチ画像 そろえる・変換する

受け取った顧客名簿の電話番号列が、見事にバラバラだった。03-3100-6125 もあれば 03-3100-5509 もあり、0331007999 と区切りが無いものも、(03)3100-5630 と括弧付きのものも混ざっている。発信するときにコピーできず、検索しても引っかからない。

これをそろえるのに、AIに投げるべきか、Excelの関数で片づけるべきか。両方を実際にやって比べました。

結果を先に書くと、Excelの数式で98.2%、AIで100%。正解が決まる164行で見ると、Excelが161行、AIが164行。採点上の差は3行です。これとは別に、正解を決められない桁不足の2行でも扱いが分かれました。違いが出たのは合わせて5行だけです。精度ではほとんど差がつきません。代わりに、はっきり違うところがありました。何を間違えるか、そしてどうすれば気づけるかです。

使うファイル

架空の顧客連絡先を用意しました。180行・6列(顧客ID・顧客名・都道府県・電話番号・登録日・備考)、12,072バイト。電話番号列は全180セルを文字列として持たせてあり、先頭の0は落ちていません。

電話番号列の中身はこうなっています。

書き方 件数
既に正しい 052-200-1494 61
全角数字 052-200-4711 15
全角ハイフン 0166-28-7926 10
中黒区切り 03・3100・4662 9
スペース区切り 06 4100 3577 9
括弧付き (06)4100-2942 9
前後に空白 ␣␣06-4100-7458␣ 8
区切りなし 0641001882 20
携帯・IP電話・フリーダイヤル 070-5004-4593 20
内線併記 052-200-7410 内線638 6
複数番号併記 03-3100-3817 / 070-5004-2860 4
国際表記 +81-3-3100-9140 3
桁が足りない 03-3100-34 2
FAX混入 FAX 0166-28-8571 2
電話番号でない 不明 / 担当者携帯へ 2
180

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

数えてみると、規則だけで答えが決まるのが164行、決まらないのが16行でした。この164と16が、以下ずっと出てきます。

まずExcelの数式だけでやってみる

AIを使わずに、どこまで行けるかを先に見ます。全角を半角にして、区切り記号をハイフンにそろえて、前後の空白を落とす。数式1本で書けます。

=SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(
   ASC(TRIM(D2)),"・","-"),"・","-"),"(",""),")","-")," ","-")

113文字です。これで全角・中黒・スペース・括弧・前後空白の60行が片づきました。164行のうち141行が正解と一致、86.0%です。

残ったのは23行。そのうち20行が「区切りなし」でした。ここが難所です。

0331007999   → 03-3100-7999     市外局番2桁
0641001882   → 06-4100-1882     市外局番2桁
0522009730   → 052-200-9730     市外局番3桁
0166289227   → 0166-28-9227     市外局番4桁

4つとも、ちょうど10桁です。市外局番が2桁の地域も3桁の地域も4桁の地域もあり、合計はどれも10桁になります。つまり桁数を数えても、どこで切るかは決まりません。0641001882 を機械的に3桁で切ると 064-100-1882 になりますが、そんな市外局番はありません。

これは規則では書けない、AIの出番だろう。そう思って試したら、外れました。

=IFERROR(IF(LEFT(I2,4)="0120","0120",
  IF(OR(LEFT(I2,3)="070",LEFT(I2,3)="050"),LEFT(I2,3),
  IF(LEFT(I2,4)="0166","0166",IF(LEFT(I2,3)="052","052",
  IF(OR(LEFT(I2,2)="03",LEFT(I2,2)="06"),LEFT(I2,2),""))))),"")

市外局番の一覧を、IFを重ねた条件分岐の式で持たせただけの204文字です。これを足したら、区切りなしの20行が全部正しく切れました。164行中161行が一致、98.2%です。

必要だったのは知能ではありませんでした。市外局番の一覧という、データです。補助列は6本、数式は全部で624文字、再計算は20ミリ秒で終わります。

2行が黙って壊れていた

98.2%まで来たので、残り3行を見ようとして、別のものを見つけました。

元:   03-3100-34      ← 数字が8桁しかない
数式: 03-31-0034      ← 電話番号らしい形に整形された

03-3100-34 は入力ミスで、8桁しかありません。数式は「市外局番+真ん中+末尾4桁」で機械的に切るので、8桁を 03-31-0034 という別の形にしてしまいました。

エラーは出ません。警告も出ません。セルの色も変わりません。並べ替えて眺めても、これだけ目に留まる理由がありません。電話番号の形をしているからです。

同じことが2行で起きていました。98.2%という数字の裏側に、「間違いだと分からない間違い」が2件入っていたわけです。

チェックの列を1本足す

直す側の数式に手を入れるのではなく、できあがりを疑う列を別に作ります。電話番号の桁数は種別ごとに決まっているので、それと合っているかを見るだけです。

=IF(K2="","NG:市外局番が判定できない",
  IF(K2="0120",IF(J2=10,"OK","NG:桁数"&J2),
  IF(OR(K2="070",K2="050"),IF(J2=11,"OK","NG:桁数"&J2),
  IF(J2=10,"OK","NG:桁数"&J2))))

145文字です。固定電話は10桁、携帯と050で始まるIP電話は11桁、0120で始まる番号は10桁。今回のファイルに出てくる4種類だけを見ています。それだけの判定です。結果はこうなりました。

NGの理由 件数 中身
市外局番が判定できない 7 国際表記3・FAX混入2・電話番号でない2
桁数15 6 内線併記
桁数22 4 複数番号併記
桁数8 2 黙って化けていた2行
19

弾かれた19行は、人が見るべき19行と過不足なく一致しました。正解データと突き合わせて確認しています。

桁数を数えるだけでは足りない点にも触れておきます。03310079990166289227 はどちらも10桁で、桁数チェックはどちらも通します。市外局番の照合と組み合わせて、初めて見逃しがゼロになりました。

AIに渡すとどうなるか

同じファイルを、今度はAIに渡しました。まずは何も考えずに1行だけです。

添付のExcelファイルの「電話番号」列の書き方がバラバラです。統一してください。

市外局番の桁数のことも、何件あるかも伝えていません。それでも164行すべてが正解と一致しました。100%です。区切りなしの20行も、数式が弾いた国際表記3行も、正しく直っています。

桁が足りない2行については、こう報告してきました。

桁を推測して補完することは一切していません。 03-3100-34 03-3100-67 の2件は数字が8桁しかなく、正しい番号を復元する手段がありません。もっともらしく埋めると「一見きれいだが間違った番号」になるので、空欄にして要確認へ回しました。ここは自動処理してはいけない箇所だと判断しています。

数式が黙って 03-31-0034 に化けさせた2行を、そのまま空欄にして報告してきたわけです。

もうひとつ、想定していなかったことがありました。頼んでいないのに、修復用のPythonスクリプト(同じ処理を次回も実行するためのプログラム)が付いてきました。素朴な1行しか渡していないのに、256行です。

この記事を書くにあたって「AIにファイルを渡す」と「AIにスクリプトを書かせる」を別の手段として比べるつもりでした。その区別は成り立ちませんでした。

ただし正確に書いておきます。3回ともスクリプトは出てきましたが、2回目と3回目は、指示文の最後に「次回も同じことができる形で残してください」と自分で頼んでいます。頼まずに出てきたのは1回目の256行だけです。それでも、素朴な1行しか渡していない回で付いてきた以上、今回の3回では、渡すことと書かせることを分けて比べられませんでした。

3回試した

1回目は上の素朴な1行。2回目と3回目は、扱い方を細かく指定した同じ指示文を使いました。3回とも、前の回のことを知らない状態で実行しています。

1回目 2回目 3回目(2回目と同じ指示)
正解164行の一致 164 164 164
決まらない16行を保留 4 16 16
決まらない16行を独断で処理 12 0 0
数字を作り出した件数 0 0 0
指示していない列の書き換え 備考16行 なし なし
出力ファイル数 2 10 7
スクリプトの行数 256 611 627
所要時間 約4分41秒 約7分43秒 約7分33秒

2回目と3回目は、電話番号列の180セルが1文字も違いませんでした。同じ指示文で、別のセッションで、完全に同じ結果です。

ただし成果物の形は違います。2回目は10ファイル・スクリプト611行、3回目は7ファイル・627行。保留した16行の説明の切り方も違いました。中身は同じで、報告の形が違う、という差です。

違いが出たのは1回目でした。決まらない12行を、独断で処理して先へ進めています。

元の値 1回目 2回目・3回目
052-200-7410 内線638 電話番号は 052-200-7410、備考へ 内線638 そのまま
03-3100-3817 / 070-5004-2860 電話番号は 03-3100-3817、備考へ第2連絡先 そのまま
FAX 0166-28-8571 電話番号は 0166-28-8571、備考へ注記 そのまま

これは捏造ではありません。数字は1件も作っていません。出てきた数字が元の値の一部であることを機械で確かめました。変更内容を書いた列も、原文を残した列も付いています。あとから戻せます。

それでも、頼んでいない備考列が16行書き換わりました。指示文に「決まらないものは推測で埋めない」「電話番号列以外を変更しない」と書いた2回目・3回目では、これが起きていません。

精度ではなく、間違え方が違う

並べます。

Excelの数式 AI
正解164行の一致 161(98.2% 164(100%
区切りなし20行 20 20
国際表記3行 0(要確認で弾いた) 3
桁が足りない2行 黙って形を整えた 推測せず保留した(1回目は空欄、2・3回目は原文のまま)
所要 20ミリ秒 4分41秒〜7分43秒
手間 補助列6本・数式624文字 指示1行、または10項目
残るもの 数式 スクリプト256〜627行

正解が決まる164行での差は3行。国際表記の3行だけです。これとは別に、正解を決められない桁不足の2行でも扱いが分かれました。この2行は採点の対象外なので、164行には入っていません。違いが出たのは合わせて5行。この差で「AIのほうが優れている」とも「Excelで十分」とも言いにくい。

違いがはっきり出たのは間違え方でした。

今回作った数式は、直せないものを黙って形だけ整えました。8桁の値を電話番号の形にして、何も言わずに次の行へ進みます。今回のAIは、直せないものを直せないと言いました。3回とも、桁が足りない2行を推測で埋めていません。

逆向きの話もあります。素朴に投げた1回目は、決まらない12行を勝手に決めました。備考列にも書き込んでいます。数式は、そんなことはしません。書いた通りにしか動かないからです。

どちらも、放っておくと違う形でずれます。そして両方とも、こちらが確かめれば見つかりました。数式のほうはチェック列1本で19行全部が挙がり、AIのほうは3回とも自分で「要確認」を出してきました。

今回の1題材だけの結果ですが、選ぶときの目安としてはこうなります。

  • 速さと透明さがほしいなら数式。今回は20ミリ秒で終わり、式を見れば何をしたか分かった。ただし検算の列は自分で足すことになる
  • 検証まで込みで受け取りたいならAI。今回は決まらない行を理由つきで別表に出し、次回用のスクリプトも残った。ただし数分かかり、頼まなければ余計なことをした回もある

どちらを選んでも、確かめる作業は残ります。そこは省けませんでした。

使った指示文

2回目・3回目に使った指示文の全文です。ファイルを添付して、そのまま貼ってください。

添付のExcelファイル(顧客連絡先.xlsx)の「電話番号」列の書き方がバラバラです。
半角数字とハイフンの形に統一してください。

【まず確認してほしいこと】
1. 電話番号列に、どんな書き方が何件ずつ混ざっているかを示してください。
2. 全部で何件あるかを示してください。

【直し方の条件】
3. 固定電話は「市外局番-市内局番-加入者番号」の形にしてください。
   市外局番の桁数は地域によって違います。
4. 携帯・IP電話・フリーダイヤルも、それぞれの区切り方に揃えてください。
5. 元から正しく書かれている行は、内容を変えないでください。
6. 区切り位置や値が一通りに決まらない行は、推測で埋めずにそのまま残し、
   別表で一覧にしてください。(どの行が、なぜ決まらないのか)
7. 電話番号列以外の列は変更しないでください。元のファイルも変更しないでください。

【最後に必ず報告してほしいこと】
8. 書き出したファイルを読み直して、行数と、統一できた件数
9. 元から正しかった行が、処理後も変わっていないか
10. 直した手順を、次回も同じことができる形(スクリプト)で残してください

素朴な1行でも164行すべて正解でした。この指示文で変わったのは精度ではありません。効いたのは6と7、つまり「決まらないものを勝手に決めない」「他の列を触らない」という振る舞いのほうです。

検証する側にも間違いは入る

3回目のAIが、自分で書いた検証スクリプトのバグを自分で見つけて報告してきました。

検証中に見つけた自分のバグを1点報告します。最初の verify_output.py は「数字の増減」判定に \D を使っていましたが、Python の \d は全角数字 0-9 にもマッチするため、全角行15件が「数字が変わった」と誤検出されました。NFKC で半角化してから比較するよう修正し、再実行して0件になっています。検証器が正しく作られていなければ検証は無意味なので、この修正込みで結果を報告します。

やさしく言い直すと、全角の「123」と半角の「123」を、同じ数字として比べられていなかったという話です。そのせいで、変わっていない行まで「変わった」と報告されていました。

この記事を書くために採点していた側も、まったく同じ間違いをしました。1回目の採点で「176件中148件しか数字が一致しない」と出て、原因は同じところでした。半角にそろえてから比べたら163件です。

同じ落とし穴に、独立した2者が別々に落ちて、別々に気づいたことになります。

ここから言えることは1つです。チェックの結果がおかしいときは、データを疑う前にチェックする側を疑ってください。「19行がNG」と出たとき、その19行が本当にNGなのかは、別の見方でもう一度確かめないと分かりません。

ここから先は人が見る

16行は、どちらの手段でも決まりませんでした。

種類 件数 決まらない理由
内線併記 6 内線を消すか、別の列へ移すか
複数番号併記 4 どちらを主番号とするか
FAX混入 2 電話番号列に残してよいか
桁が足りない 2 元の伝票を見るしかない
電話番号でない 2 空欄にしてよいか分からない

2回目のAIは、この16行についてこう書いてきました。

保留による実害はありません:内線・FAX・複数併記の12行は、番号部分自体がすでに正しい形(0166-28-8571 など)でした。つまり「触らない」判断をしても書式上は何も失っていません。(以下略)

これは押さえておく価値があります。決まらない16行のうち12行は、そもそも書式としては壊れていません。残っているのは書き方の問題ではなく、業務としてどう扱うかの問題です。

内線を別列に切り出すのか。複数番号のどちらを代表とするのか。FAXを電話番号として扱うのか。ここは表を見ても決まりません。運用を知っている人が決めることです。

この方法が使えないとき

条件 理由
市外局番の種類が多い 今回は4種類だったのでIFを重ねた式で足りました。全国の市外局番を数式に書くのは現実的ではありません。別表を作り、そこから市外局番を探す関数(VLOOKUP)を使う形になります
桁が足りない・多い値がある 元の伝票や画面を見るしかありません。補うと創作になります
1セルに複数の番号が入っている どちらを主にするかはデータからは決まりません
毎回まったく同じ結果がほしい 今回は同じ指示の2回が完全に一致しましたが、これは1つの題材での結果です。別のファイルで同じになる保証はありません
行数が非常に多い 今回試したのは180行です。どこまでの規模が通るかは試していません
そもそも入力時に決めるほうが早い 下記

最後の点を補足します。入力する時点で形式を決めておけば、この作業そのものが要りません。入力規則で全角を弾く、入力欄を市外局番・市内局番・加入者番号に分ける、といった手当てが本筋です。

ただし、すでに手元にある名簿は、それでは直りません。今回のように受け取った側で片づける場面は残ります。入口を直すのと、いま手元にあるものを直すのは、別の作業です。

送る前に確認すること

顧客名簿は、社外に出せない情報のかたまりです。AIサービスにファイルを送るのは、社外にデータを出すことです。勤務先によっては規定で禁止されています。試す前に、自分の職場のルールを確認してください。

電話番号は、それ自体が個人を特定できる情報です。氏名や住所を伏せても、番号が残っていれば意味がありません。

「では架空のデータで試そう」と考えたときに、思ったより厄介だと分かった話を書いておきます。

この記事のサンプルは、総務省が公表している「電気通信番号指定状況」を実際にダウンロードして、事業者に割り当てられていない番号帯だけを選んで作りました。適当な数字を並べると、誰かの実在の番号になりかねないからです。

調べてみると、こうなっていました。基準日はデータごとに違います。

番号帯 全ブロック 事業者に割り当てられていない データの基準日
090 900 0 2024年9月1日
080 900 0 2024年9月1日
070 900 46 2026年7月1日
050 9,000 6,576 2026年6月1日
0120 1,000 8 2024年6月1日

090と080には、空きが1つもありません。900ブロックすべてが事業者に割り当て済みです。つまり公表データの上で「どの事業者にも割り当てられていない」と言える携帯番号を、090や080から選ぶことはできません。この記事のサンプルで携帯番号に070を使ったのは、そのためです。

固定電話のほうは、市外局番と市内局番の組み合わせごとに「使用中」「未使用」が公表されています。サンプルにはその「未使用」だけを使いました。

ここで押さえておきたいのは、どれも「その基準日の時点で」割り当てが無いという意味だということです。とくに固定電話の一覧は2024年3月1日時点のもので、いちばん古い。以後に割り当てられた可能性は否定できません。公表されている中でいちばん新しいデータを使っても、そこから先は確かめようがありません。

なお、「市内局番は0や1で始まらない」という説明をいくつか見かけましたが、総務省の資料でその規則自体を明示した記載は見つけられませんでした。今回使った4つの市外局番については、公表データに0や1で始まる市内局番が1件も載っていないことだけ確認しています。

ダミーデータを作る手間は小さくありません。それでも、本物を社外に出すよりは軽い手間です。

まとめ

電話番号の表記がバラバラな180行を、Excelの数式とAIの両方で直しました。数式で98.2%、AIで100%。正解が決まる164行での差は3行、これに採点対象外の桁不足2行の扱いを足して、違いが出たのは5行でした。

市外局番の桁数が地域で変わる問題は、規則では書けないだろうと思っていました。これは外れました。市外局番の一覧を、IFを重ねた条件分岐で持たせるだけで、区切りなしの20行は全部正しく切れます。必要だったのは知能ではなく、データでした。

精度で差がつかなかったぶん、間違え方の違いが残りました。数式は直せないものを黙って形だけ整え、素朴に投げたAIは決まらないものを勝手に決めました。どちらも、確かめれば見つかります。

確かめる手は、この題材では2つで足りました。ハイフンを除いた桁数を見る。先頭が既知の市外局番かを見る。この2つを組み合わせた145文字の列が、人が見るべき19行を過不足なく挙げました。

そのチェック自体も間違えることがあります。全角数字を半角と区別せずに比べて、誤検出を出しました。AIも、この記事を書いた側も、同じところで転びました。

なお今回使ったのは Claude(Opus 5)です。他のAIサービスで同じ結果になる保証はありません。同じ指示の2回が完全に一致したのも、この題材でそうだったというだけです。

速い手を選ぶか、説明つきの手を選ぶかは、その日の都合で決めていいと思います。どちらを選んでも、できあがりを疑う列だけは自分で用意してください。そこは省けませんでした。

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