Ateam Hikkoshi Samurai Inc. Advent Calendar 2017 19日目です。
本日はエイチーム引越し侍中途入社2年目、自称爆速Webエンジニアの加藤が担当します!
みなさんGoogle Apps Script書いていますか?
めっちゃ便利だよねー!エクセルの上位互換じゃない?って人が見がちな地獄のような罠を
実体験を用いつつ、いくつかご紹介します。
これからやってみよー!って人も必読の内容となっております。
タイトルの意味は僕の敬愛する@keki さんから
『この仕事なんだけどあと2日くらいで終わるから引き継いでくれない?』
って言われて着手したんですが、実質10日以上かかって、『くそが!!!!』って思ったので
みなさんがGoogle Apps Scriptの鬼畜とも呼べる罠に引っかかって欲しくないなぁという気持ちです。
※くそが!ってのは@kekiさんに対してじゃないですよ。えぇ決して。
罠一覧
- セル、シートの読み書き、操作は絶対動くと思うなかれ
- セル、シートの読み書き、操作をfor文とかで繰り返しちゃだめ
- すべてのトリガー
- 社内システムのプライベートなAPIを呼び出したい
- Google「そんなに長い時間動かしていいと思ってんの?」
- Google「いっけね!GAの集計してなかった!」
- Google「すまんな!エラーが発生したからしばらくしたら再読み込みしてくれよな!」【超絶鬼畜】
1 セル、シートの読み書き、操作は絶対動くと思うなかれ
Google Apps Scriptで実現したいことで、セルやシートの操作がまったくないよーなんてことは無いと思うんですが、
セルやシートを操作する関数はAPIで実現されています。
なので普通にこけたりして以下のメールが飛んできます。
初めは社内共通のアカウントでトリガーを設定していたため全然気づけなくて地獄でした。
デイリーの集計を毎日昨日分取るようなプログラムを作っていたので、
休みはさんで月曜出社したときにこれが来てたらかなりテンションさがってました。
過去分を取れるように作り直すのにほぼ3日かかりました…
みなさんは初めから過去にさかのぼって集計できるように作ってくださいね!
2. セル、シートの読み書き、操作をfor文とかで繰り返しちゃだめ
1の内容ともかぶるんですが、セルやシートを操作する関数はAPIで実現されています。
なのでめっちゃくちゃ遅いです。しかも1の内容で書きましたが、こけるのでこける確率が高くなります。
https://tonari-it.com/gas-spreadsheet-speedup/
こちらの記事がとても参考になりますが、要はA1:A100の範囲の中で検索かけよーって思って
for (var i = 0; i < 100; i++) {
sheet.getRange("A" + i).getValue();
}
ってやるとバカ遅いです。この遅さは後述の5の項目で致命的になったりするので、
こんな感じで一旦その範囲のセルの値を全部取得して、その中で検索しましょう。
var values = sheet.getRange("A1:A100").getValues();
for (var i = 0; i < 100; i++) {
values[i][0];
}
このリファクタリングで1日追加…
3. すべてのトリガー
こいつが曲者です。なんでこんなんここに用意するんだって思いますが、
現在のプロジェクトのトリガーを選んだつもりがすべてのトリガーを選んでたみたいで
あれ?こんなトリガー設定したっけな?と思って×ボタンから削除しまくって最後に保存しようとしたときに
違う!他のやつも入ってたんか!ってなったのでみなさんもご注意ください。
そんなことやるかよ!って思うかもですが、僕の敬愛する@keki さんもやりかけてたので僕だけじゃないかなと思って。
4. 社内システムのプライベートなAPIを呼び出したい
エクセルでできてたんだからスプレッドシートでも余裕っしょ!
と思われてたところでかなり躓きました。
エクセルでプライベートなAPI叩いてたときは社内IPからのアクセスを許可していたため、なんなく実行できたんですが、
Google Apps Scriptだとそうはいきません。なんせGoogleさんからアクセスが来るんですから。
くっそーどうすればいいんやーと思ってひねり出した苦肉の策がこんな感じです。
// ヘッダーにこれを入れておけばアクセスできるようにしてるので
var headers = {"access_yurusu" : "true"}
var params = {'headers' : headers};
var response = JSON.parse(UrlFetchApp.fetch(API_URL, params).getContentText());
ヘッダーにこの情報を入れておけばアクセスできるようにセキュリティーホールを作ってあげて、いったん乗り切りました。
皆さんヘッダーにいろいろ仕込んでアタックしないでくださいね!実際のキーバリューは複雑ですし、他の方法でさらに認証かけてたりするので絶対みなさんにはクラッキングできませんよ!(震え声)
5. Google「そんなに長い時間動かしていいと思ってんの?」
この罠もなかなかきつかったです。
https://kido0617.github.io/js/2017-02-13-gas-6-minutes/
こちらの記事がとても参考になりますが、要はGoogleAppsScriptの実行上限時間は6分です。
6分を超えると「起動時間の最大値を超えました」とエラーとなり問答無用で強制終了されます。
ちょっと取得するデータ増やしたいんだよねーって言われてそれなら15分もあればできますよ!
って言った自分をぶん殴りたい。ちょっと取得するデータ増やしたら実行時間越えた。
結果的に5分でいったんとめて、処理中のデータを保存し、再度実行したときに先ほどのデータを用いて処理を続行する。
という立派な機能追加により2日くらいテスト込みで工数が伸びました。
6 Google「いっけね!GAの集計してなかった!」
スプレッドシートにアドオンを追加でGoogle Analyticsのデータを取得することができます。
定期的に取得しなおすこともスケジューリングできるんですが、
Googleさんはおちゃめなのでたまに取りそこなったりします。
厳密にはGASのことじゃないかもですが、トリガーの設定した時間までにGAのデータ欲しいよ!ってGASとの連携とのとこでどうしようか迷ったので書いておきます。
昨日までのデータなら1日のうちのいつとっても一緒ですよね!
1日1回がこけてしまったら致命的なので毎時取得してあげればいいですよね!(ゲス顔)
7. Google「すまんな!エラーが発生したからしばらくしたら再読み込みしてくれよな!」【超絶鬼畜】
これが超絶怒涛の鬼畜現象です。もう僕はこの画面を見ただけで即座に家に帰って布団にこもって『もう二度とGASの仕事やらない!うわあああああん!』
って叫びたくなるくらいの鬼畜現象です。
何がきっかけでこれが起きるのかは明確にはわかりませんが、僕は同じ案件をやっている中で2回も同じ現象が起きました。
これ何かって言うと俗に言う『なにもしてないのにファイルが壊れた。』ってやつです。
スプレッドシートにアクセスしたら表示されるため、せっかくスプレッドシートが更新履歴と共にバックアップを用意してくれているのにもろともオジャン。ファイルをコピーしてもダウンロードしてもダメ。
なので、
定期的なバックアップを推奨します。
繰り返します。
定期的なバックアップを推奨します。
ファイルコピーしか方法ないと思いますが、めんどくさくてもやりましょう!
ぼくはまるっと初めからやり直しになって悲しかったです。
Ateam Hikkoshi Samurai Inc. Advent Calendar 2017 19日目いかがでしたでしょうか。
明日はエイチーム引越し侍のイケメン中年、@taka999が にRuby関する記事を書いてくれます。
追伸
株式会社エイチーム引越し侍では、一緒にサイト改善をしてくれるWebエンジニアを募集しています。エイチームグループのエンジニアとして働きたい!という方は是非、以下のリンクから応募してください。
皆様からのご応募、お待ちしております!!