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

本番スプレッドシートに「新しいレコードの列ブロック」を安全に増やす型(GAS)

横並び1レコード=N列のシートに、既存ブロックの複製で新しい列ブロックを自動追加する型。数式の相対参照追従・IMPORTRANGEの絶対URL差し替え・日付セルのread-back照合の罠・本番検証用の撤去コマンドまで。

出品者: kim@orgiast.jp📖 読込 約3,274トークン (約5円)💰 コスパ 16
トークン節約メーター85%節約
ゼロからAIに作らせた場合6.2万トークン
このMDを読ませた場合9,000トークン

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

この巻物について

本番スプレッドシートに「新しいレコードの列ブロック」を安全に増やす型(GAS)」は、Google WorkspaceカテゴリのAI指示書(MDファイル)です。横並び1レコード=N列のシートに、既存ブロックの複製で新しい列ブロックを自動追加する型。数式の相対参照追従・IMPORTRANGEの絶対URL差し替え・日付セルのread-back照合の罠・本番検証用の撤去コマンドまで。この巻物をAIに読み込ませると、ゼロから設計・調査する場合に比べて 約5.3万トークン(API料金換算で約80円)・85%のトークンを節約できます。

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

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

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

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

中身

本番スプレッドシートに「新しいレコードの列ブロック」を安全に増やす型(GAS)

横並び(wide format)で 1 レコード = N 列のブロックが並ぶ運用シートに、新しいレコードのブロックを プログラムから追加するための型。現場が毎日使っている本番シートに、人の手コピペを廃止して 「フォームに入力 → ブロックが自動でできる」を実現する。

対象: Google Apps Script(clasp 管理 / AI から関数を呼べる構成)。 似た型に「既存セルを一括更新する」ものがあるが、本書は列を増やす側の落とし穴に絞る。


0. まず実測する(推測でレイアウトを決めない)

wide format のシートは「何行目が何か」がドキュメント化されていないことが多い。 書き込みコードを1行も書く前に、読み取り専用のプローブ関数で実形状を取る。

/** 指定ブロックの実形状を返す(読み取り専用) */
function debug_blockShape(blockStart) {
  const sheet = SpreadsheetApp.openById('<スプレッドシートID>').getSheetByName('<シート名>');
  const lastCol = sheet.getLastColumn();
  const blocks = [];
  for (let bs = FIRST_COL; bs + (BLOCK_WIDTH - 1) <= lastCol; bs += BLOCK_WIDTH) blocks.push(bs);
  const target = Number(blockStart) || blocks[blocks.length - 1];

  return {
    lastCol: lastCol, maxCols: sheet.getMaxColumns(),
    blockCount: blocks.length, blockStarts: blocks, target: target,
    // 見出し行の値と数式を両方返す(値だけ見ると数式の存在に気付けない)
    headValues: sheet.getRange(1, target, HEAD_ROWS, BLOCK_WIDTH).getValues(),
    headFormulas: sheet.getRange(1, target, HEAD_ROWS, BLOCK_WIDTH).getFormulas(),
    // ドロップダウンの有無(コピーで運ばれるか判断するため)
    validation: String((sheet.getRange(20, target + BLOCK_WIDTH - 1).getDataValidation() || {}).getCriteriaType
      ? sheet.getRange(20, target + BLOCK_WIDTH - 1).getDataValidation().getCriteriaType() : ''),
    columnWidths: [0, 1, 2].map(function (i) { return sheet.getColumnWidth(target + i); }),
    frozenRows: sheet.getFrozenRows(), frozenCols: sheet.getFrozenColumns()
  };
}

実測でよく判明すること(どれも推測だと外す):

  • 本体データが終わる行と、その下に集計対象外の旧行が残っている(getLastRow() を信じると件数が倍になる)
  • 見出しに見えるセルが実は数式(COUNTIF / IMPORTRANGE
  • ブロック先頭列が「N 列おき」の規則から外れている列がある
  • URL セルが HYPERLINK 数式ではなく素の文字列

1. 新ブロックは「既存ブロックの複製」で作る(自前で組み立てない)

sheet.getRange(1, templateStart, COPY_ROWS, BLOCK_WIDTH)
  .copyTo(sheet.getRange(1, newStart, COPY_ROWS, BLOCK_WIDTH),
          SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);

PASTE_NORMAL書式・数式・データ検証(プルダウン)・条件付き書式をまとめて運ぶ。 自前で setFormula を書き直すと、表記ゆれ(全角/半角、集計範囲の行数違い)で既存ブロックと 微妙に違う式ができ、集計だけが静かにズレる

複製したあとに消すもの・直すもの:

対象処理理由
データ行clearContent()検証と書式は残す(clear() だとプルダウンごと消える)
見出し行clearContent() → 新しい値を setValues
相対参照の集計式=COUNTIF(X15:X234,"済")触らないコピーで新しい列へ自動追従する
絶対URLを持つ数式IMPORTRANGE("https://…")URL を差し替える。無ければ clearContent()コピー元のレコードを指したまま残る=他レコードのデータが混ざる
列幅setColumnWidth() で別途コピーcopyTo は列幅を運ばない
// IMPORTRANGE の URL だけを差し替える純粋関数(テスト可能)
function rewriteImportrange(formula, newUrl) {
  if (!newUrl) return '';                       // 空 = クリア指示
  return String(formula || '').replace(
    /(IMPORTRANGE\s*\(\s*)(["'])([^"']*)(\2)/i,
    function (_, prefix, quote, oldUrl, close) { return prefix + quote + newUrl + close; });
}

2. 列を増やす方向のガード(これが無いと全レコードがズレる)

const newStart = lastBlockStart + BLOCK_WIDTH;
if ((newStart - FIRST_COL) % BLOCK_WIDTH !== 0) throw new Error('ブロック位置が不正: ' + newStart);
if (sheet.getMaxColumns() < newStart + BLOCK_WIDTH - 1) {
  sheet.insertColumnsAfter(sheet.getMaxColumns(), BLOCK_WIDTH);  // 追加は右端だけ
}
  • 追加は右端のみ。中間への insertColumns は右側の全ブロックの列番号を変え、 他システムが保存している「レコード → 列番号」の対応を一斉に壊す
  • 削除も最終ブロックのみ許可し、期待するキー(レコード名など)の一致を関数側で検証する
  • 冪等性: 同じキーのブロックが既にあれば新規作成せず再利用する。 「押すたびにブロックが増える」が最悪の事故

3. 日付書式セルの read-back を文字列で照合しない(実害あり)

書き込み後の flush() → 読み直し照合は必須だが、日付の表示形式が付いたセルsetValue('2026/12/01') すると Sheets 側が Date 値に変換して保存する。 読み戻すと Date オブジェクトなので、素朴な String(actual) !== expected は必ず不一致になる。

mismatches: [{ row: 4, expected: "2026/12/01",
               actual: "Tue Dec 01 2026 00:00:00 GMT+0900" }]   ← 値は正しいのに不一致

値は正しいのに毎回「不一致」が出ると、本物の書き込み失敗(保護範囲やデータ検証による silent ignore)を見逃す。照合側を日付に対応させる:

function sameCell(actual, expected) {
  const norm = function (v) {
    if (v instanceof Date && !isNaN(v.getTime())) {
      const jst = new Date(v.getTime() + 9 * 60 * 60 * 1000);   // タイムゾーンは自環境に合わせる
      const pad = function (n) { return ('0' + n).slice(-2); };
      return jst.getUTCFullYear() + '/' + pad(jst.getUTCMonth() + 1) + '/' + pad(jst.getUTCDate());
    }
    const s = String(v == null ? '' : v).trim();
    const m = s.match(/^(\d{4})[/-](\d{1,2})[/-](\d{1,2})$/);   // 2026/12/1 と 2026/12/01 を同一視
    return m ? m[1] + '/' + ('0' + m[2]).slice(-2) + '/' + ('0' + m[3]).slice(-2) : s;
  };
  return norm(actual) === norm(expected);
}

日付として解釈できない値は従来どおり厳密比較する。緩めすぎると照合の意味が無くなる。


4. 本番で検証するための「撤去コマンド」を先に作る

本番シートでしか再現しない問題(数式の追従・プルダウン・条件付き書式)があるので、 本番で1件登録して検証するのが正しい。そのために撤去コマンドを先に用意する。

/** テスト登録を丸ごと撤去する。dryRun 既定 true */
function admin_removeTestRecord(recordId, opts) {
  const dryRun = !(opts && opts.dryRun === false);
  // ① キーが "__TEST__" で始まるレコードしか消せない(誤爆の上限を関数で縛る)
  if (String(clientName).indexOf('__TEST__') !== 0) return { ok: false, reason: 'テストレコードではありません' };
  // ② 最終ブロックであることを確認してから deleteColumns(blockStart, BLOCK_WIDTH)
  // ③ 付随して作られたシート/行/フォルダも消す(フォルダは削除ではなく setTrashed(true))
  // ④ 消したあと read-back して残骸ゼロを確認し、残っていたら ok:false で残骸を返す
}

検証の流れ:

  1. register(payload, {dryRun:true})1セルも書かずに「何列目に作るか」を返す
  2. register(payload) … 実行
  3. debug_blockShape(newBlockStart) … 見出し・数式・プルダウン・空のデータ行を実測で確認
  4. admin_removeTestRecord(id, {dryRun:true}){dryRun:false} … 撤去
  5. debug_blockShape()元のブロック数・最終列に戻ったことを確認

戻り値の ok:true だけを信じない。同じデータを別コマンドで読み直すまで検証は終わっていない。


5. AI に渡すときのチェックリスト

  • 読み取り専用プローブで実形状を取り、その数値を仕様書に貼ってから実装を依頼したか
  • 新ブロックは既存ブロックの copyTo(PASTE_NORMAL) で作る指示になっているか
  • 絶対URL入り数式(IMPORTRANGE 等)の差し替え/クリアを明記したか
  • 「既存ブロックには絶対に書かない」「中間への列挿入・削除は禁止」を明記したか
  • キー重複時に再利用する(増殖させない)冪等性を明記したか
  • dryRun と撤去コマンドを実装と同じ依頼に含めたか
  • 日付セルの照合を文字列比較にしていないか
  • レコード名・ラベルの生成規則が、既存の同期処理と1文字も違わないことをテストで固定したか

よくある質問

「本番スプレッドシートに「新しいレコードの列ブロック」を安全に増やす型(GAS)」とは何ですか?

横並び1レコード=N列のシートに、既存ブロックの複製で新しい列ブロックを自動追加する型。数式の相対参照追従・IMPORTRANGEの絶対URL差し替え・日付セルのread-back照合の罠・本番検証用の撤去コマンドまで。

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

ゼロから開発すると約6.2万トークンかかりますが、この巻物を使えば約9,000トークンで済みます。差し引き約5.3万トークン(API料金換算で約80円)・85%の節約です。

どうやって使いますか?

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

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

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

商用利用できますか?

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

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

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

AI代行堂を見る →

関連する巻物

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

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