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

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

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

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

Google Apps Script

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

JavaScript

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

Q&A

解決済

2回答

1365閲覧

GASでのスプレッドシートの個別リスト作成について

SN____R

総合スコア8

Google スプレッドシート

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

Google Apps Script

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

JavaScript

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

0グッド

0クリップ

投稿2021/05/21 10:58

編集2021/05/22 12:52

予定表

フォーム

1つ前の質問の危険性を教えて下さった方へ
本当にありがとうございました。

現在GASを使用してこのようなLINEBOTを作成しています。
googleフォームを使用し、通知させる内容、日付を入力
入力された内容をスプレッドシートに記述
設定した時間ごとに通知を送信

このようなプログラムを見よう見まねで作成したのですが、予定を表示させたときに、複数人の予定が纏めて表示されてしまいました。
そこで、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("XXXXXXXXXX"); 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("XXXXXXXXXX"); 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 79 if(postMsg == "登録") { 80 replyText = "予定の登録はこちら\n" + "https://docs.google.com/forms/d/XXXXXXXXXX/edit#responses"; 81 } else if(postMsg == "今後の予定") { 82 var spreadsheet = SpreadsheetApp.openById("XXXXXXXXXX"); 83 var sheet = spreadsheet.getActiveSheet(); 84 85 var range = sheet.getRange(2, 1, sheet.getLastRow(), 3); 86 range.sort([ 87 {column: 3, ascending: true}, 88 ]); 89 90   var start = 2; 91 var end = sheet.getLastRow(); 92 93 var today = new Date();   94 var formattedDate = Utilities.formatDate(today, "JST", "yyyy/MM/dd"); 95 96 var value =[]; 97 for(var i = start; i <= end; i++) { 98 var sell_C = "C" + i; 99 var day_C = sheet.getRange(sell_C).getValue(); 100 var day_C = Utilities.formatDate(day_C, "JST", "yyyy/MM/dd"); 101 if(formattedDate < day_C){ 102 var sell_B = "B" + i; 103 value.push("・" + sheet.getRange(sell_B).getValue() + "(" + day_C + ")" + "\n\n"); 104 } 105 } 106 replyText = value.join("") + "忘れないようにしましょう!"; 107 } 108 109 if(replyText == ""){ 110 return; 111 } else { 112 var postData = { 113 "replyToken" : replyToken, 114 "messages" : [ 115 { 116 "type" : "text", 117 "text" : replyText 118 } 119 ] 120 }; 121 122 var headers = { 123 "Content-Type" : "application/json; charset=UTF-8", 124 "Authorization" : "Bearer " + ACCESS_TOKEN 125 }; 126 127 var options = { 128 "method" : "POST", 129 "headers" : headers, 130 "payload" : JSON.stringify(postData) 131 }; 132 133 return UrlFetchApp.fetch(REPLY, options); 134 } 135} 136 137function follow(e) { 138 var spsh = SpreadsheetApp.openById("XXXXXXXXXX"); 139 var sht = spsh.getActiveSheet(); 140 sht.appendRow([e.source.userId]); 141} 142 143function unFollow(e){ 144 var spsh = SpreadsheetApp.openById("XXXXXXXXXX"); 145 var sht = spsh.getActiveSheet(); 146 var result = findRow(sht, e.source.userId, 1); 147 if(result > 0){ 148 sht.deleteRows(result); 149 } 150} 151 152function findRow(sht,val,col){ 153 var data = sht.getDataRange().getValues(); 154 for(var i = 0; i < data.length; i++){ 155 if(data[i][col-1] === val){ 156 return i+1; 157 } 158 } 159 return 0; 160}

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2021/05/21 12:57 編集

ユーザーごとにスプレッドシートを作るよりも、 ・すべてのユーザーの予定を1つのスプレッドシートに集約し、 ・予定を返すときに、問い合わせたユーザーの予定だけ集計して返す というようにした方が簡単な気がするのですが、これではだめなのでしょうか?
SN____R

2021/05/21 13:02

それでももちろん大丈夫なのですが、やり方が分からなくて...
退会済みユーザー

退会済みユーザー

2021/05/21 13:32 編集

スプレッドシートの肥大化をあえて避けているのかと思いました。であれば、予定登録フォームに紐付けたスプレッドシート経由で作ればよさそうですね。 フォーム呼び出し時にユーザーIDをデフォルトでセットしておけばユーザーを区別できます。
SN____R

2021/05/21 13:34

フォーム呼び出し時にユーザーIDをセットする とは、具体的にどこの部分を書き換えるといいのでしょうか...
退会済みユーザー

退会済みユーザー

2021/05/21 13:56 編集

form作成のときにentryという番号がわかるので、その番号を指定する形ですね。といっても文章だとわかりづらいので画面キャプチャを用意してます
SN____R

2021/05/21 13:52

やはり、厳しいのでしょうか...
退会済みユーザー

退会済みユーザー

2021/05/21 13:57

すみません、時間かかると思うので気長にお待ちください・・・
SN____R

2021/05/21 13:58

なるほど!わざわざありがとうございます。
Tatsunosuke

2021/05/21 14:29

なるほど!フォームにパラメータの手がありましたね!qnoirさんお見事!
退会済みユーザー

退会済みユーザー

2021/05/21 14:33

説明サイトのリンクありがとうございます。まさにそれですね
SN____R

2021/05/21 14:43

御二方のお陰でentryという番号を取得する手順は大体理解したのですが、その番号を指定する方法が分からず(というか、それを取得した後のユーザーの区別の仕方というのでしょうか)また行き詰まってしまいました... キャプチャを撮っていただけたりと本当に助かっているので、どうかもう少しだけ初心者にお付き合い頂けると幸いです...
guest

回答2

0

ベストアンサー

ソースは下記のようになります。(reply()関数)
[05/23 10:40] getSchedTime()関数を追加、reply関数の後半を修正
※フォームに紐付けたスプレッドシートのメニューの ファイル→「スプレッドシートの設定」で、
タイムゾーンを「(GMT+0900) Tokyo」に設定しておくこと)

diff

1 2function getSchedTime(date, time) { 3 return new Date( 4 Utilities.formatDate(new Date(date), "JST", "yyyy-MM-dd") + 5 " " + Utilities.formatDate(new Date(time), "JST", "HH:mm") + "+09:00" 6 ); 7} 8 9function reply(data) { 10 var postMsg = data.message.text; 11 var replyToken = data.replyToken; 12 var replyText = ""; 13 var userId = data.source.userId; 14 15 if (postMsg == "登録") { 16 // entry.zzzzzzはユーザーIDのフォームフィールドの番号。 17 replyText = 18 "予定の登録はこちら\n" + 19 `https://docs.google.com/forms/d/1XXXXXXXXXX/viewform?usp=pp_url&entry.zzzzzz=${userId}`; 20 } else if (postMsg == "今後の予定") { 21 var spreadsheet = SpreadsheetApp.openById("XXXXXXXXXX"); 22 var sheet = spreadsheet.getActiveSheet(); 23 24 var today = new Date(Utilities.formatDate(new Date(),"JST", "yyyy-MM-dd 00:00:00+09:00")) 25 // スプレッドシートのデータを一括取得 26 var allRecords = sheet.getRange(2, 1, sheet.getLastRow()-1, 7).getValues(); 27 // ユーザID が一致しかつ当日以降のものだけ抽出し、日付順に並び替え。 28 var records = allRecords 29 .filter(e => e[3] == userId && e[2] >= today) 30 .sort((a, b) => getSchedTime(a[2], a[6]) - getSchedTime(b[2], b[6])); 31 32 // 日付をフォーマットし、予定と一緒に配列化。 33 var value = records.map(e => { 34 var date = Utilities.formatDate(new Date(e[2]), "JST", "yyyy/MM/dd"); 35 var time = Utilities.formatDate(new Date(e[6]), "JST", "HH:mm"); 36 return `・${e[1]} (${date} ${time})\n\n` 37 }); 38 39 if (value.length > 0) replyText = value.join("") + "忘れないようにしましょう!"; 40 else replyText = "予定がありません。"; 41 } 42 43【以下略】

解説

1.フォームの構造

フォームの末尾に、ユーザーID格納用の項目を追加します。(赤枠)
項目名は何でも構いません(「編集禁止」という注意書きを付けておいたほうが良いかもしれません)
イメージ説明

ここでフォームの**ユーザーID項目の番号(entry.zzzzzz(数字))**を、Tatsunosukeさんがコメントに記載していただいた
https://blog.nakachon.com/2016/12/22/how-to-add-url-parameter-for-google-form/
の要領に従ってメモしておきます。

あとはこの項目番号を、reply()ファンクション内のフォーム呼び出しURLに組み込むことで、
LINEのユーザIDがあらかじめ記入されたフォームを呼び出すことが可能になります。
(下記の部分です)

javascript

12 var userId = data.source.userId; 34 if (postMsg == "登録") { 5 // entry.zzzzzzはユーザーIDのフォームフィールドの番号。 6 replyText = 7 "予定の登録はこちら\n" + 8 `https://docs.google.com/forms/d/1XXXXXXXXXX/viewform?usp=pp_url&entry.zzzzzz=${userId}`; 9 } 10

 


2.先のフォーム画像のように作れば、フォームと紐付きのスプレッドシートの構造はこのようになっているはずです。
a列:タイムスタンプ(自動)、b列:入力した予定 c列:入力した日付 d列:ユーザID

イメージ説明

スプレッドシートのD列には、LINEから「登録」と打って予定登録フォームを呼び出した時に自動的に付けられたLINEのユーザーIDが入っているわけですから、
予定を呼び出すときは、このIDを元に取捨選択すればよいということになります。

var records = allRecords .filter(e => e[3] == userId && e[2] >= today) .sort(~~略~~)

この「e[3] == userId」の部分が「D列が、その予定を呼び出したユーザーIDと等しいかどうか」を比較している部分になります。


 

・現状の問題点
フォーム入力時に、useridを変えられたり削除されたりしてしまうと、上記の仕組みがうまく動きません。
→これは、userid項目を隠すことで対応できますが、隠すにはフォームを自作する必要があり、難易度が高いです。
現状、「useridを変えたり消したりすると動作しません」と注意喚起しておく必要があります。

 

コメントでの依頼分:当日も含めて表示&時刻追加とのことだったので日付取得部分を下記のように変更しました。
(回答前半に記載コードを参照)

js

1// getSchedTime()関数を追加 2function getSchedTime(date, time) { 3 return new Date( 4 Utilities.formatDate(new Date(date), "JST", "yyyy-MM-dd") + 5 " " + Utilities.formatDate(new Date(time), "JST", "HH:mm") + "+09:00" 6 ); 7} 8 9//reply関数後半を変更 10function reply(data) { 11【略】 12... 13... 14 // スプレッドシートのデータを一括取得 (時刻データがある7列目まで取得するように修正) 15 var allRecords = sheet.getRange(2, 1, sheet.getLastRow()-1, 7).getValues(); 16 // ユーザID が一致しかつ当日以降のものだけ抽出し、日付順に並び替え。 17 var records = allRecords 18 .filter(e => e[3] == userId && e[2] >= today) 19 .sort((a, b) => getSchedTime(a[2], a[6]) - getSchedTime(b[2], b[6])); 20 21 // 日付をフォーマットし、予定と一緒に配列化。 22 var value = records.map(e => { 23 var date = Utilities.formatDate(new Date(e[2]), "JST", "yyyy/MM/dd"); 24 var time = Utilities.formatDate(new Date(e[6]), "JST", "HH:mm"); 25 return `${e[1]} (${date} ${time})\n\n` 26 }); 27 if (value.length > 0) replyText = value.join("") + "忘れないようにしましょう!"; 28 else replyText = "予定がありません。"; 29 } 30 31【以下略】 32...

投稿2021/05/21 15:54

編集2021/05/23 01:54
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

SN____R

2021/05/21 16:45

やってみているのですが、entry.zzzzzzの部分をgasに入力しても、botが送信する時にはurlが変わっていて、入力されていない状態のページに飛んでしまいます...何故でしょうか
退会済みユーザー

退会済みユーザー

2021/05/21 17:16

通常のフォームだと、「別の回答を送信」をクリックしたときに、あらかじめ入力値を設定させるのは無理みたいですね。 誤動作防止のために、http://www.fans-google.com/form/f18.htm のやり方で、「別の回答を送信」自体を消すしかなさそうです。
SN____R

2021/05/21 17:23

出来ました!!ですが、スプレッドシートのuseridの項目にそのままuseridと出てきてしまい、今後の予定は反応しないままです...
退会済みユーザー

退会済みユーザー

2021/05/21 17:29 編集

replyText = "予定の登録はこちら\n" + `https://docs.google.com/forms/d/1XXXXXXXXXX/viewform?usp=pp_url&entry.zzzzzz=${userId}`; } のところですが URLのところは二重引用符””ではなくてアクセント記号``で囲んでおられますでしょうか。(アポストロフィ「’」とも異なります) またスクリプトエディタ上、${userId}は、全部半角で入力しているでしょうか? ご確認をお願いいたします。
SN____R

2021/05/21 17:58

${userId} ←この形式で記述するとフォーム上にuserIdが表示されず、entry.zzzzzzのリンク所得時のurlをそのままペーストすることでuserIdという文字列はフォーム上に表示されるが、今後の予定を表示させるをクリックすると、忘れないようにしましょうの一文のみが表示されました。 半角やアクセント記号はコピペしているので、間違ってないかと思われます
退会済みユーザー

退会済みユーザー

2021/05/21 18:20 編集

すみません、 もしかして、「登録」と打って出てきたリンクをタップして出てくるフォームに表示されている useridのところに入っているのは「userid」ではなくて「undefined」ではないでしょうか? であれば考えられるのは下記の2つです。 ・finction reply()の冒頭で var userId = data.source.userId; が抜けている。(変数を定義していないため、undefinedになる) または、 userId という変数名の後ろ2文字「Id」が、「id」というように、2つとも小文字になっているか、「ID 」のように2つとも大文字だけになっている。 正しくは、「I」は大文字で、「d」は小文字です。 (大文字・小文字が間違っていると、別変数扱いになるので、undefinedになる)
SN____R

2021/05/21 19:02

上記二つ確認しましたが、ミスはなかったですね...
退会済みユーザー

退会済みユーザー

2021/05/21 23:19 編集

・entry.zzzzzzのリンク取得時のurl をそのままペーストしたときに フォームのuserid欄に表示されるのは「undefined」ではなく、「userId」である、という理解でよろしいでしょうか。 ・修正の度にLINE Dev側のwebhook urlも修正されていますよね? (またはLINE Devのwebhook urlを修正しなくていいようにGASの「デプロイの管理」で、最新バージョンに変えているか) ・`https://docs.google.com/forms/d/1XXXXXXXXXX/viewform?usp=pp_url&entry.zzzzzz=${userId}`; の部分を、 引用符+プラス記号による文字列の連結 "https://docs.google.com/forms/d/1XXXXXXXXXX/viewform?usp=pp_url&entry.zzzzzz=" + userId; に変更してみる あとLINE動作を確認しているのはスマホのLINEアプリということでよろしいでしょうか?(PC版のLINEだとプロフィール情報(useId)を取得できないことがあるため) https://developers.line.biz/ja/docs/messaging-api/user-consent/ 上記も問題ないならば謎です... (こちらでは正常にできており、何等かの環境要因かもしれません) お役に立てず申し訳ありませんが、ユーザーIDではなく、メールアドレス等を使用したアプローチでやっていただく形になります。
SN____R

2021/05/22 04:07

出来ないです...泣 一度ミスがないか、全文を確認していただけないでしょうか...
退会済みユーザー

退会済みユーザー

2021/05/22 04:15 編集

少しお待ちください
SN____R

2021/05/22 04:14

usp=pp_urlの部分を訂正したり、formを新しく作成したところ、完成しました!!! 本当にありがとうございました...!!!!!
退会済みユーザー

退会済みユーザー

2021/05/22 04:16

よかったです。
Tatsunosuke

2021/05/22 04:25

お!解決しましたか!おめでとうございます!頑張ってください!
SN____R

2021/05/22 05:32

qnoirさん、Tastunosukeさん、本当にありがとうございました!
SN____R

2021/05/22 06:11

すみません、1つ書き加えたいなと思ったのでご教授お願い致します。 当日の予定を「今後の予定」で表示させないと、botが自動で通知を送信してくれるまで当日の予定が見れなく、不便だと感じたのですが // ユーザID が一致しかつ当日以降のものだけ抽出し、日付順に並び替え。 var records = allRecords .filter(e => e[3] == userId && e[2] > today) .sort((a, b) => a[2] - b[2]) の > today という部分を = today に書き変えれば大丈夫でしょうか...?
退会済みユーザー

退会済みユーザー

2021/05/22 06:18

「>= today」  としてみてはどうでしょうか(当日「以降」ということなので「>=」)
SN____R

2021/05/22 06:58

var records = allRecords .filter(e => e[3] == userId && e[2] >= today) .sort((a, b) => a[2] - b[2]) に変更しましたが、変わりませんね...他に変更しなければいけない部分があるのでしょうか
退会済みユーザー

退会済みユーザー

2021/05/22 09:45 編集

御所望の動作になるように修正しました。(回答欄参照) (念のため、フォームに紐付けたスプレッドシートのメニューから ファイル→「スプレッドシートの設定」で、 タイムゾーンが「(GMT+0900) Tokyo」になっていることを確認してください)
SN____R

2021/05/22 11:45

出来たのですが、予定が他の人の内容まで纏めて表示されるようになってしまいました...
退会済みユーザー

退会済みユーザー

2021/05/22 11:50

凡ミスでした。修正しました。
SN____R

2021/05/22 11:57

うまく作動しました!ありがとうございます...!!! もう一つ付け加えたいなと思った部分があったのですが、qnoirさんにこれ以上色々聞くのは失礼かもしれないと思ったのですが、この場合は新しい質問として聞いたほうがいいのでしょうか...
退会済みユーザー

退会済みユーザー

2021/05/22 12:20 編集

質問は私は特に構わないのですが、現状、回答欄やコメント欄も長くなってしまっているので、改めて質問を立てられた方がよろしいかと思います。 特に重ねて質問されるのは全く構いませんが、下記のことを考慮いただけると幸いです。 ・私自身も他のことがあるので、回答に時間がかかることは了承願います。 ・プログラムは環境やちょっとした違いで動かなくなることがあります。 同じコードでテストできるのが理想ですが、プライバシー等の問題で現実はできないため、似たような環境、似たようなフォーム・コードを作って試して動かしています。 今回はフォームを作り直していただいてうまく行った感じですが、同じようなコードでも、うまく動かない、原因がわからない、というようなことは多々ありえますので、 そのときはギブアップさせていただくことも御了承ください。 内容によっては、そもそも環境が用意できなかったり、知識がなく回答できない場合もあります。
SN____R

2021/05/22 12:29

ありがとうございます。この質問で最後にし、今後付け加えをしたいと思ったときは改めて質問を建てようと思います。 本題に入るのですが、予定を表示させたときに時刻も表示できればと思ったので、時刻を入力するフォームを作成しました。 時刻自体は一応教えてくれる感じになったのですが、 ・テスト(2021/05/24 12:00) といった形ですべての時刻が12:00と表示されてしまいます。 スプレッドシートのデータを取得するときに何らかの文章を書き加えたらいいのだろうなとは分かったのですが、どこを変えればいいのかわかりませんでした。ご指導のほどよろしくお願いします。 現在のコード↓ var today =new Date(Utilities.formatDate(new Date(), "JST", "yyyy-MM-dd 00:00:00+09:00")) // スプレッドシートのデータを一括取得 var allRecords = sheet.getRange(2, 1, sheet.getLastRow()-1, 4).getValues(); // ユーザID が一致しかつ当日以降(当日含む)の項目だけ抽出し、日付順に並び替え。 var records = allRecords .filter(e => e[3] == userId && e[2] >= today) .sort((a,b) => a[2] - b[2]) // 日付をフォーマットし、予定と一緒に配列化。 var value = records.map(e => `・${e[1]}(${Utilities.formatDate(e[2], "JST", "yyyy/MM/dd hh:mm")})\n\n`);
退会済みユーザー

退会済みユーザー

2021/05/22 12:39 編集

把握しました。 ご質問の内容ですが、すこし難しそう。多分今日中は無理ですので、気長にお待ちください。 下記のキャプチャを質問欄に追加していただくとわかりやすいのですが。 ・時刻入力欄を追加したフォームの画面のキャプチャ画像 ・時刻入力欄を追加した後の回答収集スプレッドシートの画面のキャプチャ画像(2行目以降の内容はダミーデータに置き換えて構いません。要は1列目のタイトル行の並び方がどうなっているか知りたいだけです)
SN____R

2021/05/22 12:53

追記しました。よろしくお願いします。
退会済みユーザー

退会済みユーザー

2021/05/23 01:54

御所望の動作になるように修正しました。(回答欄参照)
SN____R

2021/05/23 02:13

お陰様でしっかり動作することが確認できました!!本当にありがとうございます。 これは新規質問として質問させていただいてるのですが、昨日のuserIdを導入したあたりからpush関数のトリガーがエラーを吐くようになってしまいました。 お手すきの際で大丈夫ですので、新規質問の方原因がわかるようでしたらご回答をお願いしたいです。
guest

0

[追記]
横から口出しのようになってしまいすみません。

①googleフォームにユーザIDという欄を作成する。
②「登録」に対してのリプライで、googleフォームのURLを返す際にentryでユーザIDを入力する。
※ユーザIDは、以下で取得可能。

gas

1function reply(data) { 2 var postMsg = data.message.text; 3 var replyToken = data.replyToken; 4   // ユーザID 5   var userId = data.source.userId 6 var replyText = ""; 7 8  if(postMsg == "登録") { 9   replyText = "予定の登録はこちら\n" + "https://docs.google.com/forms/d/e/***/viewform?entry.***="+userId; 10//↑フォームIDとエントリーの番号を入力 11 } ...

[追記]

①follow時に、ユーザIDに適当な英数字を(認証コード)割り当て、メッセージで予め送っておき、ユーザIDと共にSSに保存しておく。

②GOOGLEフォーム側に認証コードを入力してもらう。
メールアドレスの収集を有効にする。
※google workspaceメンバーは自動で入力されますが、無料GOOGLEeアカウントだと手入力なのでちょっと面倒かも。。。

※認証コード用のフォームと予定入力用は分けてもいいと思います。
=>初めての方用
メールアドレスと認証コードを取得。認証コードと紐付いているユーザIDとメールアドレスを紐付ける。

=>予定入力用
メールアドレスを入力してもらい、ユーザIDを検索する。

になりますかね。。。

もっと簡単にしたいとなると、GOOGLEフォームは色々と制限があり使いにくいのでVUEなどを使って自分でフォームを作っちゃた方が早くて高性能でかっこよく作れます。
学習コストがちょっとかかりますが。。。

検討ください!


トラブルなかったようでよかったです!
まず先にお詫びですが、GASではLINEのメッセージAPIを使用したことはありませんので、
最後までいけるか若干不安はありますが。。。

さて、コードをどうこうの前に、まず処理を分けて試してみるのがいいと思います。

SS = スプレッドシート

①メッセージの送信
②フォロー時に、SSに保存されているユーザIDの保存
③アンフォロー時に、SSに保存されているユーザIDの削除

これはそれぞれは理解できていますか?
できていればOKです。

このようなプログラムを見よう見まねで作成したのですが、予定を表示させたときに、複数人の予定が纏めて表示されてしまいました。

そこで、BOTを追加した人ごとにスプレッドシートを作成して別々に内容を管理したいと考えたのですが行き詰ってしまいました。

ここが悩みということですよね?

④ユーザIDとGOOGLEフォームから投稿された内容を送る「誰か」を紐づける。
まず、GOOGLEフォームから投稿された内容が「誰か」に送るためには、
その[誰]とLINEユーザIDを紐づけるさせる必要があります。

紐づけるにはfollow時に、ユーザIDに適当な英数字を割り当て(ユニークId)メッセージで予め送っておき、ユーザIDと共にSSに保存しておき、ユーザ側にはGOOGLEフォーム入力時にユニークIDを入力してもらう。

GOOGLEフォーム
例)メッセージパスワードを入力してください。 [A8ga3df]

⑤予定を返す
今後の予定と入力があった場合に予定を返すこととなりますが、
ここは簡単だと思います。
詳細なコードは割愛しますが、
1.全てのデータの取得
2.ユニークIdを持った行を見つける
3.2の中の日付が未来のものだけ返す

という3つの作業になります。

gas

1function reply(data) { 2 var postMsg = data.message.text; 3 var replyToken = data.replyToken; 4 var replyText = ""; 5 6 if(postMsg == "登録") { 7 replyText = "予定の登録はこちら\n" + "https://docs.google.com/forms/d/XXXXXXXXXX/edit#responses"; 8 } else if(postMsg == "今後の予定") { 9 var spreadsheet = SpreadsheetApp.openById("XXXXXXXXXX"); 10 var sheet = spreadsheet.getActiveSheet(); 11 12   //ここに記載 13     14 15  16 }

GASやJSは日付の比較や操作が面倒なのでライブラリを入れることをお勧めします。
DAYJS

言っている意味が難しいと感じるようであれば、
まずは焦らずfor文やif分、getValues,setValues、配列と二次元配列、連想配列を自由に使いこなせるように
なってから進めた方が最終的には早く完成すると思います。

頑張ってください!!応援してます!!

投稿2021/05/21 13:08

編集2021/05/21 15:34
Tatsunosuke

総合スコア599

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

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

Tatsunosuke

2021/05/21 13:09

すみません、途中送信してしまいました。少々お待ちを
SN____R

2021/05/21 13:18 編集

承知致しました!わざわざありがとうございます...!
Tatsunosuke

2021/05/21 13:47

僕も、qnoirさんのアドバイスと同じでフォームは分けずに一つでいいと思います!
SN____R

2021/05/21 13:56

気づいていませんでした...! Tatsunosukeさんのおっしゃっている、ユニークIDですが、このやり方ですと一回登録しておけば後は結び付けられるという解釈で合っていますでしょうか? 今後の予定を確認する より予定を確認する時もユニークIDを入力する形なら、少々不便だと感じてしまいました...
Tatsunosuke

2021/05/21 14:07

フォームに入力するときにメールアドレスを必須にしてしまえば、メールアドレス紐付けでいけます! 回答のところにもう少し書きますね
SN____R

2021/05/21 14:14

右も左も分からない初心者にここまで優しくしていただき、本当にありがとうございます...泣
Tatsunosuke

2021/05/21 14:22

GASを広めるためならば!!!
Tatsunosuke

2021/05/21 14:24

あ、予定を確認するときはコードの入力いらないです! lineからこのAPI に飛んでくるとに一緒にユーザIDが含まれてます! あくまで、予定を登録するときだけです!
SN____R

2021/05/21 14:38

拝見致しました。そのような方法があるのですね...本当に参考になります????
SN____R

2021/05/21 15:26

ユーザーIDを入力とのことですが、"https://docs.google.com/forms/d/XXXXX/edit";となっているので、editの後にviewform?からの文字列を貼り付ければ良い感じですかね...? 試して見たのですが、登録を入力すると前回同様urlのみ送信され、今後の予定を入力すると何も送信されなくなってしまいました...どこが間違っていますでしょうか泣
Tatsunosuke

2021/05/21 15:40

https://docs.google.com/forms/d/XXXXX/edit" 後ろが、editになっているのは編集画面のことなので、元のサンプルコードが誤りです。 入力画面は後ろが、viewformになってます。 一部間違えていたので修正しました↓ replyText = "予定の登録はこちら\n" + "https://docs.google.com/forms/d/e/XXXXX/viewform?entry.***="+userId; ***のところに、 エントリの番号入れてやるだけです! https://blog.nakachon.com/2016/12/22/how-to-add-url-parameter-for-google-form/  これみながらフォームだけで自動で入力されるかまず試してみてください!
SN____R

2021/05/21 15:58

入力画面のURLは最後が/viewform?edit_requested=true"になっているのですが、viewform?の後にusp=pp_url&entry.XXXXXXXX=userId と入力すればいいのですかね...
Tatsunosuke

2021/05/21 16:46

edit_requested=true ↑これバッサリ切っていただいて、 viewform?entry.XXXXXXXX=userId でいけます! 上の外部リンクのやり方でコピーするっていうのが出てくると思いますので、コピーしたURLそのままで大丈夫です!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問