0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ChatGPTで整えた問い合わせCSV、Excelで開く前に数式を検出

0
Posted at

9月23日のTechCrunchに「ChatGPT mobile app gets voice-based agentic features」という見出しが出ていました。これが意味するのは、移動中にAIへ仕事を頼む機会が増えるということです。問い合わせの整理も頼みやすい。ただ、整理後のCSVをExcelで開く前には、別の確認が要ります。

問い合わせ文は相手が書いた文字列です。先頭に = などがあると、表計算ソフトが数式として扱う可能性があります。ChatGPTで文面を整えても、この確認は省けません。僕なら、開く前にCSVの文字列列を検査します。

問い合わせ4件で試す

次の内容を inquiries.csv としてUTF-8で保存します。会社名と問い合わせは外部から入る列、IDは社内で振った番号という想定です。URLは実在しない .invalid ドメインにしてあります。

ID,会社名,問い合わせ
1,青葉商事,資料を送ってください
2,"=HYPERLINK(""https://example.invalid"",""資料"")",見積相談
3,南原企画,"  +1+2"
4,東海物流,日程確認

2件目の会社名は =、3件目の問い合わせは空白の後に + が来ます。見た目だけで確認すると後者を落としそうでした。先頭の空白とタブを飛ばしてから調べます。

CSVそのものは、セルの「中身」を区切って保存する形式です。会社名として入った文字列でも、開く側の解釈で数式になり得ます。AIが日本語をきれいに並べ直したかどうかと、この解釈は別です。怖いのは、相手が入力した会社名や問い合わせが、そのまま表のセルに入ること。だから検査するのは、社内で振ったIDより、外から来た自由記述欄です。

Pythonで開く前に止める

Pythonの標準ライブラリだけで動きます。check_csv.py に保存してください。

import csv
import sys
from pathlib import Path

TEXT_COLUMNS = ("会社名", "問い合わせ")
FORMULA_PREFIXES = ("=", "+", "-", "@")

def inspect(path):
    with path.open("r", encoding="utf-8-sig", newline="") as f:
        reader = csv.DictReader(f)
        headers = reader.fieldnames or []
        if len(headers) != len(set(headers)) or any(
            name not in headers for name in TEXT_COLUMNS
        ):
            raise ValueError("列名の重複、または必要な列の欠落があります")

        hits = []
        count = 0
        for count, row in enumerate(reader, start=1):
            if None in row or any(row[name] is None for name in TEXT_COLUMNS):
                raise ValueError(f"{count}件目: 列数が合いません")
            for name in TEXT_COLUMNS:
                value = row[name]
                if value.lstrip(" \t\r\n").startswith(FORMULA_PREFIXES):
                    hits.append((count, name, value))
    return count, hits

if __name__ == "__main__":
    if len(sys.argv) != 2:
        raise SystemExit("使い方: python3 check_csv.py inquiries.csv")
    count, hits = inspect(Path(sys.argv[1]))
    for number, name, value in hits:
        print(f"{number}件目 / {name}: {value!r}")
    print(f"確認: {count}件、要確認: {len(hits)}件")
    raise SystemExit(1 if hits else 0)

実行コマンドは python3 check_csv.py inquiries.csv。僕の手元では次の表示になりました。

2件目 / 会社名: '=HYPERLINK("https://example.invalid","資料")'
3件目 / 問い合わせ: '  +1+2'
確認: 4件、要確認: 2件

3件目も止まった。

数式らしい文字列があれば終了コードは1、なければ0です。CSVを開く後続処理に組み込む場合も、この数字で中断できます。utf-8-sig は、Excelから保存したCSVの先頭にBOMが付いていても列名を読めるようにするためです。newline="" はCSV内の改行を csv に扱わせる指定です。

掲載したCSVに対して、次のassertも通しました。

from pathlib import Path
from check_csv import inspect

count, hits = inspect(Path("inquiries.csv"))
assert count == 4
assert [(n, c) for n, c, _ in hits] == [(2, "会社名"), (3, "問い合わせ")]

実行環境はPython 3.14.6です。上の4件に加え、問題のない1件だけのCSVでは 確認: 1件、要確認: 0件 と出て終了コード0。列が欠けた行では ValueError: 1件目: 列数が合いません で止まりました。行数が合わないファイルを「異常なし」と扱わないためです。出力の「2件目」はCSVの物理的な行番号ではなく、見出しを除いたデータの順番です。問い合わせ内に改行があっても、この数え方なら変わりません。

検出した後の扱い

- で始まる普通の文章も引っかかります。自動で削ると原文が変わるので、このコードは書き換えません。該当セルを人が確認し、必要なら取り込み先で文字列として扱う方法を決めます。対象列も大事です。外部から入る自由記述欄を増やしたら、TEXT_COLUMNS に足します。

逆に、先頭の記号がない文字列まで安全だと証明するコードでもありません。Excel側の取り込み設定や、その後に別の仕組みで加工する手順はここでは検査していません。今回の役目は、開く直前に明らかな要確認セルを見つけ、作業を止めること。営業の一覧表だと「とりあえず開いて中身を見る」が先になりがちですが、その一手前に置きます。

見出しのニュースから僕が気にしたのは、AIに頼める作業が増えるほど、CSVを開く直前の確認が抜けやすいことです。問い合わせ整理をAIに任せる件数が増えたら、この検査を毎回通します。検査は表を開く前に置く。今回の4件で、空白の後ろに隠れたものを含めた要確認は2件。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?