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

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

新規登録して質問してみよう
ただいま回答率
85.48%
LINE Messaging API

LINE Messaging APIは、メッセージの送信・返信ができるAPIです。Web APIを経由しアプリケーションサーバとLINEのAPIでやり取りが可能。複数のメッセージタイプや分かりやすいAPIリファレンスを持ち、グループチャットにも対応しています。

Google Apps Script

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

3012閲覧

GAS トリガーが実行されない

SN____R

総合スコア8

LINE Messaging API

LINE Messaging APIは、メッセージの送信・返信ができるAPIです。Web APIを経由しアプリケーションサーバとLINEのAPIでやり取りが可能。複数のメッセージタイプや分かりやすいAPIリファレンスを持ち、グループチャットにも対応しています。

Google Apps Script

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2021/05/22 15:24

編集2021/05/24 07:27

現在、lineで使える予定表botを作成しているのですが、決まった時間に通知を送信するためのトリガーが起動しません。

Javascript

1var ACCESS_TOKEN = "XXXXXXXXXX="; 2var PUSH = "https://api.line.me/v2/bot/message/multicast"; 3var REPLY = "https://api.line.me/v2/bot/message/reply"; 4 5function doPost(e) { 6 var events = JSON.parse(e.postData.contents).events; 7 events.forEach(function(event) { 8 if(event.type == "message") { 9 reply(event); 10 } else if(event.type == "follow") { 11 follow(event); 12 } else if(event.type == "unfollow") { 13 unFollow(event); 14 } 15 }); 16} 17 18function push() { 19 var spreadsheet = SpreadsheetApp.openById("XXXXXX"); 20 var sheet = spreadsheet.getActiveSheet(); 21 22 var start = 2; 23 var end = sheet.getLastRow(); 24 25 var today = new Date();   26 var formattedDate = Utilities.formatDate(today, "JST", "yyyy/MM/dd"); 27 28 var spsh = SpreadsheetApp.openById("XXXXXX"); 29 var sht = spsh.getActiveSheet(); 30 var data = sht.getDataRange().getValues(); 31 var userlist = []; 32 for(var n = 0; n < data.length; n++){ 33 userlist.push(data[n][0]); 34 } 35 36 var value =[]; 37 for(var i = start; i <= end; i++) { 38 var sell_C = "C" + i; 39 var day_C = sheet.getRange(sell_C).getValue(); 40 var day_C = Utilities.formatDate(day_C, "JST", "yyyy/MM/dd"); 41 if(formattedDate != day_C){ 42 continue; 43 } 44 var sell_B = "B" + i; 45 value.push("・" + sheet.getRange(sell_B).getValue() + "\n\n"); 46 } 47 if(value.length == 0){ 48 return; 49 } 50 51 var postData = { 52 "to" : userlist, 53 "messages" : [ 54 { 55 "type" : "text", 56 "text" : "【本日の予定】\n\n" + value.join("") + "今日も一日がんばってね!" 57 } 58 ] 59 }; 60 61 var headers = { 62 "Content-Type" : "application/json; charset=UTF-8", 63 "Authorization" : "Bearer " + ACCESS_TOKEN 64 }; 65 66 var options = { 67 "method" : "POST", 68 "headers" : headers, 69 "payload" : JSON.stringify(postData) 70 }; 71 return UrlFetchApp.fetch(PUSH, options); 72} 73 74function reply(data) { 75 var postMsg = data.message.text; 76 var replyToken = data.replyToken; 77 var replyText = ""; 78 var userId = data.source.userId; 79 80 if (postMsg == "登録") { 81 // entry.zzzzzzはユーザーIDのフォームフィールドの番号。 82 replyText = 83 "予定の登録はこちら!\n" + 84 "XXXXXXXXXXXX=" +userId; 85 } else if (postMsg == "今後の予定") { 86 var spreadsheet = SpreadsheetApp.openById("XXXXXXXXXXXXX"); 87 var sheet = spreadsheet.getActiveSheet(); 88 89 var today =new Date(Utilities.formatDate(new Date(), "JST", "yyyy-MM-dd 00:00:00+09:00")) 90 // スプレッドシートのデータを一括取得 91 var allRecords = sheet.getRange(2, 1, sheet.getLastRow()-1, 4).getValues(); 92 // ユーザID が一致しかつ当日以降(当日含む)の項目だけ抽出し、日付順に並び替え。 93 var records = allRecords 94 .filter(e => e[3] == userId && e[2] >= today) 95 .sort((a,b) => a[2] - b[2]) 96 97 98 // 日付をフォーマットし、予定と一緒に配列化。 99 var value = records.map(e => 100 `${e[1]}${Utilities.formatDate(e[2], "JST", "yyyy/MM/dd hh:mm")})\n\n`); 101 102 replyText = value.join("") + "忘れないようにしましょう!"; 103 } 104 105 if(replyText == ""){ 106 return; 107 } else { 108 var postData = { 109 "replyToken" : replyToken, 110 "messages" : [ 111 { 112 "type" : "text", 113 "text" : replyText 114 } 115 ] 116 }; 117 118 var headers = { 119 "Content-Type" : "application/json; charset=UTF-8", 120 "Authorization" : "Bearer " + ACCESS_TOKEN 121 }; 122 123 var options = { 124 "method" : "POST", 125 "headers" : headers, 126 "payload" : JSON.stringify(postData) 127 }; 128 129 return UrlFetchApp.fetch(REPLY, options); 130 } 131} 132 133function follow(e) { 134 var spsh = SpreadsheetApp.openById("XXXXXX"); 135 var sht = spsh.getActiveSheet(); 136 sht.appendRow([e.source.userId]); 137} 138 139function unFollow(e){ 140 var spsh = SpreadsheetApp.openById("XXXXXX"); 141 var sht = spsh.getActiveSheet(); 142 var result = findRow(sht, e.source.userId, 1); 143 if(result > 0){ 144 sht.deleteRows(result); 145 } 146} 147 148function findRow(sht,val,col){ 149 var data = sht.getDataRange().getValues(); 150 for(var i = 0; i < data.length; i++){ 151 if(data[i][col-1] === val){ 152 return i+1; 153 } 154 } 155 return 0; 156}

↑コード全文です
「トリガーを追加」より、
・「実行する関数を選択」→ push
・「実行するデプロイを選択」→ Head
・「イベントのソースを選択」→ 時間主導型
・「時間ベースのトリガーのタイプを選択」→ 日付ベースのタイマー
・「時刻を選択」→ 午前7時〜8時
・「エラー通知設定」→ 毎日通知を受け取る
でトリガーを作成したのですが、

エラー Exception: パラメータ(String,String,String)が Utilities.formatDate のメソッドのシグネチャと一致しません。
at push(コード:40:29)
 
と表示されてしまい、実行されません。
ご指導のほどよろしくお願いします。

追記:
スプレッドシート

デバッグログ

デバッグログ2

デバッグログ3

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

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

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

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

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

itagagaki

2021/05/22 15:31

怪しいのは day_C = sheet.getRange(sell_C).getValue(); ですね。 この day_C がDateオブジェクトになっていないのでは。 そこ調べてみましたか?
SN____R

2021/05/22 16:36

このような表になっているのですが、間違っていますかね... 初心者なもので、確認をお願いしたいです。
CHERRY

2021/05/22 19:38

Utilities.formatDate の直前に day_C を console.log 等で出力して確認すると何が入っていますか?
SN____R

2021/05/22 19:42

ごめんなさい、その出力の仕方すら分からないです...
退会済みユーザー

退会済みユーザー

2021/05/24 11:00 編集

回答依頼を受けたので。 質問ですが、push()関数で送信したい内容は、各ユーザーごとに異なる予定ではないのでしょうか? 現状のコードだと、全員の予定を、全員に送信しようとしているように見えるのですが、これは意図する動作なのでしょうか。
SN____R

2021/05/24 10:56

確かにその通りですね...
退会済みユーザー

退会済みユーザー

2021/05/24 10:59

ユーザーごとに、そのユーザーの当日の予定を送るように修正できますが、そのようにした方がよいですか?
SN____R

2021/05/24 11:04

お願い致します...ありがとうございます。
guest

回答2

0

ベストアンサー

横からですみませんが質問者からSOSがあったので回答させていただきます。

まず、エラーの原因は、itagagaki様が御回答のように、
`day_C = sheet.getRange(sell_C).getValue();‘^ で参照したC列のセルの内容が
日付型ではなく、文字列型になってしまっているからと考えられます。

itagagaki様がコメントで記されているように、デバッグの一時停止中の画面で、
デバッガーのステップオーバーボタン(点の回りを回る矢印のボタン)をもう一度押せば
次の行に移り、day_Cの型を知ることができたはずです。

C列のデータを文字列型ではなく日付型とするには、スプレッドシート上でC列を選択し、C列の表示形式を、日付に変えます。(下図)

イメージ説明

次に、GASの設定上、時刻設定を日本にする必要があるので、

https://isgs-lab.com/516/ に記載の手順でappscript.jsonを表示し、

"timeZone"を "Asia/Tokyo"に変更します。

イメージ説明


ここまで準備できたら、コードを下記のように変えます。(

まず、現状の上から3行目のURLは、マルチキャスト=同じ内容を複数のメンバーに送るためのエンドポイントです。
今回は、同じ内容ではなく、メンバー毎に異なる内容を送るため、
マルチキャストではなく、通常のプッシュメッセージ用のエンドポイント(/push)を使用する必要があります。

diff

1var ACCESS_TOKEN = "XXXXXXXXXX="; 2-var PUSH = "https://api.line.me/v2/bot/message/multicast"; 3+var PUSH = "https://api.line.me/v2/bot/message/push"; 4var REPLY = "https://api.line.me/v2/bot/message/reply";

次に、push()関数は下記のようにします。(元のコードから変更が少なくなるようにしています)

function push() { var spreadsheet = SpreadsheetApp.openById("XXXXXX"); var sheet = spreadsheet.getActiveSheet(); var start = 2; var end = sheet.getLastRow(); var today = new Date();   var formattedDate = Utilities.formatDate(today, "JST", "yyyy/MM/dd"); var spsh = SpreadsheetApp.openById("XXXXXX"); var sht = spsh.getActiveSheet(); var data = sht.getDataRange().getValues(); var userlist = []; for(var n = 0; n < data.length; n++){ userlist.push(data[n][0]); } // ユーザーリストから取得したユーザーID毎にループする。 for (var u = 0; u < userlist.length; u++) { var value = []; for (var i = start; i <= end; i++) { // i行目のユーザーIDの取得 var sell_D = "D" + i; var user = sheet.getRange(sell_D).getValue(); // ユーザーIDがユーザーリストのu番目のユーザーと一致する場合 if (user == userlist[u]) { var sell_C = "C" + i; var day_C = sheet.getRange(sell_C).getValue(); // 日付列が空欄だとエラーになるのでcontinueする。 if (day_C == '') continue; day_C = Utilities.formatDate(day_C, "JST", "yyyy/MM/dd"); if (formattedDate !== day_C) continue; var sell_G = "G" + i; time_G = Utilities.formatDate(new Date(sheet.getRange(sell_G).getValue()), "JST", "HH:mm"); var sell_B = "B" + i; value.push("・" + sheet.getRange(sell_B).getValue() + "(" + time_G + ")" + "\n\n"); } } if (value.length > 0) { var postData = { // 個別のユーザーIDを指定 to: userlist[u], messages: [ { type: "text", text: "【本日の予定】\n\n" + value.join("") + "今日も一日がんばってね!", }, ], }; var headers = { "Content-Type": "application/json; charset=UTF-8", Authorization: "Bearer " + ACCESS_TOKEN, }; var options = { method: "POST", headers: headers, payload: JSON.stringify(postData), }; UrlFetchApp.fetch(PUSH, options); } } }

投稿2021/05/24 12:25

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

SN____R

2021/05/24 15:19

完成したのですが、24時を回ったあと、今後の予定が機能しなくなってしまいました...
退会済みユーザー

退会済みユーザー

2021/05/24 15:47

ソースの写し間違いや、スプレッドシートのデータ不備等でなければ、 固有の環境要因と思われるのでわかりかねます。 こちらの手元のデータでは12:00をまたいでも特に問題が発生していません。 GAS 無料版には制限があり、何回も読み書き等していると制限に達してタイムアウトになり動作しなくなるので、その可能性もあります。 GASの制限は以下です。 https://monoblog.jp/archives/2349 どんなエラーかは普通ログを見ることになりますが、GASでウェブアプリ化している場合、エラーログはgoogle cloud platformに結びつけていない限り確認できません。 (アプリとGoogle Cloud Platformとの結び付け方は以下: https://teratail.com/questions/265966) 考えられる対応方法: ・制限に達しているかもしれないので半日から一日待ってみる。 ・フォーム/スプレッドシートを作り直す。
SN____R

2021/05/24 15:59

一つ伺いたいのですが、XXXXXXに入る物はどちらも予定表のURLで合ってますでしょうか?
退会済みユーザー

退会済みユーザー

2021/05/24 16:12

もし、質問文のコードの通りにするならば、 ・全員の予定を集約したスプレッドシート(予定表)と ・チャンネルをフォローしたときに追加されるユーザー一覧のスプレッドシート は、別々のスプレッドシートシート(エクセルでいうところの別々の「ワークブック」)にしなければなりません。 push()関数でいうと、push()のすぐ下の行にある var spreadsheet = SpreadsheetApp.openById("XXXXXX"); のxxxxxxに入るのは、予定表のスプレッドシートIDです。 そこから空白を除いて6行下にある var spsh = SpreadsheetApp.openById("XXXXXX"); のXXXXXXに入るのは、ユーザー一覧のスプレッドシートIDです。 (仮に、1つのスプレッドシートの中に、予定表のシートとユーザー一覧のシートを格納しているならば、 XXXXXXはどちらも同じスプレッドシートIDになりますが、 それだと現状のコードではうまく動作しません。シート名を指定するコードを追加する必要があります)
SN____R

2021/05/24 23:40

そのようになっていました。 今現在、スプレッドシートとフォームを作り直したところ、今後の予定と入力すると予定がありませんと返ってくるようになってしまいました(通知の内容は入力済、スプレッドシートとフォームのurlは変更済みです)
退会済みユーザー

退会済みユーザー

2021/05/25 01:15 編集

・ユーザー一覧のスプレッドシートのA列に正しいLINEのユーザーID(「U」から始まるID)は入っていますか? ・作り直したフォームとスプレッドシートは正しく紐付けられているでしょうか? ・作り直したスプレッドシートのIDはきちんとコードに反映されているでしょうか? ・ダミーのユーザーIDをコードに記入してデバッグモードで各行をステップ実行し、データが意図通りに取得てきて流れているか確認してください。 いずれにしても、こちらでは実際のコードを触れない以上、こちらではこれくらいしかアドバイスできません。 前の質問のコメントの最後にも書きましたが、ちょっとした違いでプログラムは動かないてすし、こちらが想定していない設定をそちらが行っている可能性もありますので。 これ以上やろうとすると、そのスクリプトやスプレッドシートを私が直接実行確認して修正できるように、プロジェクトに招待していただくしかありません。
SN____R

2021/05/25 01:22

招待しますので、後ほどスプレッドシート等を確認していただくことは可能でしょうか...?
退会済みユーザー

退会済みユーザー

2021/05/25 02:26 編集

改めて検討します。対応できるとしても夕方以降になります。以上宜しくお願い致します。
SN____R

2021/05/25 07:35

こちらいつでも大丈夫です。よろしくお願いします。
退会済みユーザー

退会済みユーザー

2021/05/25 14:49 編集

遅くなりました。
SN____R

2021/05/25 14:42

申請させて頂きました。よろしくお願いします。
退会済みユーザー

退会済みユーザー

2021/05/25 15:03 編集

コードについて確認します
guest

0

Utilities.formatDateの第1引数はDate型ですが、day_C = sheet.getRange(sell_C).getValue(); で参照したセルの内容が2021/XX/XXだとday_Cの型は文字列になってしまうので、エラーとなります。
セルにちゃんとした日付が入っていればday_CはDate型となるので大丈夫だと思います。

投稿2021/05/22 16:59

itagagaki

総合スコア8402

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

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

SN____R

2021/05/22 17:04

というと、どこを訂正すれば良いでしょうか...?
itagagaki

2021/05/22 17:10

セルの内容は 2021/XX/XX というデータを許容しなければならないのですか? 日付ではないものをformatDateするのは土台無理な話です。 formatDateを使用している意図がわからないと、お答えしようがないです。
SN____R

2021/05/22 18:28

XXは実際には日付がはいるのですが、そういう事では無いですかね...?
SN____R

2021/05/22 18:38

今XXの文字列を消して試して見たのですが、同じようにエラー吐きます...
itagagaki

2021/05/23 01:18

Google Apps Script script.google.com にはデバッグ機能があるのはご存知ですか? 実行する関数として push を選び、 var day_C = sheet.getRange(sell_C).getValue(); のところにブレークポイントを設定して 「デバッグ」をクリックすると、push の実行を開始してブレークポイントの位置で実行が停止します。 そこで変数の内容等が表示されます。 ステップ実行すると、実行が1行進んで変数がどう変わったかを見ることができます。 var day_C = sheet.getRange(sell_C).getValue(); のところで止まったら、このステップを実行して day_C の内容を見てみてください。 Dateオブジェクトが入っていればOKです。セルのデータがDateオブジェクトならそうなるはずです。 day_Cが文字列になっていたらダメです。セルのデータに問題があります。 day_Cが文字列になる場合でもその内容に応じて自力でDateオブジェクトにうまい具合に変換して対処するコードを書くことも可能だと思いますが、それを実装するかどうかはまた別の話かと。
SN____R

2021/05/23 01:51

一応試しました...この画像で分かりますでしょうか?
itagagaki

2021/05/23 01:56

右の青い[デバッグを開始]ボタンを押してもう一度やってみてください。
SN____R

2021/05/23 02:33

画像の追記をさせていただきました。ご確認よろしくお願いします。
itagagaki

2021/05/23 02:40

var day_C = sheet.getRange(sell_C).getValue(); を実行する手前でブレークポイントで止まっている状態です。day_C は undefined になっているのがわかりますね。そこでデバッガーのステップオーバーボタン(点の回りを回る矢印のボタン)を一度押してください。すると var day_C = sheet.getRange(sell_C).getValue(); の実行だけが進んでまた止まります。そこで day_C の値を見てみてください。Sun May 23 2021 00:00:00 GMT+0900 (Japan Standard Time) のようになっていればきっとDate型なのでformatDateもエラーにならないはずです。
SN____R

2021/05/24 07:29

画像の追記を致しました。ご確認よろしくお願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問