そういうのをやりたかったが、無限に「このトリガーは無効になりました。原因は不明です。」とかいうのが出るんですよねこれが
ググった
- V8ランタイムのバグ
- V8オフにするといける
- あるいは実行権限廻りのバグ?
- Webアプリケーションとしてデプロイして、アプリ内から呼べばV8でもいける
なるほど、素晴らしい!V8ランタイムをオフにするのは嫌なので、Webアプリケーションからの起動を試してみよう!
ここではミニマムで、とりあえず『1分おきにA1のセルが時刻で変更される』ということにしてみる。
何はともあれまずは適当なSpreadSheetのコンテナバインドスクリプトを作成し、設定からV8とappscript.jsonをオンにする。
んで以下のコード。ES6以降の構文をガンガン使っていこう
appscript.json
{ "timeZone": "Asia/Tokyo", "dependencies": {}, "exceptionLogging": "STACKDRIVER", "runtimeVersion": "V8", "webapp": { "executeAs": "USER_DEPLOYING", "access": "MYSELF" } }
code.gs
/** * V8でtriggerをスクリプト内部で作成してtimebasedする * 一度webアプリとしてデプロイする必要があるし、そのデプロイの中で実行する必要がある * これは初回だけ起動すればいいやつ * (あとからデプロイを取り消してもそのまま動き続けた。ただしあとから追加した処理は当然動かなかった) */ const SS = SpreadsheetApp.getActive(); const triggers = ScriptApp.getScriptTriggers(); const triggerName = "minituesOnTime"; /** * 1分ごとに現在の時間でA1を書き換えるだけ */ function minituesOnTime() { console.log("--- START---"); const sheet = SS.getActiveSheet(); /** * 関数名を決め打ちで消す箇所 */ for(let trigger of triggers){ if(trigger.getHandlerFunction() === triggerName){ ScriptApp.deleteTrigger(trigger); } } const now = new Date(); const time = Utilities.formatDate(now, "Asia/Tokyo", "HH時mm分ss秒"); console.log(`now ${time}`); const range = sheet.getRange(1, 1); // どこでもいいけどな range.setValue(time); const next = new Date(Utilities.formatDate(now, "Asia/Tokyo", "yyyy/MM/dd HH:mm")); next.setMinutes(next.getMinutes()+1); // 1分後にセット console.log(`next: ${next}`); ScriptApp.newTrigger(triggerName).timeBased().at(next).create(); } /** * ちゃんとhtml返さないと動かなかった */ function doGet(){ console.log("WELCOME HTML"); const html = HtmlService.createTemplateFromFile("index"); return html.evaluate(); }
index.html
<!DOCTYPE html> <html> <head> <base target="_top"> </head> <body> <div id="content"></div> <?!= HtmlService.createHtmlOutputFromFile("js").getContent(); ?> </body> </html>
js.html
<script> const content = document.getElementById("content"); const element = document.createElement("div"); element.id = "base"; element.style.opacity = "0.3"; element.textContent = "LETS GO....""; content.appendChild(element); // HTMLからGASの関数を叩く google.script.run.withSuccessHandler(() => { element.style.opacity = "1"; element.textContent = "処理が完了しました"; }).withFailureHandler((err)=>{ element.textContent = "SOMETHING ERROR!!!"; alert(`エラー:やり直してください ${err}`); }).minituesOnTime(); </script>
Webアプリとしてデプロイしてアクセス
アクセスするタイミングではうまくトリガーがセットされないことがある(秒数がゼロなせい?)のでそのときはもっかいどうぞ
これでSpreadSheetが時間ベースのトリガーでいじれるようになりました。やったね!以下はログ。
コード内のコメントにも書いてあるけど、一度デプロイしたらそのデプロイを削除しても動き続いた。デプロイしたあとマニュアルでコードから実行するとどうなるかは試してないのでわからない。