GAS×ChatGPT連携|スプレッドシートからAIを呼び出す方法【GPT-4o対応】

しんたろ。

スプレッドシートのデータをChatGPTで自動処理できたら…GASなら数行のコードで実現できます!

この記事でわかること
  • GASからOpenAI(ChatGPT)APIを呼び出す基本コード
  • APIキーの安全な管理方法(スクリプトプロパティ)
  • テキスト要約・カテゴリ分類・翻訳・メール生成の実践コード
  • =GPT()カスタム関数とバッチ処理の作り方
  • APIコスト管理とGASの6分制限への対策
  • VBAでのChatGPT連携コードとの比較
ChatGPT API連携スクリプトの実行を体験してみよう!

「実行」ボタンを押すと、GASからOpenAI APIにリクエストを送ってChatGPTの回答を取得する動作をシミュレーション体験できます。

</> callChatGPT.gs
1function callChatGPT() { 2 const apiKey = PropertiesService 3 .getScriptProperties() 4 .getProperty(‘OPENAI_API_KEY’); 5 6 const payload = { 7 model: ‘gpt-4o-mini’, 8 messages: [{ 9 role: ‘user’, 10 content: ‘GASとは?50文字以内で’ 11 }] 12 }; 13 14 const res = UrlFetchApp.fetch(url, opt); 15 const answer = JSON.parse(res) 16 .choices[0].message.content; 17 Logger.log(answer); 18}
実行ログ ─ callChatGPT
11:00:01[INFO] APIキーをスクリプトプロパティから取得
11:00:01[INFO] OpenAI API (gpt-4o-mini) にPOSTリクエスト送信…
11:00:03[OK] レスポンス受信: 200 OK (usage: 42 tokens)
11:00:03[LOG] GASはGoogleのクラウド上でスクリプトを実行し、Google Workspaceの各サービスを自動操作できる無料の開発環境です。
11:00:03[DONE] 実行完了 (所要時間: 2.1秒)
🤖 ChatGPT API レスポンス
U
GASとは?50文字以内で教えてください。
role: user
G
GASはGoogleのクラウド上でスクリプトを実行し、Google Workspaceの各サービスを自動操作できる無料の開発環境です。
model: gpt-4o-mini | tokens: 42 | $0.00003
</> classifyInquiries.gs
1function classifyInquiries() { 2 const sheet = SpreadsheetApp 3 .getActiveSpreadsheet() 4 .getSheetByName(‘分類’); 5 6 for (let row = 2; row <= lastRow; row++) { 7 const inquiry = sheet.getRange(row,1); 8 const category = 9 callChatGPTWithRetry(prompt); 10 sheet.getRange(row,2).setValue(category); 11 } 12}
分類シート ─ AI自動分類結果
A: 問い合わせ内容B: AI分類結果
2ログインできなくなりました技術的な質問
3請求書の金額が間違っています料金・請求
4モバイルアプリ版を作ってほしい機能リクエスト
分類 | 3件処理済み
実行ログ ─ classifyInquiries
11:30:01[INFO] シート「分類」を取得 (3件の未処理データ)
11:30:02[OK] Row2: 「ログインできなく…」→ 技術的な質問
11:30:04[OK] Row3: 「請求書の金額が…」→ 料金・請求
11:30:06[OK] Row4: 「モバイルアプリ版…」→ 機能リクエスト
11:30:06[COST] 合計トークン: 186 | 推定コスト: $0.0001
11:30:06[DONE] 分類処理が完了しました (3件)
この記事の目次
  1. GAS×ChatGPT連携でできること
  2. 準備編|OpenAI APIキーの取得と設定
  3. 基本編|GASからChatGPTにリクエストを送る
  4. 実践編|スプレッドシートデータのAI処理
  5. 応用編|カスタム関数としてChatGPTを使う
  6. コスト管理とベストプラクティス
  7. VBAとGASのAI連携比較
  8. よくある質問(FAQ)
  9. まとめ
  10. LINEでExcelを気軽に学べる

GAS×ChatGPT連携でできること

Google Apps Script(GAS)OpenAI API(ChatGPT)を組み合わせると、スプレッドシートのデータをAIで自動処理できます。手動でChatGPTにコピペしていた作業を、ボタン1つで一括実行できるようになります。

GASの基本がまだ不安な方は、先にGAS入門ガイドを確認しておくとスムーズです。

連携の全体像(スプシ → GAS → OpenAI API → スプシ)

GAS×ChatGPT連携の処理フローはとてもシンプルです。

1. スプレッドシートからデータを取得 → 2. GASがOpenAI APIにHTTPリクエストを送信 → 3. ChatGPTが回答を生成 → 4. GASが結果をスプレッドシートに書き戻す

GASの UrlFetchApp.fetch() を使ってOpenAI APIのエンドポイントにPOSTリクエストを送るだけなので、外部ライブラリのインストールは一切不要です。

実用ユースケース5選

GAS×ChatGPT連携の代表的な活用シーンを紹介します。

  1. テキスト要約:議事録や長文レポートを3行に要約してスプシに出力
  2. カテゴリ自動分類:問い合わせ内容を「技術的質問」「料金」「クレーム」等に振り分け
  3. 多言語翻訳:日本語の商品説明を英語・中国語に一括変換
  4. メール文の自動生成:顧客名・案件名を差し込んだビジネスメールを自動作成
  5. データクレンジング:表記ゆれの統一、住所の正規化、誤字の自動修正

この記事では、上記1〜4のユースケースについてコピペで使える完全動作コードを紹介します。

準備編|OpenAI APIキーの取得と設定

GASからChatGPTを使うには、OpenAI APIキーが必要です。ChatGPT Plus(月額$20)のサブスクリプションとは別のサービスで、API利用は従量課金制です。

OpenAIアカウント作成とAPIキー発行

  1. OpenAI Platform にアクセスしてアカウントを作成
  2. ダッシュボード左メニューの「API keys」をクリック
  3. 「Create new secret key」でAPIキーを発行
  4. 表示されたキー(sk-...)をコピーして安全な場所に保存
注意

APIキーは一度しか表示されません。紛失した場合は再発行が必要です。また、APIキーをGASのコードに直接書くのは絶対にやめましょう(後述のスクリプトプロパティを使います)。

GASのスクリプトプロパティにAPIキーを安全に保存

APIキーはソースコードに直書きせず、スクリプトプロパティに保存するのがベストプラクティスです。

  1. GASエディタで「プロジェクトの設定」(歯車アイコン)を開く
  2. 「スクリプトプロパティ」セクションで「プロパティを追加」をクリック
  3. プロパティ名: OPENAI_API_KEY、値: 発行したAPIキーを入力
  4. 「スクリプトプロパティを保存」をクリック

コードからは次のように取得します。

// スクリプトプロパティからAPIキーを取得
const apiKey = PropertiesService.getScriptProperties().getProperty('OPENAI_API_KEY');

この方法なら、スクリプトを共有してもAPIキーが漏洩するリスクを防げます。

料金体系と予算設定(Usage Limits)

OpenAI APIの料金はモデルごとに異なります。2024年時点の主要モデルの料金比較です。

モデル入力(100万トークン)出力(100万トークン)特徴
GPT-4o-mini$0.15$0.60高速・低コスト。分類・要約に最適
GPT-4o$2.50$10.00高精度。複雑な分析・生成向き

スプレッドシート100行の要約処理なら、GPT-4o-miniで数円程度です。まずはGPT-4o-miniで十分な精度が出るか試し、不足ならGPT-4oに切り替える運用がおすすめです。

OpenAIダッシュボードの「Usage Limits」で月額上限を設定しておけば、想定外の高額請求を防げます。最初は$5〜$10程度に設定しておきましょう。

基本編|GASからChatGPTにリクエストを送る

ここからは実際のコードを見ていきます。まずは最もシンプルなAPI呼び出しから始めましょう。

最もシンプルなAPI呼び出しコード

以下のコードをGASエディタにコピペして実行すれば、ChatGPTからの応答をログに表示できます。

/**
 * ChatGPT APIにリクエストを送る最もシンプルなコード
 * 実行前にスクリプトプロパティに OPENAI_API_KEY を設定してください
 */
function callChatGPT() {
  // スクリプトプロパティからAPIキーを取得
  const apiKey = PropertiesService.getScriptProperties().getProperty('OPENAI_API_KEY');

  // APIのエンドポイント
  const url = 'https://api.openai.com/v1/chat/completions';

  // リクエストボディ
  const payload = {
    model: 'gpt-4o-mini',           // 使用するモデル
    messages: [
      {
        role: 'system',
        content: 'あなたは優秀なアシスタントです。'
      },
      {
        role: 'user',
        content: 'Google Apps Scriptとは何ですか?50文字以内で教えてください。'
      }
    ],
    temperature: 0.7,                // 回答のランダム性(0〜2)
    max_tokens: 200                  // 最大出力トークン数
  };

  // HTTPリクエストの設定
  const options = {
    method: 'post',
    headers: {
      'Authorization': 'Bearer ' + apiKey,
      'Content-Type': 'application/json'
    },
    payload: JSON.stringify(payload),
    muteHttpExceptions: true         // エラー時もレスポンスを取得
  };

  // APIを呼び出し
  const response = UrlFetchApp.fetch(url, options);
  const json = JSON.parse(response.getContentText());

  // ChatGPTの回答を取得
  const answer = json.choices[0].message.content;
  Logger.log(answer);

  return answer;
}

ポイントは UrlFetchApp.fetch() でOpenAIのAPIにPOSTリクエストを送っている点です。messages 配列に会話の内容を渡し、choices[0].message.content から回答を取得します。

GPT-4o / GPT-4o-miniの使い分け

モデル選択はコストと精度のトレードオフです。以下の基準で使い分けましょう。

用途推奨モデル理由
テキスト分類・ラベル付けgpt-4o-mini単純な判定タスクは軽量モデルで十分
短文の要約gpt-4o-miniコスト効率が良い
翻訳(日↔英)gpt-4o-mini基本的な翻訳は十分な品質
長文の高精度な要約gpt-4o文脈理解の精度が重要
ビジネスメール生成gpt-4o自然な文章力が求められる
複雑な分析・推論gpt-4o高度な推論能力が必要

コードでの切り替えは、model パラメータを変更するだけです。

レスポンスの解析とエラーハンドリング

本番運用では、APIエラーへの対処が不可欠です。以下のコードはエラーハンドリングとリトライ処理を含んだ実用版です。

/**
 * エラーハンドリング付きのChatGPT API呼び出し関数
 * @param {string} prompt - ChatGPTに送るプロンプト
 * @param {string} model - 使用モデル(デフォルト: gpt-4o-mini)
 * @param {number} retries - リトライ回数(デフォルト: 3)
 * @return {string} ChatGPTの回答テキスト
 */
function callChatGPTWithRetry(prompt, model, retries) {
  model = model || 'gpt-4o-mini';
  retries = retries || 3;

  const apiKey = PropertiesService.getScriptProperties().getProperty('OPENAI_API_KEY');
  if (!apiKey) {
    throw new Error('OPENAI_API_KEY がスクリプトプロパティに設定されていません');
  }

  const url = 'https://api.openai.com/v1/chat/completions';
  const payload = {
    model: model,
    messages: [
      { role: 'system', content: 'あなたは優秀なアシスタントです。簡潔に回答してください。' },
      { role: 'user', content: prompt }
    ],
    temperature: 0.3,
    max_tokens: 1000
  };

  const options = {
    method: 'post',
    headers: {
      'Authorization': 'Bearer ' + apiKey,
      'Content-Type': 'application/json'
    },
    payload: JSON.stringify(payload),
    muteHttpExceptions: true
  };

  // リトライ付きでAPIを呼び出し
  for (let i = 0; i < retries; i++) {
    try {
      const response = UrlFetchApp.fetch(url, options);
      const statusCode = response.getResponseCode();
      const json = JSON.parse(response.getContentText());

      // 正常レスポンス
      if (statusCode === 200) {
        return json.choices[0].message.content.trim();
      }

      // レート制限(429)の場合は待ってリトライ
      if (statusCode === 429) {
        Logger.log('レート制限に達しました。10秒後にリトライします...');
        Utilities.sleep(10000);
        continue;
      }

      // その他のエラー
      throw new Error('API Error ' + statusCode + ': ' + JSON.stringify(json.error));

    } catch (e) {
      Logger.log('リトライ ' + (i + 1) + '/' + retries + ': ' + e.message);
      if (i === retries - 1) throw e;
      Utilities.sleep(3000);
    }
  }
}

muteHttpExceptions: true を設定すると、APIがエラーを返してもGAS側で例外にならず、ステータスコードを確認して適切に処理できます。レート制限(429エラー)の場合は自動的に待機してリトライします。

この操作でよくある疑問

Q: APIキーをスクリプトに直接書いても大丈夫ですか?

A: 絶対にやめてください。スクリプトプロパティ(PropertiesService)に保存するのが必須です。コードに直接書くと、スクリプトを共有した際にキーが漏洩し、第三者に不正利用される恐れがあります。また、GitHubなどに誤ってプッシュするリスクもあるため、プロパティ経由でのアクセスを徹底しましょう。

筆者の実務Tips

ChatGPT APIの応答時間はモデルとプロンプト長で大きく変わります。GPT-4o-miniなら1リクエスト1-3秒ですが、GPT-4oだと5-15秒かかることも。GASの6分制限を考慮すると、バッチ処理では1回の実行で最大50-80件が現実的なラインです。それ以上の場合はPropertiesServiceに処理位置を保存し、時間主導型トリガーで分割実行する設計にしています。

実践編|スプレッドシートデータのAI処理

ここからは、スプレッドシートのデータを実際にChatGPTで処理する4つのユースケースを紹介します。すべてコピペで動く完全動作コードです。

テキスト要約(長文を3行に要約)

A列に長文テキスト、B列にAIによる要約結果を出力します。議事録や報告書の要約に便利です。

/**
 * A列のテキストを3行に要約してB列に出力する
 * シート名「要約」のA2:A列にテキストを入れて実行
 */
function summarizeTexts() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('要約');
  const lastRow = sheet.getLastRow();

  for (let row = 2; row <= lastRow; row++) {
    const text = sheet.getRange(row, 1).getValue();
    if (!text) continue;  // 空セルはスキップ

    // すでに要約済みならスキップ
    if (sheet.getRange(row, 2).getValue()) continue;

    const prompt = '以下のテキストを3行(各行50文字以内)で要約してください。\n\n' + text;

    try {
      const summary = callChatGPTWithRetry(prompt);
      sheet.getRange(row, 2).setValue(summary);

      // API制限回避のため1秒待機
      Utilities.sleep(1000);
    } catch (e) {
      sheet.getRange(row, 2).setValue('エラー: ' + e.message);
    }
  }

  SpreadsheetApp.flush();  // 変更を即時反映
  Logger.log('要約処理が完了しました');
}

カテゴリ自動分類(問い合わせ内容の振り分け)

問い合わせフォームの回答を自動的にカテゴリ分類します。Googleフォーム連携と組み合わせると、回答が届くたびに自動分類するワークフローも構築できます。

/**
 * 問い合わせ内容を自動分類する
 * A列: 問い合わせ内容、B列: 分類結果
 */
function classifyInquiries() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('分類');
  const lastRow = sheet.getLastRow();

  // 分類カテゴリを定義
  const categories = [
    '技術的な質問',
    '料金・請求',
    '機能リクエスト',
    'クレーム・不満',
    'その他'
  ];

  for (let row = 2; row <= lastRow; row++) {
    const inquiry = sheet.getRange(row, 1).getValue();
    if (!inquiry || sheet.getRange(row, 2).getValue()) continue;

    const prompt = '以下の問い合わせ内容を、次のカテゴリのいずれか1つに分類してください。\n' +
      'カテゴリ: ' + categories.join('、') + '\n' +
      'カテゴリ名のみを回答してください。\n\n' +
      '問い合わせ内容: ' + inquiry;

    try {
      const category = callChatGPTWithRetry(prompt);
      sheet.getRange(row, 2).setValue(category);
      Utilities.sleep(1000);
    } catch (e) {
      sheet.getRange(row, 2).setValue('分類エラー');
    }
  }

  Logger.log('分類処理が完了しました');
}

分類タスクはGPT-4o-miniで十分な精度が出ます。temperature: 0.3(低め)に設定すると、回答のばらつきを抑えて安定した分類結果が得られます。

多言語翻訳(日本語↔英語の一括変換)

A列の日本語テキストを英語に翻訳してB列に出力します。商品説明やドキュメントの多言語化に活用できます。

/**
 * A列の日本語テキストをB列に英語翻訳する
 * シート名「翻訳」で実行
 */
function translateTexts() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('翻訳');
  const lastRow = sheet.getLastRow();

  for (let row = 2; row <= lastRow; row++) {
    const japanese = sheet.getRange(row, 1).getValue();
    if (!japanese || sheet.getRange(row, 2).getValue()) continue;

    const prompt = '以下の日本語を自然な英語に翻訳してください。' +
      '翻訳結果のみを出力し、説明は不要です。\n\n' + japanese;

    try {
      const english = callChatGPTWithRetry(prompt);
      sheet.getRange(row, 2).setValue(english);
      Utilities.sleep(1000);
    } catch (e) {
      sheet.getRange(row, 2).setValue('翻訳エラー');
    }
  }

  Logger.log('翻訳処理が完了しました');
}

英語→日本語の翻訳も、プロンプトの指示を「以下の英語を自然な日本語に翻訳してください」に変更するだけで対応できます。

メール文の自動生成

顧客名・案件名・要件をスプレッドシートに入力しておくと、ビジネスメールの文面を自動生成します。GASメール自動送信と組み合わせれば、生成から送信まで一気通貫で自動化できます。

/**
 * スプレッドシートの情報からビジネスメールを自動生成する
 * A列: 顧客名、B列: 案件名、C列: 要件、D列: 生成されたメール文
 */
function generateEmails() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('メール生成');
  const lastRow = sheet.getLastRow();

  for (let row = 2; row <= lastRow; row++) {
    const customerName = sheet.getRange(row, 1).getValue();
    const projectName = sheet.getRange(row, 2).getValue();
    const requirement = sheet.getRange(row, 3).getValue();

    if (!customerName || sheet.getRange(row, 4).getValue()) continue;

    const prompt = '以下の情報をもとに、丁寧なビジネスメールを作成してください。\n' +
      '件名と本文を分けて出力してください。\n\n' +
      '・宛先: ' + customerName + ' 様\n' +
      '・案件: ' + projectName + '\n' +
      '・要件: ' + requirement + '\n' +
      '・差出人: 山田太郎(株式会社サンプル)';

    try {
      // メール生成はGPT-4oの方が自然な文章になる
      const email = callChatGPTWithRetry(prompt, 'gpt-4o');
      sheet.getRange(row, 4).setValue(email);
      Utilities.sleep(1500);
    } catch (e) {
      sheet.getRange(row, 4).setValue('生成エラー');
    }
  }

  Logger.log('メール生成が完了しました');
}
この操作でよくある疑問

Q: ChatGPTの回答が毎回微妙に違うのですが、一貫した結果を得る方法はありますか?

A: temperatureパラメータを0に設定すると、ほぼ同じ入力に対して同じ出力が得られます。カテゴリ分類やデータ抽出など正確性が求められるタスクではtemperature: 0、メール文やキャッチコピー生成など創造性が必要なタスクではtemperature: 0.7-1.0がおすすめです。

筆者の実務Tips

問い合わせメールの自動分類をGAS×ChatGPTで構築した際、精度を上げるコツは「分類カテゴリと定義をプロンプトに明記する」ことでした。「技術サポート・料金問い合わせ・解約」の3カテゴリを明確に定義したプロンプトで分類精度95%を達成。月500件の問い合わせ仕分けが完全自動化でき、担当者の作業時間を月20時間削減できました。APIコストは月額約$3で、人件費と比較すると圧倒的なコストパフォーマンスです。

応用編|カスタム関数としてChatGPTを使う

ここからは、スプレッドシートのセルに =GPT("要約して", A1) のように入力するだけでChatGPTが使えるカスタム関数の作り方を解説します。

=GPT()関数の作成方法

以下のコードをGASに追加すると、スプレッドシート上で =GPT() 関数が使えるようになります。

/**
 * スプレッドシートのカスタム関数としてChatGPTを呼び出す
 * 使い方: =GPT("この文章を要約して", A1)
 *
 * @param {string} instruction - AIへの指示(例: "要約して"、"英語に翻訳して")
 * @param {string} inputText - 処理対象のテキスト
 * @param {string} model - モデル名(省略時: gpt-4o-mini)
 * @return {string} ChatGPTの回答
 * @customfunction
 */
function GPT(instruction, inputText, model) {
  // 引数チェック
  if (!instruction) return 'エラー: 指示を入力してください';
  if (!inputText) return '';

  model = model || 'gpt-4o-mini';

  const apiKey = PropertiesService.getScriptProperties().getProperty('OPENAI_API_KEY');
  if (!apiKey) return 'エラー: APIキー未設定';

  const url = 'https://api.openai.com/v1/chat/completions';
  const payload = {
    model: model,
    messages: [
      { role: 'system', content: instruction },
      { role: 'user', content: String(inputText) }
    ],
    temperature: 0.3,
    max_tokens: 500
  };

  const options = {
    method: 'post',
    headers: {
      'Authorization': 'Bearer ' + apiKey,
      'Content-Type': 'application/json'
    },
    payload: JSON.stringify(payload),
    muteHttpExceptions: true
  };

  try {
    const response = UrlFetchApp.fetch(url, options);
    const json = JSON.parse(response.getContentText());

    if (response.getResponseCode() !== 200) {
      return 'APIエラー: ' + (json.error ? json.error.message : '不明');
    }

    return json.choices[0].message.content.trim();
  } catch (e) {
    return 'エラー: ' + e.message;
  }
}
カスタム関数の注意点
  • カスタム関数は実行時間30秒の制限があります(通常の関数は6分)
  • シートを開くたびに再計算される可能性があり、APIコストが増大する場合があります
  • 大量のセルで使う場合は、次のバッチ処理方式を推奨します

バッチ処理で大量データを効率的に処理

大量のデータをAPI処理する場合は、カスタム関数ではなくバッチ処理で一括実行する方が効率的です。以下のコードは、データを取得→API呼び出し→結果を書き込みの流れをまとめて実行します。

/**
 * バッチ処理でA列のデータを一括AI処理してB列に出力する
 * 大量データの処理に最適(カスタム関数より効率的)
 */
function batchProcess() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const lastRow = sheet.getLastRow();

  // A列のデータを一括取得(セルへのアクセス回数を最小化)
  const inputRange = sheet.getRange(2, 1, lastRow - 1, 1);
  const inputs = inputRange.getValues();

  // B列の既存データも取得(処理済みチェック用)
  const outputRange = sheet.getRange(2, 2, lastRow - 1, 1);
  const outputs = outputRange.getValues();

  const results = [];
  let processedCount = 0;

  for (let i = 0; i < inputs.length; i++) {
    const text = inputs[i][0];

    // 空セルまたは処理済みはスキップ
    if (!text || outputs[i][0]) {
      results.push([outputs[i][0] || '']);
      continue;
    }

    try {
      const prompt = '以下のテキストを50文字以内で要約してください:\n' + text;
      const result = callChatGPTWithRetry(prompt);
      results.push([result]);
      processedCount++;

      // 5分経過したら中断(6分制限対策)
      if (processedCount % 10 === 0) {
        const elapsed = (new Date() - startTime) / 1000;
        if (elapsed > 300) {
          Logger.log('5分経過のため中断。続きは再実行してください。');
          // 残りのセルは空で埋める
          while (results.length < inputs.length) {
            results.push(['']);
          }
          break;
        }
      }

      Utilities.sleep(1000);  // APIレート制限対策
    } catch (e) {
      results.push(['エラー: ' + e.message]);
    }
  }

  // 結果を一括書き込み(パフォーマンス向上)
  outputRange.setValues(results);
  Logger.log(processedCount + '件を処理しました');
}

// 処理開始時刻を記録
const startTime = new Date();

ポイントは、getValues()setValues()データの読み書きを一括実行している点です。セルを1つずつ読み書きするより大幅に高速化できます。

キャッシュで API コストを削減

同じ入力に対して何度もAPIを呼ぶのは無駄です。GASの CacheService を使って結果をキャッシュすれば、APIコストを大幅に削減できます。

キャッシュの仕組みは簡単です。入力テキストをキーにして、APIの結果をキャッシュに保存します。次に同じテキストが来たら、APIを呼ばずにキャッシュから返します。キャッシュの有効期限は最大6時間(21,600秒)です。

実装するには、callChatGPTWithRetry 関数の先頭でキャッシュチェックを追加し、APIの結果取得後にキャッシュに保存する処理を入れるだけです。キーにはプロンプトのMD5ハッシュ値(Utilities.computeDigest() で生成)を使うと、長いプロンプトでも効率的に管理できます。

コスト管理とベストプラクティス

APIのコスト管理はGAS×ChatGPT連携で最も重要なポイントです。適切に管理しないと、予想外の請求が来る可能性があります。

トークン数の計算と最適化

OpenAI APIの料金はトークン数で決まります。日本語は1文字あたり約1〜3トークンを消費します(英語は1単語あたり約1トークン)。

コストを抑えるためのテクニックをまとめます。

  • プロンプトを短く:不要な指示や装飾的な表現を省く
  • max_tokensを適切に設定:必要以上に大きくしない(分類タスクなら50で十分)
  • systemメッセージは使い回す:バッチ処理で同じ指示を毎回送る場合も、APIの仕様上は毎リクエスト必要ですが、短くまとめる
  • GPT-4o-miniを優先:まずは軽量モデルで試し、品質が不足する場合のみGPT-4oに

月額予算の設定方法

OpenAIダッシュボードで月額の利用上限(Usage Limits)を設定しましょう。

  1. OpenAI Usage Limits にアクセス
  2. 「Monthly budget」で月額上限を設定(例: $10)
  3. 「Email notification threshold」で通知閾値を設定(例: $8で通知)

上限に達するとAPIがエラーを返すため、意図しない高額請求を防げます。個人利用なら$5〜$10/月、業務利用でも$50/月あれば十分なケースがほとんどです。

GASの実行時間制限(6分)への対策

GASには1回の実行で最大6分という制限があります。API呼び出しを含むバッチ処理では、この制限に引っかかりやすいです。

対策は3つあります。

  1. チャンク分割:処理を小分けにして、5分経過したら中断→トリガーで自動再実行
  2. 処理済みフラグ:各行の処理状況をスプレッドシートに記録し、途中から再開可能にする
  3. 時間駆動型トリガー:1分ごとにトリガーを設定し、未処理の行を少しずつ処理する

前述のバッチ処理コードには、5分経過時点で自動中断する処理を組み込んであります。再実行すると、処理済みの行をスキップして続きから再開します。

VBAとGASのAI連携比較

ExcelユーザーがVBAでChatGPT APIを呼び出すことも可能です。GASとの違いを比較してみましょう。

VBA + ChatGPT APIのコード例

VBAからChatGPT APIを呼び出すコード例です。GASと比べると、HTTPリクエスト部分のコードがやや冗長になります。

' VBAからChatGPT APIを呼び出す
' ※事前に「Microsoft XML, v6.0」の参照設定が必要
Function CallChatGPT(prompt As String) As String
    Dim apiKey As String
    apiKey = "sk-your-api-key-here"  ' ※実際にはレジストリ等で管理推奨

    Dim http As New MSXML2.XMLHTTP60
    Dim url As String
    url = "https://api.openai.com/v1/chat/completions"

    ' リクエストボディ(JSON文字列を手動で組み立て)
    Dim body As String
    body = "{""model"":""gpt-4o-mini""," & _
           """messages"":[{""role"":""user"",""content"":""" & _
           Replace(prompt, """", "\""") & """}]," & _
           """temperature"":0.7,""max_tokens"":500}"

    ' HTTPリクエスト送信
    http.Open "POST", url, False
    http.setRequestHeader "Content-Type", "application/json"
    http.setRequestHeader "Authorization", "Bearer " & apiKey
    http.send body

    ' レスポンスからJSON解析(VBAにはJSON.parseがないため手動)
    Dim response As String
    response = http.responseText

    ' 簡易的にcontentを抽出(本格運用ではJSONパーサーライブラリ推奨)
    Dim startPos As Long, endPos As Long
    startPos = InStr(response, """content"":""") + 11
    endPos = InStr(startPos, response, """}")
    CallChatGPT = Mid(response, startPos, endPos - startPos)
End Function

GASとVBAのAI連携比較表

比較項目GASVBA
HTTPリクエストUrlFetchApp(標準)MSXML2.XMLHTTP(参照設定必要)
JSONパースJSON.parse()(標準)標準機能なし(ライブラリ必要)
APIキー管理スクリプトプロパティレジストリ or 環境変数
実行環境クラウド(ブラウザ不要で自動実行可)ローカルPC(Excelを開く必要あり)
定期実行トリガーで自動実行タスクスケジューラ+マクロで対応
実行時間制限6分制限なし
コードの簡潔さシンプル(JavaScript)やや冗長
チーム共有スプレッドシート共有で即利用可.xlsmファイル配布が必要

AI連携においては、JSON処理の簡単さクラウド実行できる点でGASが圧倒的に有利です。VBAはJSON解析の標準機能がなく、参照設定やライブラリ導入が必要になります。一方、VBAには実行時間制限がないため、大量データの連続処理ではVBAに利点があります。

よくある質問(FAQ)

Q. ChatGPT APIの利用にはいくらかかりますか?

GPT-4o-miniなら100万トークンあたり約$0.15(入力)/$0.60(出力)です。スプレッドシート100行の処理で数円程度で済みます。GPT-4oは約$2.50/$10.00とコストが上がりますが、高精度が求められるタスクに適しています。OpenAIダッシュボードで月額上限を設定しておけば安心です。

Q. APIキーが漏洩した場合のリスクは?

第三者にAPIキーを使われ、高額な利用料が発生するリスクがあります。漏洩に気づいたら即座にAPIキーを無効化し、再発行してください。予防策として、Usage Limitsの設定とスクリプトプロパティによる管理を必ず行いましょう。

Q. GASからGPT-4oを使えますか?

はい、GASの UrlFetchApp でOpenAI APIを呼び出す際の model パラメータを "gpt-4o" に変更するだけで利用可能です。特別な設定や追加のライブラリは不要です。

Q. 社内データをAPIに送信してもセキュリティは大丈夫ですか?

OpenAI APIに送信されたデータは、APIの利用規約上モデルのトレーニングには使用されません(デフォルトでオプトアウト済み)。ただし、個人情報や機密情報は事前に匿名化・マスキングすることを推奨します。社内のセキュリティポリシーも確認してください。

Q. ChatGPT以外のAI(Claude、Gemini)もGASから使えますか?

はい、Claude(Anthropic API)やGemini(Google AI Studio API)も UrlFetchApp で同様に呼び出せます。エンドポイントURLやリクエスト形式が異なるだけで、GAS側の基本的な処理構造は同じです。

まとめ

この記事では、GAS(Google Apps Script)からOpenAI(ChatGPT)APIを呼び出してスプレッドシートのデータをAIで自動処理する方法を解説しました。

この記事のポイント
  • GASの UrlFetchApp でOpenAI APIに直接リクエストを送れる(外部ライブラリ不要)
  • APIキーはスクリプトプロパティに保存し、コードに直書きしない
  • 要約・分類・翻訳・メール生成をコピペで実装可能
  • =GPT()カスタム関数でセルから直接AI処理できる
  • GPT-4o-miniから始めてコストを抑え、Usage Limitsで予算管理を忘れずに

まずは基本のAPI呼び出しコードをコピペして動かしてみてください。1つ動くと、応用の幅が一気に広がります。GASの基本操作についてはGAS入門ガイドも参考にしてください。

GAS開発・自動化のご相談はこちら

「ChatGPT APIの設定が難しい...」「自社データで本格的なAI自動化を組みたい」という方へ。GAS開発代行・自動化コンサルティングを承っています。

自動化コンサルティングの詳細はこちら →

期間限定でChatGPT✖︎Googleスプレットシートのコンテンツ配布中!

LINEでExcelを気軽に学べる

しんたろ。
しんたろ。
Excel歴10年以上 → アプリ開発者
Profile
大手メーカーに15年以上勤務。製造部門で海外拠点の立ち上げ支援や、現場責任者として採算管理・納期管理・設備オペレートを経験。 2023年にDX人材育成プログラム第1期生として活動後、現在は製造現場のスケジュール運用を支えるアプリの企画・開発をメインに活動中。工程表示表作成の内製化SaaSを構築し、年間1,300万円のコスト改善を実現。 Excelによる業務改善で年間240時間の残業削減を達成した経験を活かし、ブログやSNSでも情報発信しています。
プロフィールを読む

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

ABOUT ME
しんたろ。
しんたろ。
Excel歴10年以上 → アプリ開発者
大手メーカーに15年以上勤務。製造部門で海外拠点の立ち上げ支援や、現場責任者として採算管理・納期管理・設備オペレートを経験。 2023年にDX人材育成プログラム第1期生として活動後、現在は製造現場のスケジュール運用を支えるアプリの企画・開発をメインに活動中。工程表示表作成の内製化SaaSを構築し、年間1,300万円のコスト改善を実現。 Excelによる業務改善で年間240時間の残業削減を達成した経験を活かし、ブログやSNSでも情報発信しています。
記事URLをコピーしました