マキモノ
Google Workspace無料✅ 公式検証済みv1.0.0 / 更新

スプレッドシートのボタンUIを複数人同時利用に耐えさせる(GASジョブキュー化)

▶チェックで処理が走るシートUIは複数人が同時に使うと予約が黙って消える。1押下=1キュー行+対象ごとにシート分離+claimワーカーで直す設計と、script lockの奪い合い・6分制限・並列検証の落とし穴

出品者: kim@orgiast.jp2 DL📖 読込 約2,351トークン (約4円)💰 コスパ 83
トークン節約メーター88%節約
ゼロからAIに作らせた場合22万トークン
このMDを読ませた場合2.6万トークン

19.4万トークンの節約 (API料金換算で約290円分)。 要件定義・技術調査・試行錯誤ぶんのトークンがまるごと不要になります。※ 出品者申告とレビューに基づく推定値。モデル・タスク内容により変動します。

この巻物について

スプレッドシートのボタンUIを複数人同時利用に耐えさせる(GASジョブキュー化)」は、Google WorkspaceカテゴリのAI指示書(MDファイル)です。▶チェックで処理が走るシートUIは複数人が同時に使うと予約が黙って消える。1押下=1キュー行+対象ごとにシート分離+claimワーカーで直す設計と、script lockの奪い合い・6分制限・並列検証の落とし穴この巻物をAIに読み込ませると、ゼロから設計・調査する場合に比べて 約19.4万トークン(API料金換算で約290円)・88%のトークンを節約できます。

カテゴリ
Google Workspace
対応AI
claude-code、cursor、codex-cli
ライセンス
商用利用可 (再販不可)
価格
無料
ゼロから開発時
約22万トークン
この巻物使用時
約2.6万トークン
節約量
約19.4万トークン (約290円)
更新日
2026-08-21

使い方 (AIに渡す3つの方法)

いちばん簡単なのはワンライナー。Claude Code のターミナルに貼るだけです。

⬇ .md をダウンロード
claude "https://makimono-md.vercel.app/api/v1/files/ui-gas/raw を読み込んで、この指示書どおりに実装して"
claude-codecursorcodex-cliライセンス: 商用利用可 (再販不可)

中身

スプレッドシートのボタンUIを「複数人×複数案件の同時利用」に耐えさせる(GAS ジョブキュー化)

Google スプレッドシート上に「▶チェックを入れると処理が走る」パネルを作ると、単独利用では動くのに 複数人が同時に使った瞬間に壊れる。この指示書は、その壊れ方の全パターンと、ジョブキュー化による直し方、 実装時に必ず踏む落とし穴(ロック・6分制限・API呼び出し回数)をまとめたもの。

対象: GAS + スプレッドシート製の社内ツール(実行パネル / 一括処理ボタン / 承認ボタン等)。 前提: 処理本体は別プロジェクト(またはコンテナ外)にあり、シートは「受付」だけを担う構成にできること。


1. 共有UIが壊れる4パターン(先に理解する)

#壊れ方症状
1上部の「対象セレクタ」セルが全員共有A が対象を選んだ直後に B が切り替えると、A の押下が B の対象で実行される。エラーは出ない
2機能行が全員共有同じ機能を 2 人が押すと状態セルが上書きされ、先の予約が黙って消える
3結果セルが共有誰の・どの対象の結果か分からない。上書きされる
4自由入力欄が共有同時記入で内容が混ざる

根本原因は 「セルの現在値」を暗黙の引数にしていること。onEdit は「押した瞬間のセル」を読むので、 選ぶ→押す の間に他人が変えられる時間帯が必ず存在する。


2. 直し方(設計)

2.1 対象ごとにシートを分ける

▶パネル(対象を選ぶ索引) + ▶パネル(対象A) ▶パネル(対象B) … の構成にする。 対象セレクタという操作自体を無くすのでパターン1,3,4 が消える。

シートの識別はシート名でなく隠しセルのマーカーで行う(人が改名しても壊れないため):

G1 = 'PANEL_V2'      // マーカー
G2 = <対象ラベル>     // 実行時の対象解決に使う唯一の正
G3 = <対象の物理位置> // 参考値。ズレても実行はG2から解決する
G5 = <生成日時>

2.2 1押下 = キュー1行(これが本体)

非表示シート _ジョブキュー に append する。ヘッダー固定・行の削除と並べ替えをしない(jobIdで追跡):

jobId / 受付日時 / 依頼者 / パネルシート名 / パネル行 / 対象ラベル / 機能ラベル /
command / argsJSON / システムフラグ / 状態 / 開始日時 / 終了日時 / 結果URL / メッセージ / ワーカー
  • 状態は 待機 / 実行中 / 完了 / エラー / タイムアウト
  • 依頼者は Session.getActiveUser().getEmail()取れない環境がある前提で、空でも全機能が動くようにする
  • 同じ「パネル+行」に 待機/実行中 があれば新規行を作らず「既に実行中です(依頼: ○○ / HH:mm)」を toast。 同じ成果物への同時書き込みを防ぐ

2.3 claim ベースのワーカー

毎分トリガーのワーカーを 2 本(worker1 / worker2)置き、1 実行 1 ジョブだけ処理する。

function claimAndRun(workerId) {
  var lock = LockService.getDocumentLock();      // ← §3.1 参照。script lock を使わない
  if (!lock.tryLock(10000)) return null;
  var selected;
  try {
    // 1) 実行中で開始から15分超のものを「タイムアウト」に落とす(GASは6分で強制終了するため)
    // 2) 待機を受付日時昇順に並べ、次を除外して先頭を取る
    //    - 同じパネル(=同じ対象)に実行中がある → 除外(同一対象は直列)
    //    - 同じ依頼者に実行中がある → 除外(1人の連打で他人を待たせない)
    //    - 全部除外されたら「同一対象に実行中が無い最古」を最後の砦として拾う
    // 3) 状態=実行中 / 開始日時 / ワーカーID を書いて flush
  } finally {
    lock.releaseLock();                          // ← 本処理の前に必ず解放する
  }
  // 4) ロック外で本処理(数分かかる)
  // 5) 結果をキュー行とパネル行の両方へ書く
}

結果を書く直前に jobId で行番号を引き直す。 掃除処理が行削除していると、保持していた行番号が 別ジョブを指し、他人の結果欄に書き込むサイレント混線が起きる。

2.4 待ち状況を見せる

毎分の軽い処理で、待機 行のパネル状態セルに ⏳ 順番待ち (前に n 件) を書く(1回20セルまで等の上限を付ける)。 「押したのに何も起きない」という問い合わせが消える。


3. 実装時に必ず踏む落とし穴

3.1 script lock は「操作経路」と共有してはいけない

LockService.getScriptLock() はスクリプトに 1 個しかない。外部からの操作経路(例: ファイル投函型の コマンドキュー)が 1 実行の間ずっと script lock を持つ設計だと、そこにワーカーを足した瞬間に 両者が奪い合って操作経路が毎分 skip され、操作不能に見える

  • ワーカーは getDocumentLock()(コンテナバインドなら使える)等に分離する
  • ロックは短く。claim だけ守り、本処理はロック外
  • 症状の見分け方: 「投函したファイルは消費されているのに結果が返らない」

3.2 重い書き込みは 6 分制限に届く(行ごと getRange が致命的)

数式(外部参照系)が多いシートでは 1 回の書き込みごとに再計算が走り、1 枚のパネル生成で 100 回近い API 呼び出しがあると数分かかる。

  • insertCheckboxes() / 背景色 / 値は範囲一括にする(setBackgrounds に二次元配列、 チェックボックスは列範囲へ一括後、対象外の行だけ clearDataValidations()
  • 一覧描画で「行ごとに全シートを走査してリンク先を探す」のは 行数×シート数 になる。 先に ラベル→gid のマップを 1 回だけ作る
  • 一括生成は「1 実行 N 枚まで + 残りは自分をもう一度キューに積む」自己継続方式にする (キューのワーカーが 1 分ごとに 1 枚ずつ進めるので 6 分制限に当たらない)

3.3 ファイル投函型のコマンドキューに重い命令を同時投入しない

1 回の実行でフォルダ内の全命令を拾う実装が一般的なので、重い命令を複数投げると まとめて 6 分制限で死に、後続の結果ファイルが書かれない。重いものは 1 件ずつ。

3.4 定義の二重管理をやめる

「受付側(シート)」と「実行側(別プロジェクト)」の両方に機能定義を置くと、手で同期する運用になり必ずズレる。 定義は実行側に単一ソース化し、受付側は「その行の隠し列(command / args / フラグ)を読んで積むだけ」にする。 受付側は追加権限を要求しない simple onEdit のみで完結する。


4. 検証(ここまでやって初めて完了)

4.1 ユニット(実行環境の外で回す)

純関数に切り出して node --test で検証する: claim 候補選択(同一対象除外/同一依頼者除外/全除外時の フォールバック/受付日時昇順)・stale 判定の境界(14分59秒は継続 / 15分01秒でタイムアウト)・ 順番待ち件数・重複ガード・依頼者が空文字でも壊れないこと

4.2 実機(read-back で確認する)

検証専用のダミー命令(指定秒スリープして固定の結果を返すだけ)を用意し、キューに積んで確認する。

  1. 別対象 2 件 → 並行(開始〜終了が重なること・ワーカーIDが別)
  2. 同一対象 2 件 → 直列(2 件目は 1 件目の終了後に開始)
  3. 依頼者が別 → それぞれ処理される
  4. 開始日時を過去に書き換えた行がタイムアウトに落ちて再実行可能になる

ダミーの秒数は長めにする(90〜120秒)。毎分トリガーは同時刻に発火せず数十秒ずれるため、 短いジョブでは並行しても実行時間が重ならず「並列できていない」と誤判定する。

4.3 結果の読み取りを速くする小技

索引シートを先頭シートにしておくと、スプレッドシートを CSV エクスポートするだけで 索引の中身をそのまま読める(read-back が一気に速くなる)。


5. 移行時の注意

  • 旧パネルのシート名を変えずに中身を索引へ差し替えると、既存の案内リンク・メニューが生きたまま移行できる
  • 受付側の onEdit を先に配ってから索引を作ると、旧パネルの行を押した人が意図しないシートを生成する空白期間ができる。 受付側の配布と索引の再構築は間を空けない。索引で解決できないラベルの行は作らずに toast で止める
  • 対象別シートは「使う人が開いたときだけ作る」+「終了した対象は N 日後に自動で非表示(削除はしない)」で タブの増殖を抑える

よくある質問

「スプレッドシートのボタンUIを複数人同時利用に耐えさせる(GASジョブキュー化)」とは何ですか?

▶チェックで処理が走るシートUIは複数人が同時に使うと予約が黙って消える。1押下=1キュー行+対象ごとにシート分離+claimワーカーで直す設計と、script lockの奪い合い・6分制限・並列検証の落とし穴

どれくらいトークン(費用)を節約できますか?

ゼロから開発すると約22万トークンかかりますが、この巻物を使えば約2.6万トークンで済みます。差し引き約19.4万トークン(API料金換算で約290円)・88%の節約です。

どうやって使いますか?

無料です。MDファイルを Claude Code などのAIに読み込ませるだけ。ワンライナーをターミナルに貼れば実装が始まります。要件定義や技術調査を省いて実装だけにトークンを使えます。

どのAIツールに対応していますか?

claude-code、cursor、codex-cli に対応しています。

商用利用できますか?

ライセンスは「商用利用可 (再販不可)」です。

🤝 自分でAIを動かすのは、まだ不安…という方へ

この巻物の内容を、AIを使うプロに丸ごと任せることもできます。姉妹サービスAI代行堂なら「LINEで頼むだけで、仕事が完成」。

AI代行堂を見る →

関連する巻物

この巻物、誰かのトークンも救えます

𝕏 で節約レシートをシェア