◉GEMINI LABEN
●CLI — Gemini CLI の nightly(10月2日)で、チャット記録を追記専用にして履歴の窓幅を絞る修正が入りました。長い会話の重さに効く変更です●12/31 — 導入価格の終了まで残り89日。3.8 / 3.7 / 3.6 Flash は入力 $0.75→$1.50、出力 $3.75→$7.50 になります●ACP — MCP ツールの許可要求が、どのサーバーからのものか表示されないという報告(#29595)が出ています。許可の読み方が論点です●NEW — 3月に増えた Docs・Sheets・Slides・Drive の Gemini 機能、半年後に残したものと外したもの●WINDOWS — Windows で GIT_CONFIG_GLOBAL=NUL が固定され、Git が失敗するという報告(#29614)があります。Windows で CLI を使う方は要確認です●LITE — gemini-3.1-flash-lite は2027年5月7日に停止予定で、後継は gemini-3.5-flash-lite です。急ぎではありませんが、移行表を作っておく題材です●CLI — Gemini CLI の nightly(10月2日)で、チャット記録を追記専用にして履歴の窓幅を絞る修正が入りました。長い会話の重さに効く変更です●12/31 — 導入価格の終了まで残り89日。3.8 / 3.7 / 3.6 Flash は入力 $0.75→$1.50、出力 $3.75→$7.50 になります●ACP — MCP ツールの許可要求が、どのサーバーからのものか表示されないという報告(#29595)が出ています。許可の読み方が論点です●NEW — 3月に増えた Docs・Sheets・Slides・Drive の Gemini 機能、半年後に残したものと外したもの●WINDOWS — Windows で GIT_CONFIG_GLOBAL=NUL が固定され、Git が失敗するという報告(#29614)があります。Windows で CLI を使う方は要確認です●LITE — gemini-3.1-flash-lite は2027年5月7日に停止予定で、後継は gemini-3.5-flash-lite です。急ぎではありませんが、移行表を作っておく題材です
記事一覧/Workspace 連携
◧ Workspace 連携/2026-10-03中級

Sheets から呼ぶ Gemini の月額を、年末の値上げ日をまたいで Apps Script で割り出す

スプレッドシートから Gemini API を呼んでいる方へ。呼び出しごとのトークン数を台帳タブに残し、2026年12月31日で終わる導入価格と2027年1月1日からの標準価格の二段で月額を見積もる Apps Script を、動かした出力つきで書き残します。

Apps Script12Google スプレッドシートGemini API244料金9コスト管理17usageMetadata

十月に入って、来年の予算を見直す時期になりました。ストアレビューの返信文を下書きさせているスプレッドシートを開いたとき、私はそのシートが「いくらかかっているのか」を、一度も数字で見たことがないと気づきました。

動いてはいるのです。セルの関数を引くと返信の下書きが並び、手でそれを直して送っておりました。その繰り返しを、もう何か月も続けておりました。けれど請求の画面を眺めても、どの数字がこのシートのものなのかは分かりません。

しかも Gemini Flash の導入価格には、年末に期限があります。値上げのあとに慌てて試算するのではなく、いまのうちに、シートの中だけで月額を二段で出せるようにしておきたいと思いました。

そのために書いた Apps Script を、そのまま載せます。呼び出しのたびにトークン数を台帳タブへ一行残し、価格表を日付つきで持ち、今日の価格と値上げ後の価格で月額を並べて出します。

先にお伝えしておく前提

導入価格の期限や単価の中身は、ここでは繰り返し書きません。2026年12月31日で導入価格が終わり、2027年1月1日から標準価格になること、そしてそれがモデルの世代を問わず適用されることは、別の記事で一次情報から確かめて書きました。

そちらは Python と標準ライブラリで書いています。こちらは、スプレッドシートから呼んでいる方が、シートの外へ出ずに済ませる版です。

一つだけ、私自身が確かめられていない点があります。年が替わる瞬間は、どのタイムゾーンの日付で切り替わるのでしょうか。先の記事を書いたときに読んだ範囲では、時刻までは書かれていませんでした。そのため、後で触れるとおり、12月31日と1月1日の二日間を「余裕を見る帯」として扱います。

台帳タブに、呼び出しごとの一行を残します

見積もりの材料は、一回ごとの呼び出しが使ったトークン数です。API の応答には usageMetadata が付いており、入力側は promptTokenCount、出力側は candidatesTokenCount に入っています。考える工程を持つモデルでは thoughtsTokenCount も付きます。私はこれを出力側に足して数えています。

まず、台帳用のタブを一つ作ります。シート名は ledger、一行目の見出しは次の五つです。

列見出し入る値
Aday呼び出した日(YYYY-MM-DD の文字列)
Bmodel呼び出したモデル ID
Cin_tokens入力トークン数
Dout_tokens出力トークン数(考えたぶんを含む)
Enote用途のメモ(任意)

日付を文字列にしているのは、意図があってのことです。Apps Script の Date はスクリプトのタイムゾーン設定の影響を受けます。一日のずれが月額には響きませんが、価格の切り替え日の判定には響きます。文字列のまま大小を比べれば、その心配が消えます。

呼び出しの側は、次のように包みます。

function callGemini_(model, prompt, note) {
  const key = PropertiesService.getScriptProperties().getProperty('GEMINI_API_KEY');
  const url = 'https://generativelanguage.googleapis.com/v1beta/models/' +
              model + ':generateContent';
  const res = UrlFetchApp.fetch(url, {
    method: 'post',
    contentType: 'application/json',
    headers: { 'x-goog-api-key': key },
    payload: JSON.stringify({ contents: [{ parts: [{ text: prompt }] }] }),
    muteHttpExceptions: true,
  });
  if (res.getResponseCode() !== 200) {
    throw new Error('Gemini ' + res.getResponseCode() + ': ' +
                    res.getContentText().slice(0, 200));
  }
  const body = JSON.parse(res.getContentText());
  const u = body.usageMetadata || {};
  const out = (u.candidatesTokenCount || 0) + (u.thoughtsTokenCount || 0);
  const day = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy-MM-dd');
  SpreadsheetApp.getActive().getSheetByName('ledger')
    .appendRow([day, model, u.promptTokenCount || 0, out, note || '']);
  return body.candidates[0].content.parts[0].text;
}

API キーはコードに書かず、スクリプトのプロパティに置いています(YOUR_API_KEY の部分を、ご自身のキーで設定してください)。台帳に残すのは数字だけで、プロンプトの本文は入れません。顧客の文面をうっかり台帳へ写してしまわないための、小さな線引きです。

価格表は、日付つきで持ちます

次が、見積もりの心臓部です。単価を数字のまま埋め込まず、いつからいつまで有効かを添えて持ちます。

// 100万トークンあたりの USD。from / to は "YYYY-MM-DD"、to が null は終了未告知
const PRICES = [
  { model: 'gemini-3.8-flash', from: '2026-09-02', to: '2026-12-31', input: 0.75, output: 3.75 },
  { model: 'gemini-3.8-flash', from: '2027-01-01', to: null,         input: 1.50, output: 7.50 },
  { model: 'gemini-3.7-flash', from: '2026-08-13', to: '2026-12-31', input: 0.75, output: 3.75 },
  { model: 'gemini-3.7-flash', from: '2027-01-01', to: null,         input: 1.50, output: 7.50 },
];
const PER = 1000000;
 
function priceOn_(model, day) {
  for (const r of PRICES) {
    if (r.model === model && r.from <= day && (r.to === null || day <= r.to)) return r;
  }
  throw new Error('価格行がありません: ' + model + ' @ ' + day);
}
 
function costOf_(row, day) {
  const p = priceOn_(row.model, day);
  return (row.inTok * p.input + row.outTok * p.output) / PER;
}

表の値は、私が公式ページで確認した時点のものです。ご自身で使うときは、必ず最新の公式の価格表と見比べてから上書きしてください。

priceOn_ は、該当する行がなければ例外を投げます。ここは 0 を返さないようにしました。価格表の書き忘れが、もっともらしい安い数字として出てくるのが、見積もりのいちばん怖い失敗だからです。

台帳から、30日ぶんの月額を二段で出します

台帳を読み、直近の一日あたりの平均を出し、30日ぶんに引き伸ばします。そのとき「どの日の価格で計算するか」を引数で渡します。

function projectMonth_(rows, day) {
  const days = new Set(rows.map(r => r.day));
  const perModel = {};
  for (const r of rows) perModel[r.model] = (perModel[r.model] || 0) + costOf_(r, day);
  let total = 0;
  for (const m in perModel) {
    perModel[m] = perModel[m] / days.size * 30;
    total += perModel[m];
  }
  return { perModel: perModel, total: total };
}
 
function estimate() {
  const ss = SpreadsheetApp.getActive();
  const values = ss.getSheetByName('ledger').getDataRange().getValues().slice(1);
  const rows = values.map(v => ({
    day: String(v[0]), model: v[1], inTok: Number(v[2]), outTok: Number(v[3]),
  }));
  const sheet = ss.getSheetByName('estimate') || ss.insertSheet('estimate');
  sheet.clear();
  sheet.appendRow(['基準日', 'モデル', '30日あたり(USD)']);
  ['2026-12-31', '2027-01-01'].forEach(function (day) {
    const r = projectMonth_(rows, day);
    for (const m in r.perModel) sheet.appendRow([day, m, Math.round(r.perModel[m] * 100) / 100]);
    sheet.appendRow([day, '合計', Math.round(r.total * 100) / 100]);
  });
}

基準日に 12月31日と 1月1日の二つを入れてあるのは、先ほどの帯のためです。切り替えの境目がどちらに寄っても、見積もりが二つの数字のどちらかに収まります。

手元で動かした出力

台帳ロジックの部分(projectMonth_ まで)だけを取り出し、七日ぶんのサンプルを入れて Node.js で動かしました。サンプルは、3.8 Flash を使う日と 3.7 Flash を使う日が混ざった、架空の台帳です。

2026-12-31 gemini-3.8-flash $8.21 | gemini-3.7-flash $6.19 TOTAL $14.39
2027-01-01 gemini-3.8-flash $16.41 | gemini-3.7-flash $12.38 TOTAL $28.79

金額そのものに意味はなく、見ていただきたいのは並びです。1月1日側は、どちらのモデルも 12月31日側のちょうど2倍になっています。入力も出力も単価が2倍になるので、台帳の中身が同じなら月額も2倍になる、という当たり前の結果が、こうして数字で出てきます。

世代を古いものに据え置いても、この2倍は避けられません。避けられるのは、呼び出しの量を減らす工夫のほうです。見積もりを二段で出したあとの私は、モデルを替える相談よりも先に、出力を短くできないかを考えるようになりました。出力の単価は入力の5倍だからです。

価格表に穴があるとき

試しに 3.6 Flash の行が無い状態で、その日の価格を引いてみます。

ERR 価格行がありません: gemini-3.6-flash @ 2026-10-03

シート上では、estimate の実行がここで止まり、実行ログに同じ文言が残ります。止まってくれることが大切です。台帳に新しいモデル名が現れたのに価格表が古いまま、という状況を、一番早く教えてくれるからです。

最初に試す順番

一度に全部を入れる必要はありません。私が手を付けた順に書きます。

  1. ledger タブを作り、見出しの五つを一行目に置きます。
  2. 既存の呼び出しを callGemini_ で包み、一日ぶん動かして行が増えることだけを確かめます。
  3. 価格表を、ご自身が使っているモデルの行だけで作ります。
  4. 一週間ぶん貯まってから estimate を実行します。

台帳が数日ぶんしかないうちは、平均が偏るのかもしれません。休日の多い週だけで30日ぶんに伸ばすと、実際より安く出てしまうからです。

数字を出す前に、その数字がいつの価格で、どの期間の量から出たのかを一行で残しておくこと。 この線引きを、私はいまも守るようにしております。

まずは ledger タブを作るところから、始めていただければと思います。

シェア

お読みいただきありがとうございます

Gemini Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥2,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

◈ API / SDK2026-09-08
値上げの日をまたぐ費用の見積もりを、はじめから二段で書く
Gemini Flash の導入価格は2026年12月31日で終わり、2027年1月1日から標準価格に切り替わります。世代を据え置いても避けられないこの日を、はじめての費用見積もりでどう扱うか。動くコードとともに書き残します。
◧ Workspace 連携2026-09-16
Sheets の AI 関数が生成できないとき、上限より先に置き場所を疑う
スプレッドシートの AI 関数で「生成」が動かないとき、24 時間の上限だと決めつける前に確かめたい点をまとめました。Dropbox や Box 経由で開いた表では、そもそも生成ができません。置き場所・上限・プラン・式の順に切り分けます。
◧ Workspace 連携2026-09-01
Gemini の新機能が Workspace に出てこないとき、待ちと不具合を切り分ける順序
告知された Gemini の新機能が自分の Workspace に現れないとき、それが段階展開の途中なのか設定の問題なのかを、リリーストラックと展開ペースから機械的に判定する手順と Apps Script の台帳をまとめました。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます