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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Google Apps Script

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

Q&A

解決済

2回答

3324閲覧

【GAS】土日祝を除いた日にトリガーを実行したい

sa_mo

総合スコア1

Google Apps Script

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

0グッド

1クリップ

投稿2023/04/04 02:06

実現したいこと

土日祝日を除いた日の平日にのみGASのmyFunctionを動かしたいです。
下記のコードを実行しているのですが、平日だけでなく土日祝もmyFunctionが実行されてしまいます。

該当のソースコード

//土日祝を判定
function isBusinessDay(){
var today = new Date();

//土日か判定
var weekInt = today.getDay();
if(weekInt <= 0 || 6 <= weekInt){
return false;
}

//祝日か判定
var calendarId = "ja.japanese#holiday@group.v.calendar.google.com";
var calendar = CalendarApp.getCalendarById(calendarId);
var todayEvents = calendar.getEventsForDay(today);
if(todayEvents.length > 0){
return false;
}

return true;
}

//平日のみmyFunctionのトリガーを作成
function setTrigger(){

 var date = new Date(date)
const time = new Date();
time.setHours(17);
time.setMinutes(00);

if (isBusinessDay() == true){
ScriptApp.newTrigger('myFunction').timeBased().at(time).create();
}
}

補足情報(FW/ツールのバージョンなど)

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

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

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

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

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

YellowGreen

2023/04/04 03:15

setTriggerの方の var date = new Date(date) のnew Date()のカッコ内のdateはなくてもいい(undefinedなので)と思いますが、 isBusinessDayも土日祝日(new Date()の中で土日や祝日の日付を指定したとき)はfalseを返しますので 土日、祝日にはトリガーは新たには設定されないと思います。 残るはmyFunctionの内容でしょうか。 あと、繰り返しのトリガーが重複して設定されているなどということはないでしょうか。
YellowGreen

2023/04/04 03:19

試しに、isBusinessDayの方の var today = new Date(); を var today = new Date('2023/04/09');などと土日祝日の日付を指定しておいて myFunctionを実行するとトリガーは設定されるかどうかご確認を。
sa_mo

2023/04/04 09:40

>YellowGreenさん ご回答ありがとうございます! 非エンジニアのため、わかりやすいご回答非常に助かります…! 下記が設定してあるコードの全部になるのですが、繰り返しのトリガーはmyFunctionが実行された際に削除されるようにコードを記載しており、先ほどもトリガーを再度確認したのですが、古いものはきちんと削除されていました。 実行の流れとしては、下記を想定しています。(手動でトリガーの作成はしていません) ①コード内の「平日のみmyFunctionのトリガーを作成」でmyFunctionのトリガーを作成 ▼ ②上記トリガーに従い、myFunctionが実行される ▼ ③myFunctionが実行されると①で作成されたトリガーが削除される >var today = new Date('2023/04/09');などと土日祝日の日付を指定しておいて myFunctionを実行するとトリガーは設定されるかどうかご確認を。 →上記を試したところ、「myFunctionF を実行しようとしましたが、削除されました。」というエラーが発生しました。 これは想定している流れにおいて、正しい挙動なのでしょうか…? ーーーーーーーーーーーーーーーーーーー //土日祝を判定 function isBusinessDay(){ var today = new Date(); //土日か判定 var weekInt = today.getDay(); if(weekInt <= 0 || 6 <= weekInt){ return false; } //祝日か判定 var calendarId = "ja.japanese#holiday@group.v.calendar.google.com"; var calendar = CalendarApp.getCalendarById(calendarId); var todayEvents = calendar.getEventsForDay(today); if(todayEvents.length > 0){ return false; } return true; } //平日のみmyFunctionのトリガーを作成 function setTrigger(){  var date = new Date(date) const time = new Date(); time.setHours(17); time.setMinutes(00); if (isBusinessDay() == true){ ScriptApp.newTrigger('myFunction').timeBased().at(time).create(); } } //myFunctionのトリガーを削除 function delTrigger() { const triggers = ScriptApp.getProjectTriggers(); for(const trigger of triggers){ if(trigger.getHandlerFunction() == "myFunction"){ ScriptApp.deleteTrigger(trigger); } } } function myFunction() { // 実行対象のシートを取得 var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('●●'); //最終行を取得 var lastRow = sheet.getRange(sheet.getMaxRows(), 2).getNextDataCell(SpreadsheetApp.Direction.UP).getRow(); //コピー元範囲 var range = 'E3'; //コピー先範囲 var copyRow = lastRow + 1; //最終行にコピー&ペースト sheet.getRange(range).copyTo(sheet.getRange(copyRow,2),{contentsOnly:true}); }
YellowGreen

2023/04/04 10:22

「①コード内の「平日のみmyFunctionのトリガーを作成」でmyFunctionのトリガーを作成」 これは、エディタから実行しているということでしょうか? 「繰り返しのトリガーはmyFunctionが実行された際に削除されるようにコードを記載しており、」 myFunctionにはそのようなコードは見当たりません。 トリガーの設定の手順をもう少し詳しく教えて下さい。 エディタから実行しているのならどの関数を実行しているのか。 myFunctionが実行されるとどうしてトリガーが削除されるのか。 おそらく、どこかのサイトにあるスクリプトを修正して利用されていると 思います。知恵袋で同様の質問がありました。 (その方は、個別の関数を実行してエラーになっていました。) トリガーは、毎回当日の午後5時に設定されるのでよいですね。 その当日が土日でもトリガーが設定されてしまっているのでしょうか? それとも日付を指定している(つもりで)指定の日が土日でもトリガーが設定されるということでしょうか。
YellowGreen

2023/04/04 10:32

実際のコードを加工してアップしてませんか?
sa_mo

2023/04/04 10:48

YellowGreenさん >「①コード内の「平日のみmyFunctionのトリガーを作成」でmyFunctionのトリガーを作成」 これは、エディタから実行しているということでしょうか? →はい、エディタから実行しています。 >「繰り返しのトリガーはmyFunctionが実行された際に削除されるようにコードを記載しており、」 myFunctionにはそのようなコードは見当たりません。 →上記18:40の私の投稿内にある「//myFunctionのトリガーを削除」以降の『function delTrigger() {…』部分のコードになります。 >トリガーは、毎回当日の午後5時に設定されるのでよいですね。 その当日が土日でもトリガーが設定されてしまっているのでしょうか? →はい、毎回当日午後5時に設定されています。おっしゃる通り、当日が土日祝日も設定されてしまっている状況です。。
sa_mo

2023/04/04 10:51

>実際のコードを加工してアップしてませんか? →はい、質問内容では一部をコピペして投稿しておりました。。わかりにくくすみません・・・ 18:40に投稿した私の補足コメントにコード全文が記載されております!
YellowGreen

2023/04/04 10:51

→上記18:40の私の投稿内にある「//myFunctionのトリガーを削除」以降の『function delTrigger() {…』部分のコードになります。 これは関数の定義ですが、どうやって実行しているのでしょうか?
YellowGreen

2023/04/04 10:53

毎回当日午後5時に設定されています。おっしゃる通り、当日が土日祝日も設定されてしまっている状況 土日にもエディタから実行しているのでしょうか?
YellowGreen

2023/04/04 10:56

ご説明では、設定は手動でエディタから、削除は自動とのことですが なぜ、実行していない削除の関数が実行されているのか 例えば、今の時点で設定されているトリガーはいくつあるのでしょうか。
YellowGreen

2023/04/04 11:30

質問者様以外の方がスクリプトをエディタから実行されていたりはしませんか?
guest

回答2

0

ベストアンサー

これまでのコメントのやりとりと、isBusinessDayやsetTrigger、delTriggerを使うようにサンプルスクリプトを示しているサイトなどを確認した上で回答しています。

このスクリプトは、

  1. 毎日特定の時間帯(!!)に起動するトリガー(日付ベースのタイマー)を設定して、土日祝日に関係なく営業開始時刻より前にsetTriggerを実行する。
  2. setTriggerは、その日が平日ならmyFunctionを実行するための時刻(!!)に起動するトリガー(特定の日時)を作成する。

という手法で行われるのが通常のようです。

なぜこのようなことをしているかというと、
トリガーでは、毎日の起動は1時間の範囲がある時間帯の設定だけで、何時何分という時刻での起動は日付も含めた1回限りの設定しかできないからです。
1つのトリガーに毎日の時間帯を設定できるタイマーを毎日の午後5時から6時に設定すると、日によっては午後5時20分頃だったり、またある日は午後5時40分頃に起動することになり時刻がピッタリに定まらない。
1つのトリガーに1つの特定の日時を設定できるタイマーを午後5時0分に設定すると、遅くとも午後5時1分までには起動するが実行後のトリガーは無効になるので次回のトリガーを改めて設定しなければならない。

これを解決して毎日(平日に限る)特定の日時にmyFunctionを実行するための仕組みがsetTriggerでその都度特定の日時のトリガーを設定しておくという手法なので、少なくともsetTriggerの方は土日祝日も含めて毎日自動実行される必要があります。こちらは、時刻にこだわる必要がないので営業開始時刻より余裕をもった時間帯のトリガーで起動するように設定しておくと、myFunctionはsetTriggerが平日だけ設定する1回限りの特定の日時のトリガーで起動し、その1回限りのトリガーはsetTriggerが次回起動時に自動で消去してくれる。

ということを前提にしたスクリプトをお示しします。myFunctionの方はsetTriggerが設定する1回限りのトリガーでその都度起動するので、トリガーに関するコマンドは含まれていなくて構わないのでお示ししておりません。従前のものをそのままお使いください。当方が動作確認に使ったのは、ログを記録するだけのmyFunctionです。
「既存のトリガーは、全て削除」した上でsetTriggerを「時間主導型」>「日付ベースのタイマー」>「午前2時〜3時」などの時間帯を設定して保存します。myFunctionのトリガーは自動設定されるので手動では設定しません。
時間帯は午前1時〜2時や午前3時〜4時でも構わないので営業時刻より前で余裕をもった時間帯を設定します。
動作確認をしたい場合は、エディタから手動でsetTriggerを実行してmyFunctionのトリガーが設定されるかどうか確認してみてください。なお、午後5時以降(トリガーとして無効な時刻)に実行すると設定に関係なく1分後の時刻のトリガーが設定されてしまいますので速やかにmyFunctionのトリガーを削除するかエディタからdelTriggerを実行してください。
土日祝日の確認は、setTriggerTest()をエディタで選んで実行すると、isBusinessDayの戻り値とsetTriggerの振る舞いがわかるようにしましたので、いろいろと日付を設定してみてお試しください。

以下、スクリプトです。

javascript

1//引数で渡された日が平日かどうかを 2//真偽値(平日:真 休日:偽)で返す 3function isBusinessDay(_date) { 4 //土日の判断 5 const week = _date.getDay(); 6 if (week == 0 || 6 == week) { 7 return false; 8 } 9 //Googleカレンダー(日本の祝日)から祝日の判断 10 const calendar = CalendarApp 11 .getCalendarById('ja.japanese#holiday@group.v.calendar.google.com'); 12 const holidayEvents = calendar.getEventsForDay(_date); 13 if (holidayEvents.length > 0) { 14 return false; 15 } 16 return true;//上2つに当てはまらなかったら平日 17} 18//この関数は、トリガーで「時間主導型」> 19//「日付ベースのタイマー」>「午前0時から1時」に設定し 20//土曜日曜祝日も含め日付が変わったら実行する。 21//トリガーで実行されると、最初に古いトリガーを削除 22//次にその日が平日なら新たなmyFunctionのトリガーを作成 23//その日が休日なら削除のみを行って終了 24function setTrigger() { 25 //古いトリガーを削除 26 delTrigger(); 27 //今日の日付の特定の時刻を生成 28 const today = new Date(); 29 today.setHours(17); 30 today.setMinutes(00); 31 //今日が平日ならmyFunctionのトリガーを設定 32 if (isBusinessDay(today)) { 33 ScriptApp.newTrigger('myFunction') 34 .timeBased() 35 .at(today) 36 .create(); 37 } 38} 39//'setTrigger'実行用のトリガーはそのままで 40//'myFunction'実行用のトリガーがあれば全て削除する 41function delTrigger() { 42 const triggers = ScriptApp.getProjectTriggers(); 43 for (const trigger of triggers) { 44 if (trigger.getHandlerFunction() == 'myFunction') { 45 ScriptApp.deleteTrigger(trigger); 46 } 47 } 48} 49//isBusinessDayとsetTriggerの動作確認(実際には、ログを表示するだけです) 50function setTriggerTest() { 51 console.log('テストを開始します。'); 52 //古いトリガーを削除 53 // delTrigger(); 54 console.log('delTriggerの実行テスト'); 55 //今日の日付の特定の時刻を生成 56 const today = new Date('2023/05/03');//←ここに試したい日付を入力 57 today.setHours(17); 58 today.setMinutes(00); 59 console.log('today: ' + Utilities.formatDate(today, 'JST', 'M/d')); 60 console.log('isBusinessDayの返事は、' + isBusinessDay(today)); 61 //今日が平日ならトリガーを設定 62 if (isBusinessDay(today)) { 63 // ScriptApp.newTrigger('myFunction') 64 // .timeBased() 65 // .at(today) 66 // .create(); 67 console.log('setTriggerの実行テスト'); 68 } 69 console.log('setTriggerは実行されましたか?'); 70}

投稿2023/04/04 20:54

編集2023/04/04 21:41
YellowGreen

総合スコア731

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

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

YellowGreen

2023/04/04 21:02

エディタに貼り付けるときは、functionの名前が重複しないように、既存の3つのfunctionを削除するか事前に名前をold_setTrigger、old_delTrigger、old_isBusinessDayなどと変えておきます。
sa_mo

2023/04/05 02:59

前提は上記に記載いただいた通りです!拙い説明を汲み取ってくださりありがとうございます・・・! テストをしてみたところ想定通りの動きになりました。 丁寧な解説とご回答本当にありがとうございました!
guest

0

毎日実行させる、という設定ができているのなら、
そのmyFunctionの方で現在日時が土日祝日なら何もしないで終了する、ってことをすればいいかと。

投稿2023/04/04 05:09

y_waiwai

総合スコア87774

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問