【Google Apps Script】onOpen時に「Spreadsheet.openByIdを呼び出す権限がありません」となり、メニューが追加されない

Code

はじまり

リサちゃん
リサちゃん

はっ?

なんで、いつも通りスプレッドシートを開いて
onOpenでメニューが追加されないの!?

135ml
135ml

ああ〜、それは権限のエラーが出てるかもしれない・・・

リサちゃん
リサちゃん

権限?

135ml
135ml

じゃあ、今回はそのことについて触れてみよう

事象

今回、直面したエラーはこんな感じのものです。

HtmlService()を使って、スプレッドシートを開いた時にメニューが表示されるかと思いきや、全く表示されてこない・・・

スクリプト編集画面で、こんな感じにGoogle Workspaceのサービスを叩いてみてもダメ・・・。

function authGoogleWorkspace(){
  let ss = SpreadsheetApp.getActiveSheet();
  let drive = DriveApp.getRootFolder();
  let fetch = UrlFetchApp.fetch("https://www.google.com/?hl=ja");
}

原因

本当に意味がわからない!!

そう悩んでいた時にこの記事を発見。

[GAS] 実行する権限がありません。についての対策まとめ - Qiita
Google Apps Scriptでシンプルトリガーを使用したときに実行できない関数がありますが、それについて調べたことまとめです。自分が使いたかったのは他のスプレッドシートを開く Sprea…

どうやら、onOpenやonEditなどの自動実行トリガーは権限が最低らしい。士農工商で言ったら、えた・ひにんだ。

なので、少し強い権限が必要な機能を利用するためには、onOpenではないトリガーからスクリプトを実行しなければならないっぽい。

まあ、僕が初めてこの事象と遭遇したのは、onOpenで使用するアプリ上でSpreadsheetApp.openById()を使ったからなのですが、onOpenで実際に実行される処理内でSpreadsheetApp.openById()が実行されているかどうかは関係なさそう。

僕の場合は、SpreadsheetApp.openById()がonOpenと関係ない関数に入っているだけでちゃんと動きませんでした。

なので、SpreadsheetApp.openById()を使うアプリでは、onOpenはトリガーを作成する処理だけを入れようと思ったわけです。

調査

僕は、onOpen関数に以下のような処理を入れました。

onOpenでエラーになるので、そしたらonEditイベントハンドラを追加。そのonEditイベントでイベントハンドラを削除。(まあ、onEditもSimple Triggerなので権限弱そうだけど・・・)

function onOpen(){
  try{
    let ui = SpreadsheetApp.getUi();
    const statement = ui.prompt(message).getResponseText();

    let menuName = "フォルダ作成処理";
    let objActions = [
      {name: "作業ページ一覧表示処理", functionName: "displayListOfPagesToWork"}
      , {name: "Display Thumbnails.", functionName: "displayThumbnails"}
    ];

    // これがメニューを追加する関数。
    onOpenToAddSpreadsheetMenu(menuName, objActions);

  }catch(e){
    SpreadsheetApp.getUi().alert("onOpen failed. " + e);
    // Browser.msgBox("onOpen failed. " + e);
    createTrigger();
  }
}

function createTrigger(){
  let sheet = SpreadsheetApp.getActiveSpreadsheet();
  try{
    ScriptApp.newTrigger("doOnOpen")
    .forSpreadsheet(sheet)
    .onEdit()
    .create();
  }catch(e){
    SpreadsheetApp.getUi().alert("Initialization failed. " + e);
  }
}

function doOnOpen(){
  onOpen();
  let triggers = ScriptApp.getProjectTriggers();
  for(let i = 0; i < triggers.length; i++){
    if(triggers[i].getEventType() === ScriptApp.EventType.ON_EDIT){
      ScriptApp.deleteTrigger(triggers[i]);
    }
  }
}

そして、結果的には失敗。

トリガーは追加されていませんでした。

次に、まずスクリプトが実行されているかどうかを検証。

スクリプトが走るなら、スプレッドシートを開いた時にダイアログが表示されるはず。

function onOpen(){
  try{
    // この2行を追加。
    let ui = SpreadsheetApp.getUi();
    const statement = ui.prompt(message).getResponseText();

    let menuName = "フォルダ作成処理";
    let objActions = [
      {name: "作業ページ一覧表示処理", functionName: "displayListOfPagesToWork"}
      , {name: "Display Thumbnails.", functionName: "displayThumbnails"}
    ];
    onOpenToAddSpreadsheetMenu(menuName, objActions);
  }catch(e){
    SpreadsheetApp.getUi().alert("onOpen failed. " + e);
    createTrigger();
  }
}

実行してみると、ダイアログは表示されませんでした・・・

僕が遭遇しているSpreadsheetApp.openById()の権限エラーは、自作の別ライブラリにある処理で引っかかっているようなので、そこの静的解析中にエラーになっているのかもしれない。

一応、解決

なので、スクリプト自体が実行されていないとなると、

  • アプリのコンソール画面内でトリガー設定をするか
  • スプレッドシートの中にスクリプトを実行するボタンを作るか

この2つしか方法はなさそうだったので、後者のボタンを設置する方法にしました。

やむを得ませんでした・・・無念・・・(まあ、こんな不具合に何時間も使ってられません。)

onOpen関数をinitialize関数に名前を変更して、ボタンに割り当てました。

initialize()を実行することで、自作のメニューは追加されるようになりました。

おしまい

リサちゃん
リサちゃん

良かった・・・なんとかメニューが追加された・・・

135ml
135ml

機能ごとに必要な権限が違うとは思わなかったね・・・

リサちゃん
リサちゃん

知ったこっちゃない!

以上になります!

コメント

タイトルとURLをコピーしました