回答編集履歴
5
t
test
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
質問文のエラーについては
|
1
|
+
質問文のエラーについては、updateDatesSheetの中括弧の位置 がおかしいことが原因です。
|
2
|
-
|
2
|
+
このエラー自体は、updateDatesSheet関数の続きのif文をupdateDatesSheet関数に含めるとともに
|
3
3
|
修正後のupdateDatesSheet関数をform関数の外に出すことで解消されます。
|
4
4
|
|
5
|
-
しかし
|
5
|
+
しかし他にも大量のバグが残っていてエラーが出るため、下記に原因と対応を記載します。
|
6
6
|
|
7
7
|
(注意:以下は、「2023/09/02 14:01のコメント内で共有されたスプレッドシート」の中に記載された、その時点でのコードに対する言及です。以降にコードが編集されていても関知しません。(関知できません))
|
8
8
|
|
4
冒頭追記
test
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
質問文のエラーについては
|
2
|
+
updateDatesSheetの中括弧の位置 がおかしくなっており、updateDatesSheet関数の続きのif文をupdateDatesSheet関数に含めるとともに
|
3
|
+
修正後のupdateDatesSheet関数をform関数の外に出すことで解消されます。
|
4
|
+
|
5
|
+
しかしその後もエラーが出たということなので、下記に原因と対応を記載します。
|
1
6
|
|
2
7
|
(注意:以下は、「2023/09/02 14:01のコメント内で共有されたスプレッドシート」の中に記載された、その時点でのコードに対する言及です。以降にコードが編集されていても関知しません。(関知できません))
|
3
8
|
|
3
修正
test
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
##### 1.「var id = sht.getRange(row, 1).getValue(); //ここのid部分が反応しなくなってしまった。」の原因
|
5
5
|
→ スコープ内で、変数idがどこからも参照されていないからです。
|
6
6
|
変数id は、sendEmail関数内で使われているため、sendEmail関数を呼ぶときに、idも一緒に引数として渡してやればよいです。
|
7
|
-
|
7
|
+
(idだけでなく、 name, childも sendEmail関数内で使われているため、idと一緒に引数として渡してやる必要があります)
|
8
8
|
|
9
9
|
|
10
10
|
##### 2.「TypeError: Cannot read properties of undefined (reading 'getItemResponses') at form(コード:44:28)」 の原因
|
@@ -150,8 +150,8 @@
|
|
150
150
|
updateForm(); // フォームの「空き状況」を更新
|
151
151
|
}
|
152
152
|
|
153
|
-
// 追加。メール送信時にidを渡す。
|
153
|
+
// 追加。メール送信時にid, name, childを渡す。
|
154
|
-
sendEmail(mail, date, result, id);
|
154
|
+
sendEmail(mail, date, result, id, name, child);
|
155
155
|
}
|
156
156
|
|
157
157
|
/**
|
@@ -193,7 +193,7 @@
|
|
193
193
|
|
194
194
|
|
195
195
|
//function sendEmail(mail, preferredDate, result) {
|
196
|
-
function sendEmail(mail, preferredDate, result, id) { // idを受け取るように修正
|
196
|
+
function sendEmail(mail, preferredDate, result, id, name, child) { // id,name,childを受け取るように修正
|
197
197
|
const mailTitle = "予約結果";
|
198
198
|
const imageurl = 'https://chart.apis.google.com/chart?chs=250x250&cht=qr&chl=' + id;
|
199
199
|
const response = UrlFetchApp.fetch(imageurl); // option削除
|
2
追記
test
CHANGED
@@ -1,10 +1,89 @@
|
|
1
|
+
|
2
|
+
(注意:以下は、「2023/09/02 14:01のコメント内で共有されたスプレッドシート」の中に記載された、その時点でのコードに対する言及です。以降にコードが編集されていても関知しません。(関知できません))
|
3
|
+
|
4
|
+
##### 1.「var id = sht.getRange(row, 1).getValue(); //ここのid部分が反応しなくなってしまった。」の原因
|
5
|
+
→ スコープ内で、変数idがどこからも参照されていないからです。
|
6
|
+
変数id は、sendEmail関数内で使われているため、sendEmail関数を呼ぶときに、idも一緒に引数として渡してやればよいです。
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
##### 2.「TypeError: Cannot read properties of undefined (reading 'getItemResponses') at form(コード:44:28)」 の原因
|
11
|
+
→ フォーム入力内容を取得する書き方として、getItemResponses関数は、フォームのコンテナバインドスクリプトとして書いたときだけ有効です。
|
12
|
+
|
13
|
+
質問者さんによれば、スプレッドシートのコンテナバインドスクリプトとして書かれているとのことですので、getItemResponsesは使えません。
|
14
|
+
代わりに、form関数の冒頭の「var values = e.values」のように、valuesプロパティを使いましょう。
|
15
|
+
|
16
|
+
ただ、reserveDateに格納しようとしているのは、フォームで入力された予約日ですが、予約日は、form関数の最初の方の
|
17
|
+
```
|
18
|
+
var date = values[2];//日付
|
19
|
+
```
|
20
|
+
ですでにdate変数として取得済みです。したがって、改めて
|
21
|
+
```
|
22
|
+
var reserveDate = values[2];
|
23
|
+
```
|
24
|
+
とする必要はありません。date変数をそのまま使いまわせばいいです。
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
###### その他
|
29
|
+
##### 3:reserveSheetの未定義エラー
|
30
|
+
reserveSheet がどこにも定義されていないため、このままだとエラーになります。
|
31
|
+
|
32
|
+
##### 4:予約数更新処理のバグ
|
33
|
+
日程シートの予約数を更新する下記の部分
|
34
|
+
```
|
35
|
+
datesSheet.getRange(target.rowNum, 3)
|
36
|
+
```
|
37
|
+
ですが、入力範囲を取得しているだけで、値が書き込まれていません。
|
38
|
+
値を書き込むには、「setValue(<値>)」を追加する必要があります。
|
39
|
+
|
40
|
+
##### 5. 日付が見つからなかった時のエラー処理
|
41
|
+
フォームの回答で日付を選択していますが、万が一、選択肢の日付がスプレッドシート上になかったり、フォームの質問とスプレッドシートのデータの間でコピぺミス等で文字不一致になっている場合、現状のコードだと updateDatesSheet の
|
42
|
+
```
|
43
|
+
const index = table.findIndex(row => row[0] === reserveDate);
|
44
|
+
```
|
45
|
+
で indexが-1になり、後続の処理でエラーになります。
|
46
|
+
したがって、きちんとエラートラップを置くべきです。
|
1
|
-
|
47
|
+
具体的には、上記の行の下に
|
48
|
+
```
|
49
|
+
if (index === -1) return "error";
|
50
|
+
```
|
51
|
+
を追加します。
|
52
|
+
|
53
|
+
##### 6. 定員超過判定のバグ
|
2
|
-
updateDatesSheet関数
|
54
|
+
現状、updateDatesSheet関数の「 定員超過しなければ「予約済」に加算する」の中で、定員超過の判定処理として
|
3
|
-
|
55
|
+
```
|
4
|
-
|
56
|
+
if (target.reserved < target.cap) {
|
57
|
+
```
|
58
|
+
としていますが、これだと、更新前の予約人数と定員を比べていることになるため、常にtrueになり、実際は超過する場合でも予約できてしまいます。
|
59
|
+
ここは、[更新前予約人数+フォームで回答された予約人数]と定員とを比較すべきです。
|
60
|
+
このためには、呼び出し元のform関数でupdateDatesSheet関数を呼び出す際、updateDatesSheet関数に、フォームから回答された予約人数の情報を渡してやる必要があります。
|
61
|
+
|
62
|
+
##### 7. form.getPublishedUrl()がエラーになる。
|
63
|
+
sendEmail関数の中で、
|
64
|
+
```js
|
65
|
+
const mailBody = (result === "success")
|
66
|
+
? "予約が完了しました。\n 添付されたQRコードを当日の受付でご提示ください \n"
|
67
|
+
+ ` 【予約日】:${preferredDate}`
|
68
|
+
+ '【氏 名】' + name + '\n'
|
69
|
+
+ '【お申込み人数】' + child + '名\n'
|
70
|
+
+ '【来場者ID】' + id
|
71
|
+
: "定員超過のため予約できませんでした。\n" +
|
72
|
+
"下記のフォームから再度申請してください\n" +
|
73
|
+
form.getPublishedUrl();
|
74
|
+
```
|
75
|
+
としていますが
|
76
|
+
|
77
|
+
質問中のコードの「form」は関数でありフォームオブジェクトではないため、getPublishedUrl関数を持っていません。
|
5
|
-
|
78
|
+
定員超過時に form.getPublishedUrl() が呼び出されるとエラーになります。
|
6
|
-
|
7
|
-
|
79
|
+
ここはフォームのURLを直接記述する必要があります。
|
80
|
+
|
81
|
+
---
|
82
|
+
|
83
|
+
### 修正後の全体コード
|
84
|
+
上記を踏まえて修正したものが下記です。(一部の要件が不明確のため、期待する動作になっていない部分があるかもしれませんがあしからず。)
|
85
|
+
注意:updateForm関数は、エラー回避のためダミーで作っていますが、実際は具体的な処理に置き換えてください。
|
86
|
+
|
8
87
|
```js
|
9
88
|
function form(e) {//メイン関数
|
10
89
|
var values = e.values;//フォームの回答を取得
|
@@ -27,6 +106,11 @@
|
|
27
106
|
var lastcol = sht.getLastColumn(); // 最終列を取得
|
28
107
|
var range = sht.getRange(1, 1, lastrow, lastcol);
|
29
108
|
var values = range.getValues(); // 情報をオンメモリに保持
|
109
|
+
|
110
|
+
/*来場者シートのデータを全部取得し、1行ずつチェック。
|
111
|
+
A列が空欄の場合はランダムな文字列を記入。
|
112
|
+
I列にQRコードの数式を設定
|
113
|
+
*/
|
30
114
|
for (var i = 1; i < lastrow; i++) {
|
31
115
|
data = values[i][0];
|
32
116
|
if (data == "") {
|
@@ -38,6 +122,7 @@
|
|
38
122
|
}
|
39
123
|
range.setValues(values); //スプレッドシートに書き戻し
|
40
124
|
|
125
|
+
/*回答の名前と一致する行の1列目をidとして取得する*/
|
41
126
|
for (let row = 1; row <= lastrow; row++) {
|
42
127
|
if (sht.getRange(row, 3).getValue() == name) {
|
43
128
|
var id = sht.getRange(row, 1).getValue();
|
@@ -48,39 +133,106 @@
|
|
48
133
|
// 日程シートから該当日のデータを取得
|
49
134
|
// フォームの送信内容を取得
|
50
135
|
|
51
|
-
const items = e.response.getItemResponses();
|
136
|
+
// const items = e.response.getItemResponses(); // 削除
|
137
|
+
// const reserveDate = items[2].getResponse(); // 下のように修正
|
52
|
-
const reserveDate =
|
138
|
+
const reserveDate = date; // dateをそのまま使う
|
53
139
|
|
54
140
|
// 予約処理
|
141
|
+
const reservationCount = parseInt(child) + 1; // 追加 予約人数(連れの数+1 人)
|
55
|
-
const result = updateDatesSheet(reserveDate);
|
142
|
+
//const result = updateDatesSheet(reserveDate); // 下のように修正。
|
143
|
+
const result = updateDatesSheet(reserveDate, reservationCount ); // 予約人数も渡す。
|
144
|
+
|
145
|
+
// 追加:reserveSheet変数の定義
|
146
|
+
const reserveSheet = ss.getSheetByName("予約");
|
147
|
+
|
56
148
|
if (result === "success") {
|
57
|
-
reserveSheet.appendRow([
|
149
|
+
reserveSheet.appendRow([mail, reserveDate]); // 予約シートに追記
|
58
|
-
updateForm();
|
150
|
+
updateForm(); // フォームの「空き状況」を更新
|
59
|
-
}
|
151
|
+
}
|
152
|
+
|
153
|
+
// 追加。メール送信時にidを渡す。
|
154
|
+
sendEmail(mail, date, result, id);
|
60
|
-
}
|
155
|
+
}
|
156
|
+
|
61
|
-
|
157
|
+
/**
|
158
|
+
* 引数に指定した予約日の予約人数が、定員オーバーでないか確認する。
|
159
|
+
* オーバーしていなければ、日程シートの現在の予約数に予約人数を加算し、文字列"success"を返す。
|
160
|
+
* オーバーしている場合は、文字列"error"を返す。
|
161
|
+
* 引数:reserveDate フォームに入力された予約日
|
162
|
+
* reservationCount フォームの回答から計算した予約人数
|
163
|
+
*/
|
62
|
-
function updateDatesSheet(reserveDate) {
|
164
|
+
// function updateDatesSheet(reserveDate) {
|
165
|
+
function updateDatesSheet(reserveDate, reservationCount ) { // 修正:予約人数を受け取る。
|
63
166
|
const ss1 = SpreadsheetApp.openById("シートID入れてます");
|
64
167
|
const datesSheet = ss1.getSheetByName("日程");
|
65
168
|
const table = datesSheet.getDataRange().getValues();
|
66
169
|
const index = table.findIndex(row => row[0] === reserveDate);
|
170
|
+
|
171
|
+
// 追加:フォームで回答された日付がスプレッドシート中になかった場合の処理。
|
172
|
+
if (index === -1) return "error";
|
173
|
+
|
67
174
|
const target = {
|
68
175
|
rowNum: index + 1,
|
69
176
|
date: table[index][0],
|
70
|
-
cap: table[index][1],
|
177
|
+
cap: table[index][1],
|
71
|
-
reserved: table[index][3],//日程シートのD列
|
178
|
+
reserved: table[index][3], // 予約済人数:日程シートのD列
|
72
|
-
}
|
179
|
+
}
|
180
|
+
|
73
181
|
// 定員超過しなければ「予約済」に加算する
|
182
|
+
//if (target.reserved < target.cap) { // 下記のように修正
|
183
|
+
// [更新前予約人数+フォームで回答された予約人数]と定員とを比較する。
|
74
|
-
if (target.reserved < target.cap) {
|
184
|
+
if (target.reserved + reservationCount < target.cap) {
|
75
|
-
datesSheet.getRange(target.rowNum, 3);
|
185
|
+
// datesSheet.getRange(target.rowNum, 3); // 下記のように修正
|
186
|
+
// 更新後予約済人数を日程シートの予約済(C列?)に書き込む。
|
187
|
+
datesSheet.getRange(target.rowNum, 3).setValue(target.reserved + reservationCount);
|
76
188
|
return "success"
|
77
189
|
} else {
|
78
190
|
return "error"
|
79
191
|
}
|
80
192
|
}
|
81
193
|
|
194
|
+
|
82
|
-
//
|
195
|
+
//function sendEmail(mail, preferredDate, result) {
|
83
|
-
|
196
|
+
function sendEmail(mail, preferredDate, result, id) { // idを受け取るように修正
|
197
|
+
const mailTitle = "予約結果";
|
198
|
+
const imageurl = 'https://chart.apis.google.com/chart?chs=250x250&cht=qr&chl=' + id;
|
199
|
+
const response = UrlFetchApp.fetch(imageurl); // option削除
|
200
|
+
const blob = response.getBlob().getAs(MimeType.JPEG);
|
201
|
+
|
202
|
+
const mailBody = (result === "success")
|
203
|
+
? "予約が完了しました。\n 添付されたQRコードを当日の受付でご提示ください \n"
|
204
|
+
+ ` 【予約日】:${preferredDate}`
|
205
|
+
+ '【氏 名】' + name + '\n'
|
206
|
+
+ '【お申込み人数】' + child + '名\n'
|
207
|
+
+ '【来場者ID】' + id
|
208
|
+
: "定員超過のため予約できませんでした。\n" +
|
209
|
+
"下記のフォームから再度申請してください\n" +
|
210
|
+
//form.getPublishedUrl(); //修正。エラーになるのでURLを直接記述する必要あり。
|
211
|
+
"フォームのURL";
|
212
|
+
|
213
|
+
const option = {
|
214
|
+
method: "get",
|
215
|
+
"attachments": blob,
|
216
|
+
'name': 'イベント',
|
217
|
+
}
|
218
|
+
|
219
|
+
GmailApp.sendEmail(mail, mailTitle, mailBody, option);
|
220
|
+
}
|
221
|
+
|
222
|
+
function getRndStr() {
|
223
|
+
var str = "abcdefghijklmnopqrstuvwxyz0123456789";
|
224
|
+
var len = 8;
|
225
|
+
var result = "";
|
226
|
+
for (var i = 0; i < len; i++) {
|
227
|
+
result += str.charAt(Math.floor(Math.random() * str.length));
|
228
|
+
}
|
229
|
+
return result;
|
230
|
+
}
|
231
|
+
|
232
|
+
|
233
|
+
function updateForm() {
|
234
|
+
console.log("ダミーのupdateForm()が呼ばれました。")
|
235
|
+
}
|
84
|
-
```
|
236
|
+
```
|
85
|
-
|
86
|
-
|
237
|
+
|
238
|
+
|
1
修正
test
CHANGED
@@ -5,8 +5,7 @@
|
|
5
5
|
からif文の終わりまでが updateDatesSheet の外にある形になってしまっているのがエラーの原因です。
|
6
6
|
|
7
7
|
他の部分にバグがなければ、下記で動くはずです。
|
8
|
-
```
|
8
|
+
```js
|
9
|
-
|
10
9
|
function form(e) {//メイン関数
|
11
10
|
var values = e.values;//フォームの回答を取得
|
12
11
|
//var stamp = values[0];//タイムスタンプを取得
|
@@ -71,8 +70,6 @@
|
|
71
70
|
cap: table[index][1],//日程シートB列
|
72
71
|
reserved: table[index][3],//日程シートのD列(人数シートから集計した人数)
|
73
72
|
}
|
74
|
-
|
75
|
-
|
76
73
|
// 定員超過しなければ「予約済」に加算する
|
77
74
|
if (target.reserved < target.cap) {
|
78
75
|
datesSheet.getRange(target.rowNum, 3);
|
@@ -82,40 +79,7 @@
|
|
82
79
|
}
|
83
80
|
}
|
84
81
|
|
85
|
-
function sendEmail(mail, preferredDate, result) {
|
86
|
-
|
87
|
-
const mailTitle = "予約結果";
|
88
|
-
const imageurl = 'https://chart.apis.google.com/chart?chs=250x250&cht=qr&chl=' + id;
|
89
|
-
const response = UrlFetchApp.fetch(imageurl, option);
|
90
|
-
const blob = response.getBlob().getAs(MimeType.JPEG);
|
91
|
-
|
92
|
-
const mailBody = (result === "success")
|
93
|
-
? "予約が完了しました。\n 添付されたQRコードを当日の受付でご提示ください \n"
|
94
|
-
+ ` 【予約日】:${preferredDate}`
|
95
|
-
|
82
|
+
// function sendEmail ~~~以降略
|
96
|
-
+ '【お申込み人数】' + child + '名\n'
|
97
|
-
+ '【来場者ID】' + id
|
98
|
-
: "定員超過のため予約できませんでした。\n" +
|
99
|
-
"下記のフォームから再度申請してください\n" +
|
100
|
-
form.getPublishedUrl();
|
101
|
-
const option = {
|
102
|
-
method: "get",
|
103
|
-
"attachments": blob,
|
104
|
-
'name': 'イベント',
|
105
|
-
}
|
106
|
-
GmailApp.sendEmail(mail, mailTitle, mailBody, option);
|
107
|
-
|
108
|
-
}
|
109
|
-
|
110
|
-
function getRndStr() {
|
111
|
-
var str = "abcdefghijklmnopqrstuvwxyz0123456789";
|
112
|
-
var len = 8;
|
113
|
-
var result = "";
|
114
|
-
for (var i = 0; i < len; i++) {
|
115
|
-
result += str.charAt(Math.floor(Math.random() * str.length));
|
116
|
-
}
|
117
|
-
return result;
|
118
|
-
}
|
119
83
|
|
120
84
|
```
|
121
85
|
|