導入
ある日、Google Apps Scriptでスプレッドシートにアクセスできるかどうかを判定する処理を作りたかったが、これがまた地味に沼って1時間ほど溶かしたので備忘録です。
ちなみに単にアクセス権限があるかどうかを判定する関数は多分ないです。あったら教えてほしい。
なのでここでは、スプレッドシートを開く部分をtry-catchで処理する方法を述べます。
なお今回はGoogle Apps Scriptはwebappの環境です。
appsscript.jsonを見ての通り、この記事のコードを動かすにはスプレッドシートとドライブのoauthScopesを必要とします。
{
"timeZone": "Asia/Tokyo",
"dependencies": {},
"webapp": {
"access": "ANYONE",
"executeAs": "USER_ACCESSING"
},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8",
"oauthScopes": [
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/drive"
]
}
try-catchを貫通した…だと?
アクセス権限がないスプレッドシートを開こうとするとエラーが出ます。なのでtry-catchすればアクセス権限がない場合は異なる処理をする、みたいなことができると思っていました。(当然ですよね)
しかし面白いことに、次のコードのようにtry-catchするとcatchブロックは実行されずに異常終了します。は?
// このidで定められるスプレッドシートへのアクセス権限がないとする
const id = "........"
try {
const sp = SpreadsheetApp.openById(id)
} catch (error){
// ここが実行されるはずだが、実行されない。
Logger.log('アクセスできないよ')
}
でこの現象、どうやら2016年の時点で類似のバグが報告されています。こちらはスプレッドシートで保護されたセルに書き込もうとした時に、try-catchできないというものですが、状況としてはほとんど同じです。
try-catchしてくれるコード
じゃあどうしろってんだって話ですが、少なくともスプレッドシートのopenについては、次のコードに変更することでtry-catchできることがわかりました。
// アクセス権限がないスプレッドシートのID
const id = "........"
try {
const sp = SpreadsheetApp.open(DriveApp.getFileById(id))
} catch (error){
// ここが実行される
Logger.log('アクセスできないよ')
}
参考↓
どうやらDriveApp.getFileById
などのDriveApp
からファイルを取得するようにすると、DriveApp
のメソッドから例外が送出され、正しく処理されるようです。は?なんで?