質問文のエラーについては、updateDatesSheetの中括弧の位置 がおかしいことが原因です。
このエラー自体は、updateDatesSheet関数の続きのif文をupdateDatesSheet関数に含めるとともに
修正後のupdateDatesSheet関数をform関数の外に出すことで解消されます。
しかし他にも大量のバグが残っていてエラーが出るため、下記に原因と対応を記載します。
(注意:以下は、「2023/09/02 14:01のコメント内で共有されたスプレッドシート」の中に記載された、その時点でのコードに対する言及です。以降にコードが編集されていても関知しません。(関知できません))
1.「var id = sht.getRange(row, 1).getValue(); //ここのid部分が反応しなくなってしまった。」の原因
→ スコープ内で、変数idがどこからも参照されていないからです。
変数id は、sendEmail関数内で使われているため、sendEmail関数を呼ぶときに、idも一緒に引数として渡してやればよいです。
(idだけでなく、 name, childも sendEmail関数内で使われているため、idと一緒に引数として渡してやる必要があります)
2.「TypeError: Cannot read properties of undefined (reading 'getItemResponses') at form(コード:44:28)」 の原因
→ フォーム入力内容を取得する書き方として、getItemResponses関数は、フォームのコンテナバインドスクリプトとして書いたときだけ有効です。
質問者さんによれば、スプレッドシートのコンテナバインドスクリプトとして書かれているとのことですので、getItemResponsesは使えません。
代わりに、form関数の冒頭の「var values = e.values」のように、valuesプロパティを使いましょう。
ただ、reserveDateに格納しようとしているのは、フォームで入力された予約日ですが、予約日は、form関数の最初の方の
var date = values[2];//日付
ですでにdate変数として取得済みです。したがって、改めて
var reserveDate = values[2];
とする必要はありません。date変数をそのまま使いまわせばいいです。
その他
3:reserveSheetの未定義エラー
reserveSheet がどこにも定義されていないため、このままだとエラーになります。
4:予約数更新処理のバグ
日程シートの予約数を更新する下記の部分
datesSheet.getRange(target.rowNum, 3)
ですが、入力範囲を取得しているだけで、値が書き込まれていません。
値を書き込むには、「setValue(<値>)」を追加する必要があります。
5. 日付が見つからなかった時のエラー処理
フォームの回答で日付を選択していますが、万が一、選択肢の日付がスプレッドシート上になかったり、フォームの質問とスプレッドシートのデータの間でコピぺミス等で文字不一致になっている場合、現状のコードだと updateDatesSheet の
const index = table.findIndex(row => row[0] === reserveDate);
で indexが-1になり、後続の処理でエラーになります。
したがって、きちんとエラートラップを置くべきです。
具体的には、上記の行の下に
if (index === -1) return "error";
を追加します。
6. 定員超過判定のバグ
現状、updateDatesSheet関数の「 定員超過しなければ「予約済」に加算する」の中で、定員超過の判定処理として
if (target.reserved < target.cap) {
としていますが、これだと、更新前の予約人数と定員を比べていることになるため、常にtrueになり、実際は超過する場合でも予約できてしまいます。
ここは、[更新前予約人数+フォームで回答された予約人数]と定員とを比較すべきです。
このためには、呼び出し元のform関数でupdateDatesSheet関数を呼び出す際、updateDatesSheet関数に、フォームから回答された予約人数の情報を渡してやる必要があります。
7. form.getPublishedUrl()がエラーになる。
sendEmail関数の中で、
js
1 const mailBody = (result === "success")
2 ? "予約が完了しました。\n 添付されたQRコードを当日の受付でご提示ください \n"
3 + ` 【予約日】:${preferredDate}`
4 + '【氏 名】' + name + '\n'
5 + '【お申込み人数】' + child + '名\n'
6 + '【来場者ID】' + id
7 : "定員超過のため予約できませんでした。\n" +
8 "下記のフォームから再度申請してください\n" +
9 form.getPublishedUrl();
としていますが
質問中のコードの「form」は関数でありフォームオブジェクトではないため、getPublishedUrl関数を持っていません。
定員超過時に form.getPublishedUrl() が呼び出されるとエラーになります。
ここはフォームのURLを直接記述する必要があります。
修正後の全体コード
上記を踏まえて修正したものが下記です。(一部の要件が不明確のため、期待する動作になっていない部分があるかもしれませんがあしからず。)
注意:updateForm関数は、エラー回避のためダミーで作っていますが、実際は具体的な処理に置き換えてください。
js
1function form(e) {//メイン関数
2 var values = e.values;//フォームの回答を取得
3 //var stamp = values[0];//タイムスタンプを取得
4 var mail = values[1];//アドレス
5 var date = values[2];//日付
6 var name = values[3];//氏名
7 var child = values[4];//お連れ様の人数
8 var way = values[5];//イベント知ったツール
9 var up = 'FALSE';
10 var brank = '';
11 var ss = SpreadsheetApp.getActiveSpreadsheet();//スプレッドシートを有効にする
12 var sht = ss.getSheetByName('来場者');
13 sht.appendRow([brank, mail, name, way, child, up, date]);
14
15 var today = Utilities.formatDate(new Date(), "JST", "yyyy/MM/dd");
16 var ss = SpreadsheetApp.getActiveSpreadsheet();
17 var sht = ss.getSheetByName("来場者");
18 var lastrow = sht.getLastRow(); // 最終行を取得
19 var lastcol = sht.getLastColumn(); // 最終列を取得
20 var range = sht.getRange(1, 1, lastrow, lastcol);
21 var values = range.getValues(); // 情報をオンメモリに保持
22
23 /*来場者シートのデータを全部取得し、1行ずつチェック。
26 */
27 for (var i = 1; i < lastrow; i++) {
28 data = values[i][0];
29 if (data == "") {
30 values[i][0] = getRndStr();
31 }
32 values[i][8] = false;
33 var qrc1 = '=image(\"https://chart.apis.google.com/chart?chs=250x250&cht=qr&chl=\"&A' + (i + 1) + ')';
34 values[i][7] = qrc1;
35 }
36 range.setValues(values); //スプレッドシートに書き戻し
37
38 /*回答の名前と一致する行の1列目をidとして取得する*/
39 for (let row = 1; row <= lastrow; row++) {
40 if (sht.getRange(row, 3).getValue() == name) {
41 var id = sht.getRange(row, 1).getValue();
42 }
43 }
44
45 //------------------------------------------
46 // 日程シートから該当日のデータを取得
47 // フォームの送信内容を取得
48
49 // const items = e.response.getItemResponses(); // 削除
50 // const reserveDate = items[2].getResponse(); // 下のように修正
51 const reserveDate = date; // dateをそのまま使う
52
53 // 予約処理
54 const reservationCount = parseInt(child) + 1; // 追加 予約人数(連れの数+1 人)
55 //const result = updateDatesSheet(reserveDate); // 下のように修正。
56 const result = updateDatesSheet(reserveDate, reservationCount ); // 予約人数も渡す。
57
58 // 追加:reserveSheet変数の定義
59 const reserveSheet = ss.getSheetByName("予約");
60
61 if (result === "success") {
62 reserveSheet.appendRow([mail, reserveDate]); // 予約シートに追記
63 updateForm(); // フォームの「空き状況」を更新
64 }
65
66 // 追加。メール送信時にid, name, childを渡す。
67 sendEmail(mail, date, result, id, name, child);
68}
69
7076
77// function updateDatesSheet(reserveDate) {
78function updateDatesSheet(reserveDate, reservationCount ) { // 修正:予約人数を受け取る。
79 const ss1 = SpreadsheetApp.openById("シートID入れてます");
80 const datesSheet = ss1.getSheetByName("日程");
81 const table = datesSheet.getDataRange().getValues();
82 const index = table.findIndex(row => row[0] === reserveDate);
83
84 // 追加:フォームで回答された日付がスプレッドシート中になかった場合の処理。
85 if (index === -1) return "error";
86
87 const target = {
88 rowNum: index + 1,
89 date: table[index][0],
90 cap: table[index][1],
91 reserved: table[index][3], // 予約済人数:日程シートのD列
92 }
93
94 // 定員超過しなければ「予約済」に加算する
95 //if (target.reserved < target.cap) { // 下記のように修正
96 // [更新前予約人数+フォームで回答された予約人数]と定員とを比較する。
97 if (target.reserved + reservationCount < target.cap) {
98 // datesSheet.getRange(target.rowNum, 3); // 下記のように修正
99 // 更新後予約済人数を日程シートの予約済(C列?)に書き込む。
100 datesSheet.getRange(target.rowNum, 3).setValue(target.reserved + reservationCount);
101 return "success"
102 } else {
103 return "error"
104 }
105}
106
107
108//function sendEmail(mail, preferredDate, result) {
109function sendEmail(mail, preferredDate, result, id, name, child) { // id,name,childを受け取るように修正
110 const mailTitle = "予約結果";
111 const imageurl = 'https://chart.apis.google.com/chart?chs=250x250&cht=qr&chl=' + id;
112 const response = UrlFetchApp.fetch(imageurl); // option削除
113 const blob = response.getBlob().getAs(MimeType.JPEG);
114
115 const mailBody = (result === "success")
116 ? "予約が完了しました。\n 添付されたQRコードを当日の受付でご提示ください \n"
117 + ` 【予約日】:${preferredDate}`
118 + '【氏 名】' + name + '\n'
119 + '【お申込み人数】' + child + '名\n'
120 + '【来場者ID】' + id
121 : "定員超過のため予約できませんでした。\n" +
122 "下記のフォームから再度申請してください\n" +
123 //form.getPublishedUrl(); //修正。エラーになるのでURLを直接記述する必要あり。
124 "フォームのURL";
125
126 const option = {
127 method: "get",
128 "attachments": blob,
129 'name': 'イベント',
130 }
131
132 GmailApp.sendEmail(mail, mailTitle, mailBody, option);
133}
134
135function getRndStr() {
136 var str = "abcdefghijklmnopqrstuvwxyz0123456789";
137 var len = 8;
138 var result = "";
139 for (var i = 0; i < len; i++) {
140 result += str.charAt(Math.floor(Math.random() * str.length));
141 }
142 return result;
143}
144
145
146function updateForm() {
147 console.log("ダミーのupdateForm()が呼ばれました。")
148}
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2023/09/02 00:58
退会済みユーザー
2023/09/02 04:31 編集
2023/09/02 05:01
退会済みユーザー
2023/09/02 05:51
2023/09/02 06:48
退会済みユーザー
2023/09/02 07:49 編集
2023/09/02 09:37