はじめに
前に、VBA×生成AIの記事を初級・中級・上級と3回連続でアップしました。
ここでは同じようにPython×生成AIの記事を初級・中級・上級と3回連続でアップしていきます。
======
Excelのデータを整理していて、こんな経験はありませんか?
- 「株式会社ABC」と「(株)ABC」と「ABC株式会社」が混在している
- 「東京都港区」と「東京都 港区」で半角スペースが入っていたりいなかったり
- 「田中太郎」と「田中 太郎」で氏名の区切りがバラバラ
これらの表記ゆれは、VLOOKUP やピボットテーブルが正しく動かない原因になります。手作業で直すのは大変ですし、VBA で対応しようとしても「どのパターンに統一するか」のルール作りが膨大になりがちです。
この記事では、Python と OpenAI API(GPT) を使って、生成AIに表記ゆれの判断と修正を任せるツールを作ります。
この記事のシリーズ
| レベル | 内容 |
|---|---|
| 初級(本記事) | Python + OpenAI API で Excel の表記ゆれを自動修正 |
| 中級(次回) | Coming Soon |
| 上級(次々回) | Coming Soon |
対象読者
- Excel の表記ゆれに悩んだことがある方
- Python をこれから学びたい方・始めたばかりの方
- VBA でデータクレンジングをしていたが限界を感じている方
完成イメージ
こんな表記ゆれだらけの Excel ファイルが…
| No | 会社名 | 住所 |
|---|---|---|
| 1 | 株式会社ABC | 東京都港区赤坂1-1-1 |
| 2 | (株)ABC | 東京都 港区 赤坂1-1-1 |
| 3 | ABC株式会社 | 東京都港区赤坂1−1−1 |
| 4 | 株式会社エービーシー | 東京都港区赤坂1丁目1番1号 |
↓ 生成AIが自動で統一!
| No | 会社名 | 住所 |
|---|---|---|
| 1 | 株式会社ABC | 東京都港区赤坂1-1-1 |
| 2 | 株式会社ABC | 東京都港区赤坂1-1-1 |
| 3 | 株式会社ABC | 東京都港区赤坂1-1-1 |
| 4 | 株式会社ABC | 東京都港区赤坂1丁目1番1号 |
注意: 「赤坂1丁目1番1号」と「赤坂1-1-1」のように意味は同じでも表記形式が異なるケースは、生成AIでも完全な統一が難しい場合があります。プロンプトの調整次第で改善可能ですので、4章のカスタマイズも参考にしてください。
1. 環境構築
1-1. 必要なもの
| 項目 | 説明 |
|---|---|
| Python | 3.9 以上 |
| OpenAI API キー | OpenAI Platform で取得 |
| テキストエディタ | VS Code 推奨 |
1-2. ライブラリのインストール
pip install openai python-dotenv openpyxl
| ライブラリ | 用途 |
|---|---|
openai |
OpenAI API を Python から呼び出す |
python-dotenv |
API キーを安全に管理する |
openpyxl |
Excel ファイル(.xlsx)の読み書き |
1-3. プロジェクトフォルダの作成
まず、作業用のフォルダを作ります。エディタのターミナルを開いてください(メニューの「ターミナル」→「新しいターミナル」、またはショートカット Ctrl + `)。
ターミナルに以下を入力して Enter を押します。
mkdir excel-cleansing
cd excel-cleansing
すると、excel-cleansingフォルダに移動します。
1-4. API キーの設定
-
エディタの左側エクスプローラーで「新しいファイル」アイコンをクリック
-
ctrl + S で保存
OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
sk-xxxxxxxx... の部分は、自分の API キーに置き換えてください。
API キーは OpenAI Platform の API keys ページ で発行できます。
1-5. サンプルデータの準備
動作確認用の Excel ファイルを Python スクリプトで作成します。
手順1: エディタの左側エクスプローラーで「新しいファイル」アイコンをクリックし、create_sample.py というファイル名で作成します。
手順2: 以下のコードをそのままコピーして貼り付け、保存します。
import openpyxl
wb = openpyxl.Workbook()
ws = wb.active
ws.title = "顧客リスト"
# ヘッダー
ws.append(["No", "会社名", "住所", "電話番号"])
# 表記ゆれを含むサンプルデータ
data = [
[1, "株式会社ABC", "東京都港区赤坂1-1-1", "03-1234-5678"],
[2, "(株)ABC", "東京都 港区 赤坂1-1-1", "03(1234)5678"],
[3, "ABC株式会社", "東京都港区赤坂1−1−1", "03−1234−5678"],
[4, "株式会社エービーシー", "東京都港区赤坂1丁目1番1号", "03-1234-5678"],
[5, "株式会社 ABC", "東京都港区赤坂 1-1-1", "03 1234 5678"],
[6, "株式会社XYZ", "大阪府大阪市北区梅田2-2", "06-9876-5432"],
[7, "(株)XYZ", "大阪府大阪市北区梅田2-2", "06(9876)5432"],
[8, "XYZ株式会社", "大阪府大阪市 北区 梅田2-2", "06−9876−5432"],
]
for row in data:
ws.append(row)
# 列幅の調整
ws.column_dimensions["A"].width = 5
ws.column_dimensions["B"].width = 25
ws.column_dimensions["C"].width = 30
ws.column_dimensions["D"].width = 20
wb.save("sample_data.xlsx")
print("sample_data.xlsx を作成しました")
python create_sample.py
sample_data.xlsx を作成しました と表示されれば成功です。
excel-cleansing フォルダ内に Excel ファイルが生成されています。

この時点で、フォルダの中身は以下のようになっています。
2. 表記ゆれ修正スクリプトを作ろう
2-1. 全体のコード
エディタの左側エクスプローラーで「新しいファイル」アイコンをクリックし、excel_cleansing.py というファイル名で作成します。
注意:excel-cleansingフォルダ内に作成すること。
次に、この新しいexcel_cleansing.pyファイルに以下のコードをそのままコピーして貼り付け、保存してください。
import os
import json
from openai import OpenAI
from dotenv import load_dotenv
import openpyxl
# .envファイルからAPIキーを読み込む
load_dotenv()
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
def normalize_column(values: list[str], column_name: str) -> list[str]:
"""
生成AIを使って列データの表記ゆれを修正する関数
Args:
values: 修正対象の値リスト
column_name: 列名(会社名、住所など)
Returns:
修正後の値リスト
"""
prompt = f"""
以下は「{column_name}」列のデータ一覧です。
表記ゆれを検出し、統一されたデータに修正してください。
【修正ルール】
- 同じ意味のデータは最も一般的・正式な表記に統一してください
- 会社名の場合: 「株式会社」は前につける形に統一(例: 株式会社ABC)
- 住所の場合: 余分なスペースを除去し、数字は半角に統一してください
- 電話番号の場合: 「03-1234-5678」の形式(半角ハイフン区切り)に統一してください
- 全角英数字は半角に変換してください
- 元のデータの意味や内容は変えないでください
【入力データ】
{json.dumps(values, ensure_ascii=False)}
【出力形式】
修正後のデータをJSON配列で返してください。
入力と同じ要素数・同じ順序で返してください。
JSON配列のみを返し、それ以外のテキストは含めないでください。
"""
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{
"role": "system",
"content": "あなたはデータクレンジングの専門家です。指示に従ってJSON配列のみを返してください。"
},
{"role": "user", "content": prompt}
],
temperature=0.0 # 表記統一なので創造性は不要
)
result_text = response.choices[0].message.content.strip()
# JSON文字列の前後にマークダウンのコードブロックがついている場合に除去する
if result_text.startswith("```"):
result_text = result_text.split("\n", 1)[1] # 最初の行を除去
if result_text.endswith("```"):
result_text = result_text.rsplit("\n", 1)[0] # 最後の行を除去
result = json.loads(result_text)
return result
def cleanse_excel(input_file: str, output_file: str, target_columns: list[str]):
"""
Excelファイルの指定列の表記ゆれを修正する関数
Args:
input_file: 入力Excelファイルのパス
output_file: 出力Excelファイルのパス
target_columns: 修正対象の列名リスト
"""
wb = openpyxl.load_workbook(input_file)
ws = wb.active
# ヘッダー行から列名とインデックスの対応を取得
headers = {}
for col_idx, cell in enumerate(ws[1], start=1):
headers[cell.value] = col_idx
# 対象列ごとに処理
for column_name in target_columns:
if column_name not in headers:
print(f"警告: 「{column_name}」列が見つかりません。スキップします。")
continue
col_idx = headers[column_name]
# 列のデータを取得(ヘッダー行を除く)
values = []
for row in ws.iter_rows(min_row=2, min_col=col_idx, max_col=col_idx):
cell = row[0]
values.append(str(cell.value) if cell.value is not None else "")
if not values:
continue
print(f"「{column_name}」列を修正中...({len(values)}件)")
# 生成AIで表記ゆれを修正
normalized = normalize_column(values, column_name)
# 修正結果をExcelに書き戻す
for i, row in enumerate(ws.iter_rows(min_row=2, min_col=col_idx, max_col=col_idx)):
cell = row[0]
old_value = str(cell.value) if cell.value is not None else ""
new_value = normalized[i]
if old_value != new_value:
print(f" 修正: {old_value} -> {new_value}")
cell.value = new_value
wb.save(output_file)
print(f"\n{output_file} に保存しました")
def main():
"""メイン処理"""
print("=" * 50)
print("Excel 表記ゆれ自動修正ツール")
print("=" * 50)
# 設定
input_file = "sample_data.xlsx"
output_file = "sample_data_cleaned.xlsx"
target_columns = ["会社名", "住所", "電話番号"]
# ファイルの存在確認
if not os.path.exists(input_file):
print(f"エラー: {input_file} が見つかりません。")
print("先に create_sample.py を実行してサンプルデータを作成してください。")
return
print(f"\n入力ファイル: {input_file}")
print(f"出力ファイル: {output_file}")
print(f"対象列: {', '.join(target_columns)}")
print()
# 表記ゆれ修正を実行
cleanse_excel(input_file, output_file, target_columns)
print("\n完了しました")
if __name__ == "__main__":
main()
3. 実行してみよう
インプット
インプットデータは、先ほどコードを使って作成したサンプルファイルの通りです。
中身はこうなっています。

全体的に表記ゆれがあるので、それを先ほどのコードで整えていくということですね。
アウトプット
コードを実行します。
すると、ターミナルにはこう表示されます。
最終的に、エクセルファイルは「sample_data_cleaned.xlsx」という名前で別名保存され、画像の通り修正されました!
最初の時と違って表記ゆれが整理されていますね。
2-2. コードの解説
以下、コードの解説です。
ポイント1: 列単位でAIに渡す
values = []
for row in ws.iter_rows(min_row=2, min_col=col_idx, max_col=col_idx):
cell = row[0]
values.append(str(cell.value) if cell.value is not None else "")
normalized = normalize_column(values, column_name)
セル1つずつAIに渡すと API 呼び出し回数が増えてコストがかかります。そこで、列のデータをまとめてリストとして渡すことで、AIが全体を見て統一的な修正を行えるようにしています。
| 方法 | API呼び出し回数 | メリット | デメリット |
|---|---|---|---|
| セル1つずつ | データ件数 x 列数 | 個別に丁寧な処理 | コスト高・低速 |
| 列単位でまとめて | 列数のみ | 低コスト・高速・統一性が高い | 大量データには分割が必要 |
ポイント2: temperature=0.0
temperature=0.0 # 表記統一なので創造性は不要
日報生成のような文章作成では temperature=0.7 程度で多様性を持たせますが、表記ゆれ修正は正確さが最優先です。temperature=0.0 に設定することで、毎回同じ入力に対して同じ出力を返すようになります。
ポイント3: JSON形式で受け取る
prompt = f"""
...
【出力形式】
修正後のデータをJSON配列で返してください。
入力と同じ要素数・同じ順序で返してください。
JSON配列のみを返し、それ以外のテキストは含めないでください。
"""
生成AIの出力をプログラムで処理するには、構造化されたフォーマットで返してもらう必要があります。JSON配列で返すよう指示することで、json.loads() でそのままPythonのリストに変換できます。
ただし、GPT はたまにマークダウンのコードブロック(```json ... ```)で囲んで返すことがあるため、以下のように除去処理を入れています。
if result_text.startswith("```"):
result_text = result_text.split("\n", 1)[1]
if result_text.endswith("```"):
result_text = result_text.rsplit("\n", 1)[0]
ポイント4: 修正内容のログ表示
if old_value != new_value:
print(f" 修正: {old_value} -> {new_value}")
どのデータが修正されたかを表示することで、AIの判断を目視確認できるようにしています。生成AIの出力は必ずしも正しいとは限らないため、特にデータクレンジングのような用途では確認の仕組みが重要です。
4. カスタマイズしてみよう
4-1. 修正ルールを変える
プロンプトの 【修正ルール】 を変えることで、統一ルールを自由にカスタマイズできます。
# 例: 会社名を略称に統一したい場合
"""
- 会社名の場合: 「(株)」の形式に統一(例: (株)ABC)
"""
# 例: 住所の丁目表記を維持したい場合
"""
- 住所の場合: 「1丁目1番1号」の形式はそのまま維持してください
- 「1-1-1」の形式は変換しないでください
"""
4-2. 対象列を変える
main() 関数内の target_columns を変えるだけで、任意の列を修正対象にできます。
# 例: 氏名と部署名だけ修正したい場合
target_columns = ["氏名", "部署名"]
4-3. 大量データへの対応
データが多い場合、一度に全件をAPIに送ると制限に引っかかることがあります。以下のようにバッチ処理を入れると安全です。
def normalize_column_batch(values: list[str], column_name: str, batch_size: int = 50) -> list[str]:
"""大量データをバッチに分割して処理する"""
all_results = []
for i in range(0, len(values), batch_size):
batch = values[i:i + batch_size]
print(f" バッチ処理中... {i + 1}〜{min(i + batch_size, len(values))}件目")
result = normalize_column(batch, column_name)
all_results.extend(result)
return all_results
5. VBA との比較
VBA でも表記ゆれ修正は可能ですが、生成AIを使うアプローチとの違いを整理します。
| 観点 | VBA | Python + 生成AI |
|---|---|---|
| ルール作成 | 全パターンを手動で定義する必要がある | AIが文脈から判断してくれる |
| 未知のパターン | 定義していないパターンには対応できない | 初見のパターンにも柔軟に対応 |
| 処理速度 | 高速(ローカル処理) | API通信があるため比較的遅い |
| コスト | 無料 | API利用料がかかる |
| 精度の保証 | ルール通り確実に動く | まれに誤変換の可能性がある |
| 導入の手軽さ | Excel さえあれば動く | Python環境とAPIキーが必要 |
使い分けの指針: パターンが明確で件数が多いなら VBA、パターンが複雑・不定で判断が必要なら生成AI、というように併用するのがおすすめです。
6. よくあるエラーと対処法
JSON のパースに失敗する
json.JSONDecodeError: Expecting value
→ AIの出力がJSON形式になっていない場合に発生します。プロンプトに「JSON配列のみを返してください」と明記しているか確認してください。それでも発生する場合はリトライ処理の追加を検討しましょう。
修正結果の件数が合わない
→ AIが要素を追加・削除してしまうケースです。normalize_column 関数にチェックを追加すると安全です。
result = json.loads(result_text)
if len(result) != len(values):
print(f" 警告: 入力 {len(values)}件に対し出力 {len(result)}件。修正をスキップします。")
return values # 元のデータをそのまま返す
API の料金が心配
この記事のサンプルデータ(8件 x 3列)を処理した場合の目安です。
| モデル | 1回あたりのコスト目安 |
|---|---|
gpt-4o-mini |
約 0.01 円以下 |
gpt-4o |
約 0.1 円程度 |
gpt-4o-mini であれば、数百件のデータを処理しても数円程度です。
まとめ
この記事では、Python と OpenAI API を使って Excel データの表記ゆれを自動修正するツールを作りました。
今回学んだこと
- openpyxl で Excel ファイルを読み書きする方法
- 生成AIに構造化データ(JSON)を返させるプロンプトの書き方
-
temperature=0.0で出力の安定性を確保する手法 - VBA と生成AIの使い分けの考え方
生成AIに任せる際の注意点
表記ゆれの修正を生成AIに任せるということは、判断をAIに委ねるということです。AIの判断が常に正しいとは限らないため、以下の点に注意してください。
過剰な修正: 「株式会社ABC」と「株式会社エービーシー」が実際には別会社なのに、AIが同じ会社と判断して統一してしまう可能性があります
判断のブレ: temperature=0.0 でもAPIのバージョンアップなどで挙動が変わり、実行するたびに結果が異なることがあります
文脈の見落とし: 「1-1-1」と「1丁目1番1号」のどちらに統一すべきかは会社のルール次第ですが、AIにはその背景がわかりません
だからこそ、だからこそ、本記事のコードに入れた「修正: 旧データ -> 新データ」のターミナル表示が重要です。AIに任せっぱなしにするのではなく、「AIが下書きして、人間が確認する」 という運用を心がけるのが良さそうです。
慣れてきたら楽になるかなと思います。ぜひお試しを!
参考リンク
この記事は「Python x 生成AI 業務自動化シリーズ」の初級編です。
いいねやストックしていただけると励みになります!





