質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.03%

複数人のカレンダーから予定有無の情報を取得し、予定がない時間のみログに出したい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,030

_af28_

score 12

※最終的にやりたいことを追記いたしました
ーーーーー
Google Apps Scriptで複数人のカレンダーから予定有無の情報を取得し、
予定がない時間のみログに書きだそうとしています。

目的はGoogleカレンダー上でイベント登録する際に、
複数のゲストの空き時間を確認するのが大変なので、
最初から複数ゲスト全員が空いている時間だけをピックアップし、
スクリプト上で実装したウェブアプリケーションでプルダウンで表示させ、
選択された日付にcreateEventさせようとしています。

エラーは出ず実行できるのですが、求めているログ結果となりません。
配列に格納していって、_.intersectionで重複分だけを表示させようとしています。
(ライブラリにUnderscore追加済み)

何か良い方法をご教示いただけると幸いです…
(Google検索で集めた情報で作ったレベルであること重々承知です…)

function set_availability(sheet, column, id){

//時間の記載されているSS
 var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
 var availability_spreadsheet = spreadsheet.getSheetByName('SS');

  var calendar_id = "アドレス1";
  var calendar_id2 = "アドレス2";

  var last_row = availability_spreadsheet.getLastRow()
  var calendar_info = CalendarApp.getCalendarById(calendar_id);
  var calendar_info2 = CalendarApp.getCalendarById(calendar_id2);

  //ステータス列の判定
  var array_data=[];

  for(var i = 3; i <= last_row; i++){

   //SS3行目から30分ごとに時間が記載されています
    var start_date_base = availability_spreadsheet.getRange(i, 1).getValue();
    var start_date_tmp = new Date(start_date_base);
    var end_date_tmp = start_date_tmp.setMinutes(start_date_tmp.getMinutes()+30);
    var start_date = new Date(start_date_base);
    var end_date = new Date(end_date_tmp);

    var myEvents= calendar_info.getEvents(start_date, end_date);

    var myEvents2= calendar_info2.getEvents(start_date, end_date);

//予定がなかったら格納    
    if (myEvents.length == 0){
      var start_date_in = Utilities.formatDate(start_date , "Asia/Tokyo", "yyyy/MM/dd HH:mm");
      array_data.push(start_date_in);
    }

//予定がなかったら格納    
     if (myEvents2.length == 0){
      var start_date_in = Utilities.formatDate(start_date , "Asia/Tokyo", "yyyy/MM/dd HH:mm");
      array_data.push(start_date_in);
    }

  }

  var _ =Underscore.load();
  var array_data = _.intersection(array_data);

  Logger.log(array_data);

  }
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • papinianus

    2018/10/15 11:17

    最終的には予定がない時間が欲しいのだとすると、intersectionを使っても、のちのち辛いと思うのですが?またログに書いても、スクリプトからしか見えないですし。また2つのカレンダーしかないならintersectionとか回りくどいことしなくていい気もします。やりたいことの全体のロードマップで今どこらへんかを示していただけませんか?

    キャンセル

  • _af28_

    2018/10/15 12:45

    ご指摘ありがとうございます。最終的にやりたいことを追記いたしました。別でウェブアプリケーションのHTMLは準備しているのですが、プルダウンに表示させるデータの生成に手間取っております…

    キャンセル

回答 2

checkベストアンサー

0

必ずしも質問者様ご本人にとって参考となるかは分かりませんが、試案として。

ただ、質問者様の方法で懸念されるのが、カレンダーの予定を人数と時間の候補分呼び出すので、実行速度がかなり遅くなります。gasはあまりに長い実行をすると、勝手に中断されるので、こういうやり方が適切なのかは、状況によると思います(2人で、半日分とかだったらセーフ?)

var datetimes = set_availability(["some@example.com","other@example.com"])みたいな呼び出しをするとdatetimesにsome@example.comやother@example.comのカレンダーにない日付が配列で返されます(Date型で返されます)。

fuction manual_run() {
  var res = set_availability(["あなたの@アドレス"]);
  Logger.log(res);
}

function set_availability(calendarids){ //calendaridsはカレンダidの配列を渡す。2人でなくてもよいようにはしているが、時間がかかりすぎる問題がある。

  //idをGoogle カレンダーの配列にする
  const calendars = calendarids.map(function(element, index, array) {
      return CalendarApp.getCalendarById(element);
  });

  //候補の日付の配列を取る
  const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  const availability_spreadsheet = spreadsheet.getSheetByName('SS');
  const full = availability_spreadsheet.getDataRange().getValues();
  const schedules = full.slice(2).map(function(element, index, array) { //3行目からA列に日付が入っている仕様のはず
      return element[0];
  });

  //候補の日付の配列から、予定がない日付をフィルタして返す
  return schedules.filter(function(time, index, array) {
      return calendars.every(function(cal, ind, arr) {
        const st = new Date(time);
        var ed = new Date(time);
        ed.setMinutes(st.getMinutes() + 30);
        return cal.getEvents(st, ed).length === 0;
      })
  });
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/15 18:15

    詳細にわかりやすくご対応いただきありがとうございました。無事求めていた答えが出ました…今後投稿することが増えるかと思いますが、ぜひよろしくお願い致します。

    キャンセル

  • 2018/10/16 10:18

    補足しておきます。
    CalendarApp.getCalendarById(element)
    で取得できるカレンダーは
    実行者のGoogleカレンダーの「他のカレンダー」に表示されているカレンダーのみになります。
    G Suiteなどを利用しており、同ドメインでAPI実行で参照可能の場合でも上記に追加しなければ、取得することができません。
    「他のカレンダー」の追加・削除が発生する状況であれば、APIを利用したほうがよいかと思います。
    (必ず追加するなど、変わらないのであれば、特に問題はありません。)

    キャンセル

  • 2018/10/16 10:30

    コメントありがとうございます。
    「他のカレンダー」の追加・削除が発生する状況であれば、APIを利用したほうがよいかと思います。
    ⇒G-suite使用中で、まさにこの問題にぶつかっており、他のカレンダーに毎度追加していたのですが、APIを利用すればできるものなのでしょうか?(無知で恐縮です…)

    キャンセル

0

やりたいことが良く分からない気もしますが、おそらく今のところ問題なのは、_.intersectionの使い方が違うところ。今はログになにもでないのでは?(もしくは全部出る?)

2つの配列の共通を抜きだすので、アドレス1さんのものと、アドレス2さんのものを別々の配列にする必要があります。

function set_availability(sheet, column, id){

//時間の記載されているSS
 var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
 var availability_spreadsheet = spreadsheet.getSheetByName('SS');

  var calendar_id = "アドレス1";
  var calendar_id2 = "アドレス2";

  var last_row = availability_spreadsheet.getLastRow()
  var calendar_info = CalendarApp.getCalendarById(calendar_id);
  var calendar_info2 = CalendarApp.getCalendarById(calendar_id2);

  //ステータス列の判定
  var array_data1=[];
  var array_data2=[];

  for(var i = 3; i <= last_row; i++){

   //SS3行目から30分ごとに時間が記載されています
    var start_date_base = availability_spreadsheet.getRange(i, 1).getValue();
    var start_date_tmp = new Date(start_date_base);
    var end_date_tmp = start_date_tmp.setMinutes(start_date_tmp.getMinutes()+30);
    var start_date = new Date(start_date_base);
    var end_date = new Date(end_date_tmp);

    var myEvents= calendar_info.getEvents(start_date, end_date);

    var myEvents2= calendar_info2.getEvents(start_date, end_date);

//予定がなかったら格納    
    if (myEvents.length == 0){
      var start_date_in = Utilities.formatDate(start_date , "Asia/Tokyo", "yyyy/MM/dd HH:mm");
      array_data1.push(start_date_in);
    }

//予定がなかったら格納    
     if (myEvents2.length == 0){
      var start_date_in = Utilities.formatDate(start_date , "Asia/Tokyo", "yyyy/MM/dd HH:mm");
      array_data2.push(start_date_in);
    }

  }

  var _ =Underscore.load();
  var array_data = _.intersection(array_data1, array_data2);

  Logger.log(array_data);

  }

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.03%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる