実現したいこと
Googleカレンダーから取得したスケジュールをスプレッドシートに入力し、そのシートをもとに一日のスケジュール表を作成しています。
上図のようにカレンダーから取得したデータを、下図のような表に書き込んでいくGASスクリプトを作っています。
スケジュール開始時間とスケジュール表の時間軸を比較し、該当する時間帯の行に詳細を追加していきたいです。自力で組んだスクリプトでも一応正常に動くのですが、速度やデータ量の面でもっと効率よく動かしたいため書き直しています。修正前のコードはあまりにも長く非効率なのでいったん割愛させていただきます補足しました。
発生している問題・分からないこと
API呼出回数の削減のため、getValue、setValueの数を減らして書いたコードです。
[j][0] <= 開始時刻 < [k][0] で条件指定してインデックス番号から該当する時間帯を特定したところまでは良いのですが、[j][1]と[j][2]にあたるセルをどう定義すればよいのかが分かりません。
var eventRange = sheet.getRange('displayTime[j][1]:displayTime[j][2]');
と入れてあります(もちろん範囲が見つからずエラーを吐きます)が、このように変数j,kあるいは新たに定義した変数を使用して範囲を取得することは可能でしょうか?
該当のソースコード
GAS
1function settingmacroTest() { 2 3 var sheet = SpreadsheetApp.getActiveSpreadsheet(); 4 5 //元データ(Googleカレンダーから取得したイベントデータの配列) 6 var datasheet = sheet.getSheetByName('Input'); 7 //データの抽出先となるシート(スケジュール表) 8 var mainsheet = sheet.getSheetByName('main'); 9 10 //元データ全体[スケジュール名, URL, 開始時刻]を配列に格納 11 var allEventData = datasheet.getRange('A2:C').getValues(); 12 //書き込む要素[スケジュール名, URL]のみを配列に格納 13 var eventData = datasheet.getRange('A2:B').getValues(); 14 //スケジュール表の時間軸+書き込みたい範囲を配列に格納 15 var displayTime = mainsheet.getRange('C7:E51').getValues(); 16 17 18 //時間軸と変数を使って、[開始時刻]が[HH:MM]から[HH:MM]の間にあるときに該当の行へsetValuesしたい 19 for(var i = 0; i <= allEventData.length; i++){ 20 //実際に書き込むデータを二次元配列で取得 21 var event = eventData[i]; 22 23 for(var j = 0, k = 2; j <= displayTime.length - 2, k <= displayTime.length; j+=2, k+=2){ 24 //書き込むスケジュールの開始時刻 25 var starttime = allEventData[i][2]; 26 //比較で使う時間軸その1 27 var timeJ = displayTime[j][0]; 28 //比較で使う時間軸その2 29 var timeK = displayTime[k][0]; 30 31 //問題の箇所 書き込むべき範囲、すなわちtimeJと同じ行にある隣接2セルを定義したい 32 var eventRange = sheet.getRange('displayTime[j][1]:displayTime[j][2]'); 33 34 //書き込む予定の開始時刻と同じ時間軸の行を条件指定しsetValues 35 if((timeJ <= starttime)&&(starttime < timeK)){ 36 mainsheet.getRange(eventRange).setValues(event); 37 } 38 39 } 40 41 } 42 43}
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
時間軸のところのfor文を下記のようにシートの行番号/列番号に置き換えてみたりもしたのですが、配列に格納してあるのでなるべくこの書き方は避けたいと思っています。
for(var j = 7, k = 9; j <= 49, k <= 51; j+=2, k+=2){ var starttime = allEventData[i][2]; var timeJ = mainsheet.getRange(j,3).getValue(); var timeK = mainsheet.getRange(k,3).getValue(); if((timeJ <= starttime)&&(starttime < timeK)){ mainsheet.getRange(j,4).setValue(event); } }
補足
修正前のスクリプトについて、冒頭では割愛しておりましたがざっくりと補足させていただきます。
修正前
・記入するスケジュール名、URLをそれぞれ別で定義していた
・timeJ, timeKをループのたびにgetRange,getValueで取得していた
・j,kは行番号、列番号
・書き込む範囲はD列のj行目、E列のj行目をgetRangeしていた
現段階での修正点
前提:API呼出回数を削減する
・スケジュール名、URLはまとめて配列に格納
・j,kはインデックス番号
・書き込む範囲は配列displayTime[j][1],[j][2]