Google Apps Scriptの「保護されたセルまたはオブジェクト」エラーを修正する方法

intermediate📗 Google Sheets2026-07-23| Google Apps Script, Google Sheets (すべてのオペレーティングシステム)

Error Message

Exception: You are trying to edit a protected cell or object. Please use the Sheets API to edit protected ranges.
#apps-script#保護された範囲#google-sheets#権限#sheets-api

エラーメッセージ

スクリプトが保護(ロック)された範囲に対して setValue()setValues()、または clear() を実行しようとすると、このエラーが発生する可能性が高くなります。エラーは以下のように表示されます。

Exception: You are trying to edit a protected cell or object. Please use the Sheets API to edit protected ranges.

スクリプトが失敗する理由

原因は権限にあります。たとえあなたがスプレッドシートのオーナーであっても、Google Apps Scriptは現在コードを実行しているユーザーに基づいて「保護された範囲」の設定を尊重します。操作しているユーザーがセル A1:C10 に対して手動での編集権限を持っていない場合、スクリプトもその権限を持つことはできません。

通常、以下の3つのパターンのいずれかで発生します。

  • シンプルトリガー: onEdit(e) を使用している場合です。これらのトリガーは常に実行中のユーザーとして動作します。ゲストや制限された編集者がスクリプトを実行すると、保護されたセルに触れた瞬間にエラーが発生します。
  • カスタムボタン: ユーザーがボタンをクリックして関数を実行する場合です。スクリプトはそのユーザーのアカウントで実行されます。ユーザーがそのセルに入力できなければ、スクリプトも書き込むことができません。
  • 共有ライブラリ: 中央ライブラリから関数を呼び出してシートを更新しようとしているが、その特定のシートの保護設定でユーザーに明示的な権限が与えられていない場合です。

解決方法

方法 1: インストール可能トリガーを使用する(最も簡単な解決策)

インストール可能トリガーは、シートを編集した人ではなく、トリガーを作成した人の権限で実行されるため、強力な回避策となります。開発者であるあなたに保護された範囲へのアクセス権があれば、他のすべてのユーザーに対してもスクリプトは正常に動作します。

  • Apps Script プロジェクトを開きます。
  • 左側のサイドバーにあるトリガーアイコン(時計のマーク)をクリックします。
  • 右下の + トリガーを追加 をクリックします。
  • 実行したい関数(例: onFormSubmit)を選択します。
  • イベントのソースをスプレッドシートからに設定します。
  • イベントの種類を編集時またはフォーム送信時に設定します。
  • 保存してスクリプトを承認します。これで、あなたの昇格された権限で実行されるようになります。

方法 2: Sheets API を使用する(プロフェッショナルな方法)

Googleのエラーメッセージでは、Sheets APIの使用が明示的に推奨されています。この「拡張サービス」は、制限された範囲を扱う際により堅牢に動作することが多いです。特に、500行のインポートなど、標準的なコマンドでは遅延や失敗が発生する可能性がある大規模なデータセットを更新する場合に便利です。

  • Apps Script エディタで、サービスの横にある + をクリックします。
  • Google Sheets API を選択して 追加 をクリックします。
  • SpreadsheetApp の代わりに Sheets サービスを使用するようにコードを更新します。
// このバージョンは標準的なUI制限をバイパスします
function updateProtectedRange() {
  const ssId = SpreadsheetApp.getActive().getId();
  const range = "Sheet1!A1"; 
  const valueRange = {
    values: [["Updated via API"]]
  };
  
  Sheets.Spreadsheets.Values.update(valueRange, ssId, range, {
    valueInputOption: "USER_ENTERED"
  });
}

方法 3: 「ロック解除・書き込み・再ロック」パターン

スクリプトがオーナーレベルのアクセス権を持っている場合、一時的に保護を解除して更新を行い、その後にロックを再設定することができます。これは、自動化されたメンテナンス作業でよく使われるパターンです。

function writeToProtectedRange() {
  const sheet = SpreadsheetApp.getActive().getSheetByName("Data");
  const range = sheet.getRange("A1:B10");
  
  // 既存の保護設定を特定する
  const protections = sheet.getProtections(SpreadsheetApp.ProtectionType.RANGE);
  let myProtection = protections.find(p => p.getRange().getA1Notation() == "A1:B10");

  // 一時的にロックを解除する
  if (myProtection) {
    myProtection.remove();
  }

  // 編集を実行する
  range.setValue("Success");

  // すぐに保護を再適用する
  const newProtection = range.protect().setDescription("Restored by Script");
  newProtection.removeEditors(newProtection.getEditors()); 
  newProtection.addEditor("admin@example.com");
}

修正の確認

スクリプトを過信せず、正常に動作することを確認するために、制限されたユーザーとしてテストする必要があります。

  • テスト用の別のアカウントでシートを開きます。
  • そのテストアカウントが、対象の範囲を手動で編集できない(ブロックされている)ことを確認します。
  • スクリプトを実行します(ボタンをクリックするか、セルを編集します)。
  • セルが更新され、エラーが表示されなければ、権限のギャップは解消されています。

予防のためのヒント

チームが大きくなるにつれて、Google スプレッドシートの権限管理は複雑になりがちです。ウェブサーバーを管理している方なら、ファイル権限の扱いがいかに厄介かをご存知でしょう。私は chmod のロジックを視覚化するために、よく Unix Permissions Calculator を使用します。スプレッドシートはビジュアルなUIを使用していますが、「オーナー」対「編集者」という概念は非常によく似ています。

将来的にこうしたトラブルを避けるために、以下の点に注意してください。

  • ロックされたシートで複数のユーザーがスクリプトを実行する必要がある場合は、インストール可能トリガーを使用するようにしてください。
  • ユーザーが少なくともファイルへの「編集者」権限を持っているか確認してください。スクリプトは、「自分」として実行されるウェブアプリとしてデプロイされない限り、「閲覧のみ」の制限をバイパスすることはできません。
  • コード内での意図しない重複を避けるために、どの範囲が保護されているかのログを記録しておきましょう。

Related Error Notes