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

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

新規登録して質問してみよう
ただいま回答率
85.45%
Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google フォーム

Google フォームは、 Google社が提供しているアンケートフォーム作成および集計ができる無料のツール。Googleアカウントがあれば利用が可能です。集計データは、スプレッドシートに収集され、データ分析もできます。

Google Apps Script

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

Q&A

解決済

2回答

2056閲覧

Googleカレンダーへの反映させるGASコード

ch-taros164

総合スコア2

Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google フォーム

Google フォームは、 Google社が提供しているアンケートフォーム作成および集計ができる無料のツール。Googleアカウントがあれば利用が可能です。集計データは、スプレッドシートに収集され、データ分析もできます。

Google Apps Script

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

0グッド

0クリップ

投稿2023/04/11 14:07

編集2023/04/12 02:10

実現したいこと

GASでGoogleフォームに入力した予定(シフト)を
フォームを送信したらGoogleカレンダーにも反映させるというものを作りたいです。

エラーが出てしまい実行が成功しません。
どこを直したらいいのか教えてください。

前提

発生している問題・エラーメッセージ

TypeError: Cannot read properties of undefined (reading 'response') gs4

該当のソースコード

イメージ説明function createEvent(e) {
// let [timestamp, date, time1, time2] = e.values;
const items = [];
const itemResponses = e.response.getItemResponses();
for (const itemResponse of itemResponses) {
items.push(itemResponse.getResponse());
}
let [date, time1, time2] = items;
let id = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@group.calendar.google.com';
let calendar = CalendarApp.getCalendarById(id);
let title = xxx薬局;

let hoursS = Number(time1.split(':')[0]);
let minutesS = Number(time1.split(':')[1]);
let hoursE = Number(time2.split(':')[0]);
let minutesE = Number(time2.split(':')[1]);
let startTime = new Date(y, m, d, hoursS, minutesS);
let endTime = new Date(y, m, d, hoursE, minutesE);

▼勤務内容 予約日時:${timestamp} 勤務日: ${date} 開始時間: ${time1} 終了時間: ${time2};

Calendar.createEvent(title, startTime, endTime);
}

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

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

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

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

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

YellowGreen

2023/04/11 21:18

Yahoo!知恵袋 https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12278404932?__ysp=Z2Fz (teratailヘルプより引用) 他のサービスにも質問投稿をしたい(してしまった) ------------------------------------------------------------------ teratailでは、マルチポスト※の推奨はしていません。 やむを得ず複数のサイトに質問を投稿された場合は、質問内容にマルチポストをする理由を書き、他のサイトの投稿へのリンクを貼ってください。 また、解決した際には必ずteratail及びすべての投稿に解決した旨と、どのように解決したかを記載してください。 また、teratail上で誤って同じ質問を複数投稿してしまった場合は、質問の削除リクエストを送ってください。 ※「マルチポスト」とは、同じ内容の文章を複数のQ&Aサイトや掲示板などへ投稿することです。
YellowGreen

2023/04/12 02:38

質問の内容を私の回答を反映したスクリプトに変更してますね。 何か説明はないのでしょうか。 しかも、 TypeError: Cannot read properties of undefined (reading 'response') のエラーの原因を回答でお答えしているのに同じことを繰り返していませんか。
ch-taros164

2023/04/12 02:48

どこを修正すればいいのかわかりません。エラーの意味もわかりません。 教えていただきたいから質問投稿をしているのです。 GAS初心者で理解力が無くてすいません
YellowGreen

2023/04/12 03:13

なお、このスクリプトはフォームの送信をトリガーにして起動するものなので、 エディタから実行すると e の値が undefined なのでエラーになります。 エディタからは、実行できないスクリプトです。 フォーム送信時のトリガーの設定方法は、 「GAS フォーム送信 トリガー設定」 などでGoogle検索してみてください。
YellowGreen

2023/04/12 03:23

GAS初心者からのご質問だと判断できなかった私が未熟でした。 申し訳ありませんでした。
ch-taros164

2023/04/12 04:02

ReferenceError: items is not defined at createEvent(シフト入力:9:41) 次はこのエラーが出ました、、 何度もすみません。
YellowGreen

2023/04/12 04:05

const items = []; の行を消してしまってませんか?
ch-taros164

2023/04/12 04:22

その行でした!ありがとうございました!!
ch-taros164

2023/04/12 05:09

ログの取得遅延の対処法は何かありますか??
YellowGreen

2023/04/12 05:16

フォームではなく、回答先のスプレッドシートから同じようにフォーム送信をトリガーにスクリプトを起動するようにして、 そのスクリプトで、トリガー起動時に最終行の回答の値を取得してその各列の値(インデックスで判断)から日付と時刻を取り出して 日時を生成してカレンダーに登録という処理になります。
ch-taros164

2023/04/12 05:43

かなりのタイムラグがかかるということですか?
YellowGreen

2023/04/12 05:45

原因はわかりませんが、何度か値の取得に失敗してメールの送信やカレンダーへの反映などの処理が漏れてしまうことがありました。 今回もカレンダーに登録されないことがあり、先に記載のエラーが発生していました。
YellowGreen

2023/04/12 06:03 編集

> かなりのタイムラグがかかるということですか? タイムラグではなく、もう一度回答しないとその時の回答はカレンダーに反映されなくなるということです。
ch-taros164

2023/04/12 06:07

かしこまりました、、 ありがとうございます。
guest

回答2

0

参考までに、フォームの回答先のスプレッドシートに保存して、トリガー起動する方のスクリプトをアップしておきます。
コードのコメントにも書きましたが、こちらはエディタから実行することができます。
実行すると既に蓄積されている回答の最終行の値からカレンダーの予定を作成します。

js

1//フォームの回答からカレンダーの予定を作成 2//スプレッドシートに保存してトリガー起動 3//こちらをトリガー設定するときは、フォームのトリガーを削除 4//エディタから実行すると最終行の値でカレンダーを作成 5function createEvent() {//eは不要 6 const name = 'フォームの回答 1';//回答が蓄積されるシート名をコピペ 7 const ss = SpreadsheetApp.getActiveSpreadsheet(); 8 const sheet = ss.getActiveSheet(); 9 if (sheet.getName() == name) {//トリガー起動したシート名が一致 10 const values = sheet.getRange(sheet.getLastRow(), 1, 1, sheet.getLastColumn()) 11 .getDisplayValues()//画面表示の値を文字列として取得 12 .flat();//一次元配列に変換 13 const date = values[1];//B列 14 const time1 = values[2];//C列 15 const time2 = values[3];//D列 16 const startTime = new Date(date + ' ' + time1); 17 const endTime = new Date(date + ' ' + time2); 18 const title = '×××薬局'; 19 const calendar = CalendarApp.getCalendarById('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); 20 calendar.createEvent(title, startTime, endTime); 21 } 22}

投稿2023/04/12 09:15

YellowGreen

総合スコア731

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

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

0

ベストアンサー

--<2回目の回答>--

当初提示いただいたスクリプトは、勤務日に'年'や'月'が含まれている記述式の回答を前提としていましたが、
追加していただいた画像にあるように、日付、時刻として回答を得ているということですね。

そうであれば、もう少し簡単になります。
まず、重ねて発生しているエラーを防止するために、
スクリプトの冒頭に次のコードを追加します。

js

1function createEvent(e) { 2 //エラー防止のため、以下の5行を追加 3 if (e === undefined) { 4 console.log('このスクリプトは、エディタから実行できません。'); 5 console.log('フォームに回答してみてください。'); 6 return; 7 }

次に、日付と時刻の処理を次のようにします。

js

1 // let hoursS = Number(time1.split(':')[0]); 2 // let minutesS = Number(time1.split(':')[1]); 3 // let hoursE = Number(time2.split(':')[0]); 4 // let minutesE = Number(time2.split(':')[1]); 5 // let startTime = new Date(y, m, d, hoursS, minutesS); 6 // let endTime = new Date(y, m, d, hoursE, minutesE); 7 let startTime = new Date(date + ' ' + time1);//' 'の中は、半角スペース 8 let endTime = new Date(date + ' ' + time2);

最後に、カレンダーへの反映の変数名を再修正します。

js

1 // Calendar.createEvent(title, startTime, endTime); 2 calendar.createEvent(title, startTime, endTime);

なお、フォームの送信から起動するスクリプトは、時々送信時の値を取得できないことが
ありますので、カレンダーに反映されていないときは、時間をおいて再度お試しください。
エディタの実行数からトリガー実行に失敗したログをクリックすると
エラーメッセージにもそのように記載されています。
Exception: Failed to retrieve form data. Please wait and try again.

--<最初の回答>--
勤務日、開始時間、終了時間共に記述式で、年は2023年4月12日、時間は9:30と入力するのですね。
修正が必要なところがいくつかあります。

なお、このスクリプトはフォームの送信をトリガーにして起動するものなので、
エディタから実行すると e の値が undefined なのでエラーになります。

できるだけ元のスクリプトに沿った形で修正する場合の例です。

回答の内容を得るには、質問が勤務日、開始時間、終了時間の3つの場合、

js

1 // let [timestamp, date, time1, time2] = e.values; 2 const items = []; 3 const itemResponses = e.response.getItemResponses(); 4 for (const itemResponse of itemResponses) { 5 items.push(itemResponse.getResponse()); 6 } 7 let [date, time1, time2] = items;

のようにします。timestampは取得できませんし使っていません。

時間の取得も開始時間、終了時間をそれぞれ加工するようにして、

js

1 // let hours = Number(time1, time2.split(':')[0]); 2 // let minutes = Number(time1, time2.split(':')[1]); 3 // let startTime = new Date(y, m, d, hours, minutes); 4 // let endTime = new Date(y, m, d, hours, minutes); 5 let hoursS = Number(time1.split(':')[0]); 6 let minutesS = Number(time1.split(':')[1]); 7 let hoursE = Number(time2.split(':')[0]); 8 let minutesE = Number(time2.split(':')[1]); 9 let startTime = new Date(y, m, d, hoursS, minutesS); 10 let endTime = new Date(y, m, d, hoursE, minutesE);

また、カレンダーへの反映もoptionは設定されていないのと、
CalendarAppではなく、ご自身で指定したCalendarへの反映ですから、

js

1 // CalendarApp.createEvent(title, startTime, endTime, options); 2 Calendar.createEvent(title, startTime, endTime);

投稿2023/04/11 22:58

編集2023/04/12 03:10
YellowGreen

総合スコア731

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.45%

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

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

質問する

関連した質問