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

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

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

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

Google Apps Script

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

Q&A

解決済

1回答

117閲覧

スプレッドシートのminuteのセルから正しい値を取り出すことができない

g4367

総合スコア1

Google スプレッドシート

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

Google Apps Script

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

0グッド

0クリップ

投稿2025/01/12 06:45

実現したいこと

特定の時刻になったらgmailを送るものをつくろうとしています。
特定の時刻が複数あるので、GASのトリガーではなくGoogleスプレッドシートでnow関数を用いています。
now関数からhourとminuteで時と分を表示するセルをそれぞれ用意しています。その二つの値が表で用意している時刻表群と等しいものがあれば、それ以降の、gmailを送るプログラムが動くようにしています。

発生している問題・分からないこと

実現したいことで説明した、minute関数を用いて分を表示しているセルの値を変数hourに"const"を用いて格納した際に、実際にセルで表示されている分の値とhourが異なってしまいます。これは、下のソースコードの"console.log"で確認しています。
"const"を"var"に変えてもセルの値とhourが異なっています。
minute関数になっていない定数のセルから数値を正しく読み取ることは可能でした。
minute関数となっているセルの値を「=(セルの番号)」でそのまま置換するセルを用意して、それをhourとして読み取る形にしても、minuteのセルと「=(セルの番号)」の2つは同じ値が表示されますが、hourとは値が異なってしまいます。
now関数があるスプレッドシートは、更新時と分ごとに値が更新されるようになっています。
上記のような場合で、値が異なってしまう理由を教えてください。

該当のソースコード

Google

1function sendConditionalEmails() { 2 const spreadsheet = SpreadsheetApp.openById("1ujn3YC5CG0T_p4LpkNPq50Sq9D7BOnP74odvJsXk-e4"); 3 4 // timeシートからデータを取得 5 const timeSheet = spreadsheet.getSheetByName("time"); 6 const month = timeSheet.getRange("B4").getValue(); 7 const day = timeSheet.getRange("C4").getValue(); 8 const hour = timeSheet.getRange("D4").getValue(); 9 const minute = timeSheet.getRange("E4").getValue(); 10 11 // 変数の値を確認 12 console.log(month) 13 console.log(day) 14 console.log(hour) 15 console.log(minute) 16 17 // class_timeシートのデータを取得 18 const classTimeSheet = spreadsheet.getSheetByName("class_time"); 19 const classTimeData = classTimeSheet.getDataRange().getValues(); 20 21 // hourと一致する行を検索 22 let i = -1; 23 for (let row = 1; row < classTimeData.length; row++) { 24 if (classTimeData[row][1] === hour) { // B列の値と一致 25 i = row + 1; // 行番号を取得 (1ベース) 26 break; 27 } 28 } 29 30 if (i === -1) { 31 Logger.log("hourと一致する値が見つかりません。プログラムを終了します。"); 32 return; 33 } 34 35 // minuteと一致するか確認 36 const classTimeMinute = classTimeSheet.getRange(i, 3).getValue(); // C列 37 if (classTimeMinute !== minute) { 38 Logger.log("minuteと一致しません。プログラムを終了します。"); 39 return; 40 } 41 42 // A列の値をperiodに代入 43 const period = classTimeSheet.getRange(i, 1).getValue(); 44 45 // 繰り返し処理の準備 46 const classPlanSheet = spreadsheet.getSheetByName("class_plan"); 47 const memberSheet = spreadsheet.getSheetByName("member"); 48 const mailSheet = spreadsheet.getSheetByName("mail"); 49 const classPlanData = classPlanSheet.getDataRange().getValues(); 50 const memberData = memberSheet.getDataRange().getValues(); 51 52 const noc = 5; 53 let rep = 1; 54 55 while (rep <= noc) { 56 const planMonth = classPlanData[rep - 1][0]; // A列 57 const planDay = classPlanData[rep - 1][1]; // B列 58 const planPeriod = classPlanData[rep - 1][2]; // C列 59 const planStatus = classPlanData[rep - 1][4]; // E列 60 61 // 条件を満たさなければ次のrepに進む 62 if (planMonth !== month || planDay !== day || planPeriod !== period || planStatus !== 0) { 63 rep++; 64 continue; 65 } 66 67 // 条件を満たした場合 68 const id = classPlanData[rep - 1][3]; // D列 69 i = -1; 70 71 // memberシートでidを検索 72 for (let row = 1; row < memberData.length; row++) { 73 if (memberData[row][0] === id) { // A列の値と一致 74 i = row + 1; // 行番号を取得 (1ベース) 75 break; 76 } 77 } 78 79 if (i === -1) { 80 Logger.log(`memberシートにID ${id} が見つかりません。(rep: ${rep})`); 81 rep++; 82 continue; 83 } 84 85 // メール情報をセット 86 const recipient = memberSheet.getRange(i, 4).getValue(); // D列 87 mailSheet.getRange("B1").setValue(recipient); 88 const subject = mailSheet.getRange("B2").getValue(); 89 let body = mailSheet.getRange("B3").getValue(); 90 91 // $1, $2, $4の置換 92 const memberB = memberSheet.getRange(i, 2).getValue(); // B列 93 const memberC = memberSheet.getRange(i, 3).getValue(); // C列 94 body = body.replace("$1", memberB).replace("$2", memberC).replace("$4", period); 95 96 // メール送信 97 if (recipient && subject && body) { 98 GmailApp.sendEmail(recipient, subject, body); 99 Logger.log(`メールを送信しました。(rep: ${rep})`); 100 } else { 101 Logger.log("メール送信に必要な情報が不足しています。"); 102 } 103 104 // mailシートのB1に"$4"をセット 105 mailSheet.getRange("B1").setValue("$4"); 106 107 // repを1増やす 108 rep++; 109 } 110} 111 112

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

「わからないことや発生している問題を教えてください」に書いた通りです。
また、検索してもminuteが原因で値が正しく」読み取れない理由はわかりませんでした。

補足

最後に、今回初めてGASに触れたため至らないところが多いとは思いますが、よろしくお願いします。

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

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

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

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

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

patapi

2025/01/12 07:25

文章だけだとわからないので、スプレッドシートの共有リンクを貼ってください。 > 、minute関数を用いて分を表示しているセルの値を変数hourに"const"を用いて格納した際に、実際にセルで表示されている分の値とhourが異なってしまいます。これは、下のソースコードの"console.log"で確認しています。 > minute関数となっているセルの値を「=(セルの番号)」でそのまま置換するセルを用意して、それをhourとして読み取る形にしても、minuteのセルと「=(セルの番号)」の2つは同じ値が表示されますが、hourとは値が異なってしまいます。 ここの意味が分かりません。なぜminuteの値をhourに入れなければいけないでしょうか?
g4367

2025/01/12 07:31

対応していただきありがとうございます。 初めに話しておくと、minute関数のセルの値をhourに格納しているというのは自分の間違いです。 申し訳ございません。 正しくはスプレッドシートのminute関数のセルの値をGAS上の変数minuteに格納しています。 URLは少々お待ちください。 個人情報を入力してしまっているため少し編集します。
patapi

2025/01/12 07:42

スクリプトが紐ついているファイルと、スクリプトの2行目の openById() で指定しているファイルが異なるようですが、それでいいのですか? もし、そのスクリプトが紐ついているファイルを指定したいならば、 2行目の const spreadsheet = SpreadsheetApp.openById(~);の行を const spreadsheet = SpreadsheetApp.getActive(); に変更して実行してみて下さい。
YAmaGNZ

2025/01/12 07:46

最終的にやりたいことというのは現在日時を取得したいということになるのでしょうか? もしそうなのであればシートに現在日時を格納するセルを設けるのではなく var d = new Date(); var mon = d.getMonth() + 1; var d2 = d.getDate(); var h = d.getHours(); var min = d.getMinutes(); といった感じでGASで取得すればいいのではないでしょうか?
g4367

2025/01/12 07:55

まずkotori_aさんの方に返信します。 コメントありがとうございます。 紐づいているプログラムが異なるのは、私のミスです。申し訳ございません。 ここで共有するためにここでプロジェクトをコピーしたあと、URLを変更し忘れたために起きてしましました。 そのうえで、指定されたとおりに修正し、実行してみましたが変数minuteの値がセルの値と異なってしまいます。 申し訳ございませんが、うまく動きません。
patapi

2025/01/12 08:04 編集

自分の環境ではうまく動きましたが、いろいろ検索すると、GASのバグ?のせいで、スプレッドシート上では更新されているはずの値が、プログラムで読み取れないことがあるみたいです。なので回答に解決策を記載しました。
g4367

2025/01/12 08:08

YAmaGNZさんの方に返信します。 コメントありがとうございます。 GAS内で時間を読み取ってしまうという方法は自分の頭にはなく、大変参考になりました。ありがとうございます。 そのうえで、申し訳ございませんがセルの読み取りが更新されないのはバグであることを教えていただいたことが、自分の中により納得感があるため、こちらをベストアンサーに選ばせていただきたいと思います。 対応してくださって、本当にありがとうございました。
g4367

2025/01/12 08:15

kotori_aさんの方に返信します。 対応ありがとうございます。 問題の原因を聞き、とても納得できました。 今後は、GASでセルの値を読み取ることはできるだけ避けたいと思いました。 あらためて、ありがとうございました。
patapi

2025/01/12 08:20

解決されたのであればよかったです!
guest

回答1

0

ベストアンサー

自分の環境では正常に動きましたが、ネットを検索したところ、たまにスクリプトが読み取るシート内容が更新されていないというバグが発生することがあるみたいです。
(SpreadsheetApp.flush() を使っても更新されないとのこと)

下記のように、シートから読み取るのではなく、Date()関数を使って、スクリプト内で直接、日付時刻を取得すれば解決すると思います。

※この場合、シートの方の表示更新は遅いため、シートの表示とプログラム実行時にコンソールに表示される時刻が若干異なる場合があります。
ただし、下のプログラムでは、「プログラムを実行した時点」の日付時刻を正しく取得しています。

function sendConditionalEmails() { const spreadsheet = SpreadsheetApp.getActive(); // --------以下は削除--------- // const timeSheet = spreadsheet.getSheetByName("time"); // timeシートからデータを取得 //const timeSheet = spreadsheet.getSheetByName("time"); //const month = timeSheet.getRange("B4").getValue(); //const day = timeSheet.getRange("C4").getValue(); //const hour = timeSheet.getRange("D4").getValue(); //const minute = timeSheet.getRange("E4").getValue(); // -----------削除ここまで---------- // 念のためFlushする SpreadsheetApp.flush(); // スクリプトで直接、日付時刻を取得する。 const [month, day, hour, minute] = Utilities.formatDate(new Date(), 'Asia/Tokyo','MM,dd,HH,mm').split(',').map(e=>parseInt(e)); // 変数の値を確認 console.log(month) console.log(day) console.log(hour) console.log(minute)

投稿2025/01/12 08:00

編集2025/01/12 08:06
patapi

総合スコア874

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

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

g4367

2025/01/12 08:11

対応ありがとうございます。 問題の原因とそれに対する対処法のどちらも大変参考になりました。 したがって、ベストアンサーに選ばせていただきます。 他の対応してくださった方にもとても感謝しています。 みなさま、本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.34%

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

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

質問する

関連した質問