皆さんこんにちは。
以前、Google Apps Scriptで1000行近くあるスケジュール表から自分のタスクだけをとってくるスクリプトを作っていたのですが、
最初に完成したときは、実行するのに60秒以上かかってしまいました。。
ですが、これから紹介する3つのポイントを意識することで、4~5秒まで速くすることができます。 その方法を紹介しますね。
getValue() は使わず、getValues() を使う
最も有名でかつ最も効果的な方法は、値を取得するときにgetValues()
を使うということ。
getValue()
はひとつのセルの値を取得するのに対し、getValues()
はRange
から配列形式で値を取りにいきます。
例えば、A1~A1000までの値を取りたい場合、
1 2 3 4 5 6 7 8 9 | function get() { var ss = SpreadsheetApp.getActiveSpreadsheet(); var sheet = ss.getActiveSheet(); //セルA1:A1000を取得 var range = sheet.getRange(1, 1, 1, 1000); for (var i = 1;i <= range.length; i+=1) { Logger.log(range.getCell(1, i).getValue()); } } |
とするよりも、
1 2 3 4 5 6 7 8 9 10 | function get() { var ss = SpreadsheetApp.getActiveSpreadsheet(); var sheet = ss.getActiveSheet(); //セルA1:A1000を取得 var rang3 = sheet.getRange(1, 1, 1, 1000); var range = rang3.getValues(); for (var i = 0;i < range.length; i+=1) { Logger.log(range[0][i]); } } |
とした方が圧倒的に速いです。
ループするたびにオブジェクトを取ってくるのではなく、一度全部取ってきてからループした方がいいですね。
ただし二次元配列なので値にアクセスする時はrange[0][index]
としてください。
for文の書き方に注意
for
文を使うときの条件式にも気をつけてください。
以下のように、変数に入れられるものは可能な限り入れておいたほうが速いです。 Range
のキーの数をキャッシュさせています。
1 2 3 4 5 6 7 8 9 10 | function get() { var ss = SpreadsheetApp.getActiveSpreadsheet(); var sheet = ss.getActiveSheet(); //セルA1:A1000を取得 var rang3 = sheet.getRange(1, 1, 1, 1000); var range = rang3.getValues(); for (var i = 1, len = range.length;i <= len; i+=1) { Logger.log(range[0][i]); } } |
また、ここには書いていませんが、break
できるものは可能な限りbreak
することでループ回数も減らせます。
文字列の判定に正規表現を使わない
スクレイピングにおいて、文字列のマッチ判定は欠かせないと思いますが、できるだけ正規表現は使わない方が速いです。
特に日本語も混じっていると判定に時間がかかります。
代わりに、等しいかどうか ==
で判定したり、getFontSizes()
や getFontColors()
などフォントのスタイルで判定することで、時間が短縮できます。
最後に
結果、速度が1/10まで改善できました。
GASのみならず、クライアントで動作するスクリプトには応用できると思いますので、意識してみてはどうでしょうか。