2
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?

【n8n×ChatGPT】APIがない?諦めるな。メール添付の「謎Excel」を構造化データに変換してDBにぶち込む実装術

2
Posted at

unnamed.jpg

はじめに:現場の「APIないです」に絶望するな

SIerや受託開発の現場で、こんな会話をしたことはありませんか?

クライアント: 「受注業務を自動化(DX)したいんです!」
エンジニア: 「承知しました。基幹システムのAPI仕様書をいただけますか?」
クライアント: 「API……? うちは毎日、取引先からメールでExcelが送られてくるだけですが……」

ここで「APIがないと連携できません」「RPAでやるしかないですね(高額)」と答えるのが、普通のエンジニアです。

しかし、我々「実装屋」の回答は一つです。

「大丈夫です。そのExcel、AI(LLM)を使って無理やりAPI化しましょう」

今回は、セル結合や表記揺れだらけの「謎Excel」を、n8nとOpenAI API (GPT-4o) を使って綺麗なJSONに整形し、データベース(KintoneやSupabase)に格納する 「泥臭い実装術」 を共有します。


敵を知る:今回のラスボス「謎Excel」

今回相手にするのは、人間が見るためだけに作られた、システム連携を拒絶するExcelファイルです。

問題 具体例
セル結合 商品カテゴリが見出しとして結合されている
表記揺れ 「(株)」「株式会社」「㈱」が混在
謎の余白 印刷レイアウトのためにA列が空いている
備考の自由記述 「※大至急!」「午前中着で」などが手入力

これをPython(pandas)や従来のプログラムでパースしようとすると、例外処理の嵐で死にます。

そこで、「構造化のプロ」であるLLMの出番です。


アーキテクチャ:n8nが「接着剤」になる

サーバーレスで構築します。n8nをハブにすることで、メール受信からデータ保存までをノーコード(ローコード)で完結させます。

コスト見積もり(月1,000件処理の場合):

  • n8n Cloud: ¥2,500/月(セルフホストなら無料)
  • OpenAI API: ¥3,000-5,000/月(GPT-4o使用)
  • 合計: ¥5,500-7,500/月(RPAツールの1/10以下)

実装ステップ

1. メール監視と添付ファイル取得

n8nの Gmail Trigger ノードを使います。

設定
Filter Subject Contains 【注文書】
Download Attachments true

これで、メールが届いた瞬間にワークフローが起動し、Excelファイルがバイナリデータとしてn8n内に取り込まれます。

2. Excelを「LLMが読める形」にする

ここがポイントです。ExcelバイナリをそのままLLMには投げられません。

n8nの Spreadsheet File ノードを使って、一度「生のデータ(配列)」として読み込みます。
その後、データを軽量化するために、必要なカラムだけを抽出したCSVテキストや、マークダウンの表形式に変換します。

// Code NodeでCSV→Markdownテーブルに整形
const rows = $input.all()[0].json.data;
const headers = Object.keys(rows[0]);

// 最初の20行のみ抽出(トークン節約)
const limitedRows = rows.slice(0, 20);

const mdTable = [
  `| ${headers.join(' | ')} |`,
  `| ${headers.map(() => '---').join(' | ')} |`,
  ...limitedRows.map(row => `| ${headers.map(h => row[h] || '').join(' | ')} |`)
].join('\n');

return [{ json: { markdown_table: mdTable, total_rows: rows.length } }];

3. LLMによる「構造化と正規化」

ここが本記事のハイライトです。
OpenAI Chat Model ノードを使い、ぐちゃぐちゃのテキストデータを「理想的なJSON」に変換させます。

プロンプト例:

あなたは優秀なデータ入力オペレーターです。
以下のテキストデータは、フォーマットが崩れた注文書のExcelから抽出したものです。
これを以下のJSONスキーマに従って構造化し、JSONのみを出力してください。

【ルール】
1. セル結合されている「カテゴリ」は、下位の商品行にも適用すること
2. 会社名の「(株)」「㈱」などは「株式会社」に統一すること
3. 数量が「1ケース」「2箱」などの場合、数値のみ(1, 2)を抽出し、unitに単位を入れること
4. 「備考」にある配送希望時間は `delivery_time` フィールドに入れること
5. 「※大至急」などの表現は urgency: "high" として抽出すること
6. 日付はISO 8601形式(YYYY-MM-DD)に統一すること

【出力JSONスキーマ】
```json
[
  {
    "order_id": "受注番号(なければnull)",
    "customer_name": "正規化された会社名",
    "order_date": "YYYY-MM-DD",
    "items": [
      {
        "category": "カテゴリ名",
        "product_name": "商品名",
        "quantity": 数値,
        "unit": "単位",
        "price": 単価(数値)
      }
    ],
    "delivery_time": "配送希望時間",
    "urgency": "high/normal/low",
    "note": "その他特記事項"
  }
]

JSONモードの活用:
OpenAIノードの設定で、**Response Formatを JSON Object** に必ず設定しましょう。

{ "type": "json_object" }

これがないと、AIが気を利かせて「はい、データを整形しました!」という余計な挨拶文を入れてしまい、後続のノードでパースエラーになります。

温度(Temperature)の設定:
事実抽出なので、創造性は不要です。temperature: 0.1 程度に抑え、再現性を高めます。

出力例:

{
  "order_date": "2026-02-18",
  "customer": {
    "name": "株式会社プロドウガ",
    "contact": "山本様"
  },
  "items": [
    {
      "category": "文具",
      "name": "A4コピー用紙",
      "qty": 10,
      "unit": "箱",
      "unit_price": 2500
    },
    {
      "category": "文具", 
      "name": "ボールペン(黒)",
      "qty": 100,
      "unit": "本",
      "unit_price": 100
    }
  ],
  "delivery": {
    "date": "2026-02-20",
    "time": "AM",
    "urgency": "high"
  },
  "note": "20日午前中までに必着"
}

GPT-4oであれば、人間が「なんとなく」で理解しているセル結合や文脈を、驚くほどの精度で解釈してくれます。
正規表現で3日かかる処理が、プロンプト3行で終わります。

4. データベースへの格納

LLMから返ってきたのは、美しいJSONデータです。
あとは HTTP Request ノード(Kintone REST API)や Kintone ノードを使って、DBにぶち込むだけです。

Kintoneへの登録例:

// HTTP Requestノードの設定
// Method: POST
// URL: https://{{kintone_domain}}[.cybozu.com/k/v1/record.json](https://.cybozu.com/k/v1/record.json)
// Headers:
//   X-Cybozu-API-Token: {{token}}
//   Content-Type: application/json

// Body (JSON):
{
  "app": 123, // アプリID
  "record": {
    "order_date": { "value": "{{ $json.order_date }}" },
    "company_name": { "value": "{{ $json.customer.name }}" },
    "total_amount": { "value": {{ $json.items.reduce((a,b)=>a+b.qty*b.unit_price, 0) }} },
    "delivery_date": { "value": "{{ $json.delivery.date }}" },
    "raw_json": { "value": JSON.stringify({{ $json }}) } // 元データも保存
  }
}

これで、「メールで届くExcel」が「API経由のデータ」と同等の品質になりました。


現場で役立つ「泥臭い」テクニック

PII(個人情報)のマスキング

LLMに顧客データを投げる際、セキュリティが懸念される場合があります。
対策: LLMに投げる前に、n8n内の Code ノードで個人情報をハッシュ化・マスキングします。

// マスキング処理
const data = $input.first().json;

// 電話番号、メールアドレスを正規表現で検出して置換
const maskedText = data.markdown_table
  .replace(/\d{2,4}-\d{2,4}-\d{4}/g, '[PHONE]')  // 電話番号
  .replace(/[\w.-]+@[\w.-]+\.\w+/g, '[EMAIL]'); // メール

// 住所も模糊化(例:東京都渋谷区→東京都[MASK])
const maskedText2 = maskedText.replace(/(...市|...区).*/, '$1[MASK]');

return [{ 
  json: { 
    masked_data: maskedText2,
    original_length: data.markdown_table.length
  } 
}];

ポイント:

  1. LLMには「構造化」だけを依頼する
  2. 返ってきたJSONに対して、後からn8nで本物の個人情報をマージし直す

これなら、OpenAI側に個人情報は渡りません。GDPR・個人情報保護法対応が可能です。

エラーハンドリングと「人間の目」

LLMも万能ではありません。複雑なExcelや手書き文字が入ったファイルは失敗する可能性があります。

推奨フロー:

閾値の設定:

// Ifノードの条件
{
  "conditions": [
    {
      "value": "{{ $json.items.length }}",
      "operation": "gt", // greater than
      "compare": 0
    },
    {
      "value": "{{ $json.customer.name }}",
      "operation": "isNotEmpty"
    }
  ]
}

必須フィールドが欠けている場合は、人間の確認待ち(Human-in-the-loop)に回します。

コスト最適化(PL脳)

GPT-4o-miniでも構造化は十分可能です。精度が必要な場合のみGPT-4oを使い分けます。

月間件数 モデル 概算コスト(月額)
1,000件 GPT-4o-mini ¥1,500 - 2,000
1,000件 GPT-4o ¥5,000 - 8,000

節約テク: Excelの行数が多い場合、1リクエスト100行程度に分割して並列処理すると、速度とコストのバランスが良くなります。


まとめ:DXの入口は「泥」の中にある

「最新のAPIがないから無理」と言うのは簡単です。
しかし、中小企業の現場には、APIなんてありません。あるのはExcelとメールとFAXだけです。

レガシーな入口(Excel/Mail)と、モダンな出口(DB/Dashboard)を、技術(n8n/LLM)で繋ぐこと。
これこそが、我々エンジニアが提供できる本当の「DX」ではないでしょうか。

もし「謎Excel」との戦いに疲れている方がいれば、ぜひこの構成を試してみてください。世界が変わります。


🔗 参考リンク

著者:@YushiYamamoto
株式会社プロドウガ代表 / フルスタックエンジニア。
「技術的負債は返せるなら背負え」がモットー。n8nとTypeScriptを駆使して、泥臭くも止まらない業務自動化システムを構築しています。

2
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
2
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?