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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Q&A

解決済

2回答

1503閲覧

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

_af28_

総合スコア18

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

0グッド

0クリップ

投稿2018/10/15 01:54

編集2018/10/15 03:43

※最終的にやりたいことを追記いたしました
ーーーーー
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); }

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

papinianus

2018/10/15 02:17

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

2018/10/15 03:45

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

回答2

0

ベストアンサー

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

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

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

javascript

1fuction manual_run() { 2 var res = set_availability(["あなたの@アドレス"]); 3 Logger.log(res); 4} 5 6function set_availability(calendarids){ //calendaridsはカレンダidの配列を渡す。2人でなくてもよいようにはしているが、時間がかかりすぎる問題がある。 7 8 //idをGoogle カレンダーの配列にする 9 const calendars = calendarids.map(function(element, index, array) { 10 return CalendarApp.getCalendarById(element); 11 }); 12 13 //候補の日付の配列を取る 14 const spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); 15 const availability_spreadsheet = spreadsheet.getSheetByName('SS'); 16 const full = availability_spreadsheet.getDataRange().getValues(); 17 const schedules = full.slice(2).map(function(element, index, array) { //3行目からA列に日付が入っている仕様のはず 18 return element[0]; 19 }); 20 21 //候補の日付の配列から、予定がない日付をフィルタして返す 22 return schedules.filter(function(time, index, array) { 23 return calendars.every(function(cal, ind, arr) { 24 const st = new Date(time); 25 var ed = new Date(time); 26 ed.setMinutes(st.getMinutes() + 30); 27 return cal.getEvents(st, ed).length === 0; 28 }) 29 }); 30}

投稿2018/10/15 05:38

編集2018/10/15 07:31
papinianus

総合スコア12705

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

papinianus

2018/10/15 05:39

underscoreには依存していません(underscoreなしでも動きます)。自分の予定だけではありますが、動作することを確認済。
_af28_

2018/10/15 06:54

ご提案ありがとうございます! var datetimes = set_availability(["some@example.com","other@example.com"]) 上記に自分のアドレスを設定し、動かすと下記エラーが出るのですが、何か考えられる設定不備ございますでしょうか TypeError: undefined のメソッド「map」を呼び出せません。
papinianus

2018/10/15 07:32 編集

関数実行から試してますよね。テストの仕方を追記します。 →追記しました。関数を実行から、「manual_run」を実行してください。もちろん"あなたの@アドレス"を正しくしてからですが。
_af28_

2018/10/15 09:15

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

2018/10/16 01:18

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

2018/10/16 01:30

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

0

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

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

javascript

1function set_availability(sheet, column, id){ 2 3//時間の記載されているSS 4 var spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); 5 var availability_spreadsheet = spreadsheet.getSheetByName('SS'); 6 7 var calendar_id = "アドレス1"; 8 var calendar_id2 = "アドレス2"; 9 10 var last_row = availability_spreadsheet.getLastRow() 11 var calendar_info = CalendarApp.getCalendarById(calendar_id); 12 var calendar_info2 = CalendarApp.getCalendarById(calendar_id2); 13 14 //ステータス列の判定 15 var array_data1=[]; 16 var array_data2=[]; 17 18 for(var i = 3; i <= last_row; i++){ 19 20 //SS3行目から30分ごとに時間が記載されています 21 var start_date_base = availability_spreadsheet.getRange(i, 1).getValue(); 22 var start_date_tmp = new Date(start_date_base); 23 var end_date_tmp = start_date_tmp.setMinutes(start_date_tmp.getMinutes()+30); 24 var start_date = new Date(start_date_base); 25 var end_date = new Date(end_date_tmp); 26 27 var myEvents= calendar_info.getEvents(start_date, end_date); 28 29 var myEvents2= calendar_info2.getEvents(start_date, end_date); 30 31//予定がなかったら格納 32 if (myEvents.length == 0){ 33 var start_date_in = Utilities.formatDate(start_date , "Asia/Tokyo", "yyyy/MM/dd HH:mm"); 34 array_data1.push(start_date_in); 35 } 36 37//予定がなかったら格納 38 if (myEvents2.length == 0){ 39 var start_date_in = Utilities.formatDate(start_date , "Asia/Tokyo", "yyyy/MM/dd HH:mm"); 40 array_data2.push(start_date_in); 41 } 42 43 } 44 45 var _ =Underscore.load(); 46 var array_data = _.intersection(array_data1, array_data2); 47 48 Logger.log(array_data); 49 50 }

投稿2018/10/15 02:14

papinianus

総合スコア12705

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問