回答編集履歴

4

 

2022/10/26 22:40

投稿

退会済みユーザー
test CHANGED
@@ -42,7 +42,7 @@
42
42
  これはなぜかというと「チェックを入れた行だけを送信対象とする」という、条件によるふるい分け処理が欠けているからです。
43
43
 
44
44
  ではどのようにするかについて説明します。
45
- まず、送信対象を作っている部分は(①で言及したのと同じ) Step8 : getTargets() 関数の中の、以下の部分になります。
45
+ まず、送信対象を作っている部分は(①で言及したのと同じ) Step8 : getTargets() 関数の中の、以下の部分になります。(もとのコードのままです)
46
46
  ```js
47
47
  const targets = contents.map((row) => {
48
48
  return {

3

 

2022/10/26 16:30

投稿

退会済みユーザー
test CHANGED
@@ -1,5 +1,5 @@
1
1
  (続き)
2
- 修正後のコード全体については、別()の回答欄に記載しています。
2
+ 修正後のコード全体については、別()の回答欄に記載しています。
3
3
  # 修正したところとポイント
4
4
 
5
5
  #### ① チェックボックスの状態を格納する部分

2

 

2022/10/26 16:29

投稿

退会済みユーザー
test CHANGED
@@ -1,142 +1,49 @@
1
- ※誠に申し訳ありませんが、文字数(1つの回答欄に10000字以上は投稿不可の関係で回答を2つに分けます。
1
+ (続き
2
- まず修正後の全体のコードに記載します。(修正した部分については後述します) 
2
+ 修正後のコード全体については、別()の回答欄に記載しています。
3
+ # 修正したところとポイント
4
+
5
+ #### ① チェックボックスの状態を格納する部分
6
+ 「/*Step8:宛先リストシート名から、シートの内容を配列で取得する」(130行目あたりから)を見ると
3
7
  ```js
4
- /*Step1:グローバル定数
5
- -------------------------------------------------------------*/
6
- const ss = SpreadsheetApp.getActiveSpreadsheet();
8
+ function getTargets(recipientListName) {
9
+
10
+ ...
11
+ ......
7
- const mainSheet = ss.getSheetByName("Main");
12
+ const targets = contents.map((row) => {
13
+ return {
14
+ checkbox: [0], // チェックボックス
15
+ ```
16
+ となっていました。
17
+ この一番下の行の
18
+ 「checkbox: [0]」
19
+ というところを
20
+ 「checkbox: row[0]」
21
+ に修正しています。
8
22
 
9
- /*Step2:シートオープン時にプルダウンの選択肢をセットする
23
+ おそらく単純ミスではないかな、と思いました。
24
+ その下の行では
25
+ ```js
10
- -------------------------------------------------------------*/
26
+ to: row[1], // 宛先メールアドレス
27
+ cc: row[2], // ccアドレス
11
- function onOpen() {
28
+ bcc: row[3],
29
+ ```
12
- setRecipientListPulldown();
30
+ のように、「row[x]」という形になっていますね。
13
- }
14
31
 
15
- /*Step3:送信/下書きボタン押下時の処理|onClickCreateDrafts
16
- -------------------------------------------------------------*/
32
+ row[0]ではなく[0]としてしまうと、単に数字のゼロが格納されるだけなので、チェックボックスの状態を格納したことになりません。
17
- function onClickSendEmails() {
18
- const answer = Browser.msgBox("メールを一括送信します。よろしいですか。", Browser.Buttons.OK_CANCEL);
19
- if (answer === "ok") {
20
- batchProcessEmails("sendEmail");
21
- Browser.msgBox("処理が完了しました。「処理結果」列を確認してください。");
22
- }
23
- }
24
33
 
25
- function onClickCreateDrafts() {
26
- const answer = Browser.msgBox("メールの下書きを一括作成します。よろしいですか。", Browser.Buttons.OK_CANCEL);
27
- if (answer === "ok") {
28
- batchProcessEmails("createDraft");
29
- Browser.msgBox("処理が完了しました。「処理結果」列を確認してください。");
30
- }
31
- }
32
34
 
33
- /*Step4:宛先シート全行分のメールを処理する|batchProcessEmails
34
- -------------------------------------------------------------*/
35
- function batchProcessEmails(action) {
36
- // Mainシートの入力値を取得
37
- const inputValues = getInputValues();
38
- // ログ列(R列)をクリア
39
- ss.getSheetByName(inputValues.recipientListName).getRange("R2:R").clear();
40
- // 宛先シートの入力内容を取得
41
- const targets = getTargets(inputValues.recipientListName);
42
- // 宛先シートの全行に対して送信(または下書き)を実行
43
- const logs = [];
44
- for (const target of targets) {
45
- const result = processEmail(inputValues, target, action);
46
- logs.push([result]);
47
- }
48
- // ログ列(Q列)に結果を貼り付け
49
- ss.getSheetByName(inputValues.recipientListName)
50
- .getRange(`R2:R${logs.length + 1}`)
51
- .setValues(logs);
52
- }
53
35
 
36
+ #### ② チェックボックスを入れた宛先だけを送付させるには?
54
- /*Step5:メ1件送信たは下書き作成する|processEmail
37
+ ご質問の中にある「チェックのついたデタのみ取得できせん。」という文から察するに、
55
- -------------------------------------------------------------*/
38
+ 質問者さんのコードだと「チェックを入れた行だけメール送信したいのに、全部の行に記入したメールが送信されてしまう。」ということであると推測しました。
56
- function processEmail(inputValues, target, action) {
57
- try {
58
- // タイトル・本文に差込を適用
59
- const replacedMailTitle = getReplacedString(inputValues.mailTitle, target.replaceList);
60
- const replacedMailBody = getReplacedString(inputValues.mailBody, target.replaceList);
61
39
 
62
- // 添付ファイルを取得
63
- const attachements = [
64
- ...getAttachements(inputValues.attachmentFolderId, inputValues.commonAttachmentNames),
65
- ...getAttachements(inputValues.attachmentFolderId, target.eachAttachmentNames)
40
+ そして上に書いた の部分を直して試しに「送信」ボタンまたは「下書き」ボタンを押しても、やはり全部送信されてしまいます。
66
- ]
67
41
 
68
- /* メールオプションの設定
69
- -------------------------------------------------------------*/
70
- const options = {};
71
- if (inputValues.senderEmail) options.from = inputValues.senderEmail;
72
- if (inputValues.senderName) options.name = inputValues.senderName;
73
- if (target.cc) options.cc = target.cc;
74
- if (target.bcc) options.bcc = target.bcc;
75
- if (attachements.length) options.attachments = attachements;
42
+ これはなぜかというと「チェックを入れた行だけを送信対象とする」という、条件によるふるい分け処理が欠けているからです。
76
43
 
77
- /* メール送信 or 下書き作成
78
- -------------------------------------------------------------*/
79
- if (action === "sendEmail") {
80
- GmailApp.sendEmail(target.to, replacedMailTitle, replacedMailBody, options);
81
- } else {
82
- GmailApp.createDraft(target.to, replacedMailTitle, replacedMailBody, options);
83
- }
84
- return "Success";
85
- } catch(error) {
86
- return error;
87
- }
88
- }
89
-
90
- /*Step6:文字列, 差込リストから差込後のテキストを取得する|getReplacedString
91
- -------------------------------------------------------------*/
92
- function getReplacedString(string, replaceList) {
93
- let replacedString = string;
94
- for (const item of replaceList) {
95
- const before = new RegExp(`\{\{ *${item.before} *\}\}`, "g");
96
- replacedString = replacedString.replace(before, item.after);
97
- }
98
- return replacedString;
99
- }
100
-
101
- //★:チェックボックスの判定
102
-
103
- function getCheckbox() {
104
- const myCell = mainSheet.getActiveCell();
105
- const rule = myCell.getDataValidation();
106
- if (rule != null) {
44
+ ではどのようにするかについて説明します。
107
- const criteria = rule.getCriteriaType();
108
- const status = myCell.getValue()
109
- if ( criteria == 'CHECKBOX' && status == true) {
110
- const row = myCell.getRow();
111
- getInputValues();
112
- }
113
- }
114
- }
115
-
116
- /*Step7:mainシートに入力された値を取得する|getInputValues
117
- -------------------------------------------------------------*/
118
- function getInputValues() {
119
- const inputValues = {
120
- attachmentFolderId: mainSheet.getRange("B2").getValue(), // 添付ファイル格納フォルダID
121
- mailTitle: mainSheet.getRange("B5").getValue(), // メールタイトル
122
- mailBody: mainSheet.getRange("B6").getValue(), // 本文
123
- commonAttachmentNames: [
124
- mainSheet.getRange("B7").getValue(), // 共通添付ファイル名1
125
- mainSheet.getRange("B8").getValue(), // 共通添付ファイル名2
126
- mainSheet.getRange("B9").getValue(), // 共通添付ファイル名3
127
- ],
128
- recipientListName: mainSheet.getRange("B12").getValue(), // 宛先リストシート名
129
- }
130
- return inputValues;
131
- }
132
-
133
- /*Step8:宛先リストシート名から、シートの内容を配列で取得する
134
- -------------------------------------------------------------*/
135
- function getTargets(recipientListName) {
136
- const targetsSheet = ss.getSheetByName(recipientListName);
137
- const sheetData = targetsSheet.getDataRange().getValues();
45
+ まず、送信対象を作っている部分は(①で言及したのと同じ) Step8 getTargets() 関数の中の、以下の部分になります。
138
- const header = sheetData[0];
46
+ ```js
139
- const contents = sheetData.slice(1);
140
47
  const targets = contents.map((row) => {
141
48
  return {
142
49
  checkbox: row[0], // [修正] // チェックボックス
@@ -150,67 +57,56 @@
150
57
  row[16], // 個別添付ファイル名3
151
58
  ]
152
59
  };
60
+ });
61
+ ```
62
+ contents.map の「map」 は配列を作る関数です。
63
+ 「contents」 には、宛先シートの全行データが格納されています。
64
+ そこから1行1行取り出して、必要な列だけ格納している処理が、上記のコードの部分です。
65
+
66
+ では、チェックを付けた行だけに絞るにはどうすればよいでしょうか?
67
+
68
+ ここで「filter」という関数を使用します。
69
+ filter 関数は、配列のうち「条件にあてはまる要素だけ」を抜き出して、新たな配列として返す関数です。
70
+ 簡単な例で説明します。
71
+ たとえば
72
+ numbers = [ 1, 2, 3, 4, 5, 6]
73
+ という配列があるとして、この配列から、偶数だけを抜き出したいとします。
74
+ これをコードで表すと
75
+ ```js
76
+ const numbers = [1, 2, 3, 4, 5, 6];
77
+ const new_numbers = numbers.filter(e => e % 2 === 0);
78
+ console.log(new_numbers);
79
+
80
+ >>> [2, 4, 6]
81
+ と表示される
82
+ ```
83
+
84
+ となります。
85
+ filterの中の「e => e % 2 === 0」というのが条件で「numbersの要素の中で、2で割った余りが0になる数だけを抜き出す」という条件を指定していることになります。
86
+
87
+ これを応用して、上記の宛先リストのコードに適用すると
88
+ 「チェックボックスにチェックが入っている(=チェックボックスの値が true)であるものだけを抜き出す」という条件になります。
89
+
90
+ これをコードで書くと
91
+ ```js
92
+ const targets = contents.map((row) => {
93
+ return {
94
+ checkbox: row[0], // [修正] // チェックボックス
95
+ to: row[1], // 宛先メールアドレス
96
+ cc: row[2], // ccアドレス
97
+ bcc: row[3], // bccアドレス
98
+ replaceList: getReplaceList(header, row), // 置換内容
99
+ eachAttachmentNames: [
100
+ row[14], // 個別添付ファイル名1
101
+ row[15], // 個別添付ファイル名2
102
+ row[16], // 個別添付ファイル名3
103
+ ]
104
+ };
153
- }).filter(e => e.checkbox === true); // [追加]
105
+ }).filter(row => row.checkbox === true); // [追加]
106
+ ```
154
- console.log(targets);
107
+ というようになります。(filter関数の条件を最後に追加)
108
+
155
- return targets;
109
+ いったん、contents =全行について列を整えた配列を作り、さらにその配列の中から「チェックボックスにチェックが入っている行」だけを抜き出した新たな配列を作る、という処理になります。
156
- }
157
110
 
158
111
 
159
- /*Step8:ヘッダー行・値行から、置換前・置換後を格納したオブジェクトの配列を返す
160
- -------------------------------------------------------------*/
161
- function getReplaceList(header, row) {
162
- const beforeStrings = header.slice(4, 14); // 5 - 14列目が差込項目
163
- const afterStrings = row.slice(4, 14); // 5 - 14列目が差込項目
164
- const replaceList = [];
165
- beforeStrings.forEach((beforeString, index) => {
166
- if (beforeString) replaceList.push({
167
- before: beforeString,
168
- after: afterStrings[index]
169
- });
170
- });
171
- return replaceList;
172
- }
173
112
 
174
- /* -------------------------------------------
175
- getAttachments
176
- フォルダID, ファイル名配列からファイル配列を取得する
177
- -------------------------------------------- */
178
- function getAttachements(folderId, fileNames) {
179
- const attachements = [];
180
- fileNames.forEach((fileName) => {
181
- if (fileName) attachements.push(getAttachement(folderId, fileName));
182
- })
183
- return attachements;
184
- }
185
-
186
- /* ----------------------------------------
187
- getAttachment
188
- フォルダID, ファイル名からファイルを取得する
189
- ------------------------------------------- */
190
- function getAttachement(folderId, fileName) {
191
- const files = DriveApp.getFolderById(folderId).getFilesByName(fileName);
192
- if (!files.hasNext()) throw Error(`添付ファイル ${fileName} が存在しません。`);
193
- file = files.next();
194
- if (files.hasNext()) throw Error(`添付ファイル ${fileName} が複数存在します。`);
195
- return file;
196
- }
197
-
198
- /* -----------------------------------------
199
- setRecipientListPulldown
200
- 宛先リストシート名のプルダウンに選択肢をセットする
201
- ------------------------------------------ */
202
- function setRecipientListPulldown() {
203
- // Mainシート以外のシート名を取得
204
- const values = ss.getSheets().map((sheet) => {
205
- const sheetName = sheet.getName()
206
- return sheetName !== "Main"
207
- ? sheetName
208
- : ""
209
- })
210
- // 入力規則を作成
211
- const rule = SpreadsheetApp.newDataValidation().requireValueInList(values).build();
212
- // MainシートのB14セルにルールを適用
213
- ss.getSheetByName("Main").getRange("B14").setDataValidation(rule);
214
- }
215
- ```
216
- (修正部分の説明については別の回答欄に記載しています)

1

 

2022/10/26 16:27

投稿

退会済みユーザー
test CHANGED
@@ -1,5 +1,5 @@
1
1
  ※誠に申し訳ありませんが、文字数(1つの回答欄に10000字以上は投稿不可)の関係で回答を2つに分けます。
2
- まず修正後の全体のコードを下記に記載します。(修正した部分については後述します)
2
+ まず修正後の全体のコードを下記に記載します。(修正した部分については後述します) 
3
3
  ```js
4
4
  /*Step1:グローバル定数
5
5
  -------------------------------------------------------------*/