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

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

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

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

Google Apps Script

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

Q&A

解決済

1回答

2874閲覧

【GAS】フィルタをかけて表示された内容を取得し、行毎に書き換え、1回のメソッド呼び出しで反映させたい

aafxaa

総合スコア0

Google スプレッドシート

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

Google Apps Script

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

0グッド

0クリップ

投稿2021/07/04 14:07

編集2021/07/06 03:53

実現したいこと

GASで、スプレッドシートにフィルタをかけて表示された内容を取得し、行毎に書き換え、1回のメソッド呼び出しで反映させたい。
・フィルタをかけて表示された内容を取得:出来た
・フィルタをかけて表示された内容を行毎に書き換え:出来たのか不明
・書き換えた内容を1回のメソッド呼び出しでスプレッドシートに反映:やり方が判らない

具体的には、
・スプレッドシートの列は「メールアドレス」「メール送信済フラグ」
1.「メール送信済フラグ」が空白の行をフィルタして取得
2.行毎にメール送信し、送信したら「メール送信済フラグ」に値を書き込む
3.この処理を毎分繰り返す

発生している問題

スプレッドシートには、フォームから入力された内容が増えていくので、
メール送信済みの行は取得せず、最小限のデータのやり取りで済ませたい。
最小限のデータのやり取りにする書き方が判らない。

ソースコード

Google

1// 1分毎のトリガーに設定しておく 2function onTimerEveryMinute() { 3 const ColAddress = 1; 4 const ColRemind = 2; 5 const SheetID = 'testSheetID'; 6 const SheetName = 'フォームの回答 1'; 7 const RowStart = 2; // 行:データ開始位置(見出し行が1) 8 9 // フィルタ準備(誰かが変えてたら掛け直される) 10 const Sheet = SpreadsheetApp.openById(SheetID).getSheetByName(SheetName); 11 var Filter = Sheet.getFilter(); 12 if (null != Filter) { 13 Filter.remove(); 14 } 15 Filter = Sheet.getRange(RowStart - 1, 1, Sheet.getLastRow(), Sheet.getLastColumn()).createFilter(); 16 17 // 値が空白(メール未送信)でフィルタ 18 var criteria = SpreadsheetApp.newFilterCriteria().whenCellEmpty(); 19 criteria.build(); 20 Filter.setColumnFilterCriteria(ColRemind, criteria); 21 22 // メール送信 23 var values = Sheet.getDataRange().getValues().filter(function(_, i) {return !Sheet.isRowHiddenByFilter(i + 1)}); 24 for(var j = RowStart - 1; j < values.length; j++) { 25 GmailApp.sendEmail(values[j][ColAddress - 1], 'testMailSubject', 'このメールはGoogle Apps Scriptによる自動送信です。', {name: 'testMailName'}); 26 // メール送信済フラグを立てる 27 values[j][ColRemind - 1] = 1; // 出来たのか不明 28 } 29 // ループ内でフラグ立てて、ループ外で一気に書き込みたいが、やり方が判らない 30 31 // メール送信したらデフォルトのフィルタ状態に復帰 32 if (null != criteria) { 33 Filter.removeColumnFilterCriteria(ColRemind); // remindフィルタ解除 34 } 35}

読んだteratailのページ

・スプレッドシートのデータをフィルタで非表示にした行を除外して取得したい
https://teratail.com/questions/228915
・【GAS】フィルタをかけて表示される行の行番号を知りたい
https://teratail.com/questions/297477

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

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

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

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

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

sawa

2021/07/06 05:29

>最小限のデータのやり取りで済ませたい 処理速度を気にされてるのであれば、全部データ取得したあと配列に対してfilterかけた方がよさそうですが、なにかフィルタ表示を使う理由はありますか? 今書かれているコードも Sheet.getDataRange().getValues() で取得した全データを絞り込んでるだけなので、特に理由が無いなら取得した配列で処理をしていけば良いかと。
aafxaa

2021/07/07 11:55

コメントありがとうございます。反応が遅くなりまして申し訳ございません。 実はGASのコードを書くのは今回が初で、 Sheet.getDataRange().getValues().filter()の行はコピペでした。 ご指摘の通り、データを絞り込めればいいので、 「見た目」をフィルタする必要はありません。 よって「メール送信」前後の処理は不要になりますね。 処理速度の件も、GASには実行時間制限が有るらしいと聞きかじった程度なので、 データ量の見積をして問題無さそうならシンプルな処理に書き直そうと思います。 調査不足の質問にコメントくださいましてありがとうございました。 勉強になりました。
guest

回答1

0

自己解決

遅くなりました。シンプルにこんな感じになりました。

Google

1const ColRemind = 23; 2const ColStatus = 4; 3const RngMRemindRcvd = '$A$3' 4const RowStart = 3; // 行:データ開始位置(見出し行が2) 5 6const SheetID = 'testSheetID'; 7const SheetName = 'フォームの回答 1'; 8const SheetNameMStat= '状態マスタ'; 9const SheetNameMRemind= 'Remindマスタ'; 10 11const Sheet = SpreadsheetApp.openById(SheetID).getSheetByName(SheetName); 12const SheetMStat = SpreadsheetApp.openById(SheetID).getSheetByName(SheetNameMStat); 13const SheetMRemind = SpreadsheetApp.openById(SheetID).getSheetByName(SheetNameMRemind); 14 15function onEdit(e) { // スプレッドシート編集トリガに設定 16 const ColRcvdDateTime = 6; 17 const RngMstatRcvd = '$A$1' 18 19 const Rng = e.range; 20 if (RowStart <= Rng.getRow() && ColRcvdDateTime == Rng.getColumn() && !e.oldvalue) {// データ行に受取日時が入力されたら受取済にする 21 Sheet.getRange(Rng.getRow(), ColStatus).setValue(SheetMStat.getRange(RngMstatRcvd).getValue()); 22 Sheet.getRange(Rng.getRow(), ColRemind).setValue(SheetMRemind.getRange(RngMRemindRcvd).getValue()); 23 } 24} 25 26function onTimerEveryMinute() { // 1分毎のトリガーに設定しておく 27 const ColAdrs = 2; 28 const ColAdrsManager = 24; 29 const ColCustomer = 3; 30 const ColDeadlineDate = 20; 31 const ColDeadlineTime = 21; 32 const ColOrderDateTime = 1; 33 const ColOrderId = 10; 34 const ColOrderName = 11; 35 const ColScheduledDate = 16; 36 const ColScheduledTime = 17; 37 const PrmFmt = 'yyyy/MM/dd HH:mm'; 38 const PrmTimeZone = 'Asia/Tokyo'; 39 const RngMRemindSent = '$A$1' 40 const RngMRemindNoAdrs = '$A$2' 41 42 // メール送信 43 const NowJst = Utilities.formatDate(new Date(), PrmTimeZone, PrmFmt); 44 var values = Sheet.getDataRange().getValues(); 45 for(var j = RowStart - 1; j < values.length; j++) { // 見出し行はスキップ 46 if(values[j][ColRemind - 1]) { // 何らかのフラグが立ってたらスキップ 47 continue; 48 } 49 50 if(values[j][ColStatus - 1]) { // 状態値が設定されていたらスキップ(onEditの保険) 51 // ここに来るということは、!values[j][ColRemind - 1]である 52 Sheet.getRange(j + 1, ColRemind).setValue(SheetMRemind.getRange(RngMRemindRcvd).getValue()); 53 continue; 54 } 55 56 if(!values[j][ColAdrs - 1]) { // メールアドレスが無いと送信できないのでスキップ 57 // ここに来るということは、!values[j][ColRemind - 1]である 58 Sheet.getRange(j + 1, ColRemind).setValue(SheetMRemind.getRange(RngMRemindNoAdrs).getValue()); 59 continue; 60 } 61 62 if(!values[j][ColDeadlineDate - 1]) { // 期日が決まっていなければ催促出来ないのでスキップ 63 // ここに来るということは、!values[j][ColRemind - 1]である 64 continue; 65 } 66 67 if (values[j][ColScheduledDate - 1] + ' ' + values[j][ColScheduledTime - 1] < NowJst) { 68 GmailApp.sendEmail(values[j][ColAdrs - 1] 69 , 'testMailSubject' 70 , 'このメールはGoogle Apps Scriptによる自動送信です。' 71 , {name: 'testMailName'}); 72 Sheet.getRange(j + 1, ColRemind).setValue(SheetMRemind.getRange(RngMRemindSent).getValue()); 73 } 74 } 75}

投稿2021/08/07 13:56

aafxaa

総合スコア0

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問