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

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

ただいまの
回答率

88.57%

誕生日に自動でメール送信してくれるスプレッドシートを作成したい

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 233

下記の記事を参考にして、GASを組んでみたのですが、タイプエラーが表示されます。
原因がどうしてもわからないので、わかる方いたら教えてほしいです。

http://tech.innovation.co.jp/2016/11/24/G-A-S.html

TypeError: values[i][2].getDate is not a function(行 19、ファイル「コード」)
A列   B列   C列   D列       E列   
名前    生年月日    日付    メールアドレス    件名    

内容は別シートに「本文」というものを作成しています。

何卒よろしくお願いいたします。

function myFunction() {
  var sh_id             = SpreadsheetApp.openById('???')  //  どのシートを使うか指定
  var rows              = sh_id.getDataRange(); 
  var num_rows          = rows.getNumRows();
  var values            = rows.getValues(); //rowsにセルの情報、num_rowsに値が入っているセルの最大列数、valuesにセルに入っている値の情報が入る。

  var today             = new Date();
  var this_day          = today.getDate();
  var this_month        = today.getMonth() + 1;   //今日の日付を取得

  var name              = "";
  var to                = "";

  var subject           = sh_id.getRange("E2").getValue(); //タイトル


  //ループ処理
    for(var i = 1;i < num_rows;i++){
    var birthday    = values[i][2].getDate();
    var birthmonth  = values[i][2].getMonth() + 1;
    const FullName        = sh_id.getRange(i,0).getValue(); //名前

  //誕生日であればメール送信
    if(birthday == this_day && birthmonth == this_month){
      name = values[i][0];
      to   = values[i][3];
      if(values[i][4] != ""){
        subject = values[i][4];
      }
    }
  }

  const text = sheet.getSheetByName('本文').getRange(1,1).getValue; //本文
  const body = text
  .replace(/{名前}/g,FullName)

  // 出力
  if (to != ""){
    body += name + "\n" + body;
    GmailApp.sendEmail(to, subject, body);
  }
  }
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • sawa

    2020/09/10 14:16

    values[i][2] は C列の日付の値だと思いますが、 日付の形式になってますか?

    キャンセル

  • Hogeike

    2020/09/10 15:23

    > タイプエラーが表示されます。
    エラー内容も書きましょう

    キャンセル

  • macaron_xxx

    2020/09/10 15:25

    >Hogeike
    書いてありますよ。見にくいですけど。

    キャンセル

回答 1

checkベストアンサー

+1

  • 質問中のエラーは、「日付」の値が日付(数値の一種)と認識されていないため。日付になり得る文字列なら、new Date()の引数に指定してやればいい。
  • スプレッドシートIDを指定して得られるのは、シートではなく(シートの集合としての)スプレッドシートのオブジェクト。ここから直接getRangeすると、最初のシートが対象となる。しかし、スプレッドシートに対するgetRange引数のバリエーションが少ないので、質問のコードのような(行番号, 列番号)の指定はできない。
  • また、提示されたリンク先のページでは、本文は同じシートに書かれているが、質問では別のシート「本文」のA1を参照するので、このスプレッドシートは2つのシートを持つはず。こういうときは、シートごとのオブジェクトを取得して操作したほうがいい。getRangeのバリエーションも豊富だ。
  • 以下のコードでは、名前・誕生日・メールアドレスなどのリストが書かれたシートを(便宜的に)「シート1」としている。もっとふさわしいシート名を付けているなら、getSheetByNameの引数を変更すること。このシートのオブジェクトをsheet1として取得し、リスト全体をvaluesに読み込んでいる。
  • 「本文」シートのオブジェクトはsheet2として取得し、A1セルに書かれた本文をtextに読み込んでいる。そういえば、件名のデフォルト値(リストの書かれたシートのE2セルの値を利用している)も、こっちのB1とかA2とかに書いた方がいいのでは?
  • forループでは、「日付」の値から月・日の値を読み取り、今日の月・日と一致する場合のみメール送信の処理を行なう。そういえば、どこにも「生年月日」の値は使っていないが何のためにあるのかな?
  • メール送信処理では、名前、メールアドレス、(個別の)件名をリストから読み取り、メール本文を(名前を置換する処理なども含めて)生成してから、メールを送信している。元のコードでは名前をシートから読み取っていたが、リスト全体を読み込んだvaluesに名前も含まれるので、そちらを使うほうが高速だ。
function myFunction() {
  const spreadsheet = SpreadsheetApp.openById('(スプレッドシートIDを指定)')

  const sheet1 = spreadsheet.getSheetByName('シート1');
  if (sheet1 === null) {
    console.log('名前や誕生日を記録したシート名を正しく設定してください');  
  }
  const range = sheet1.getDataRange();
  const num_rows = range.getNumRows();
  var values = range.getValues();
  const default_subject = sheet1.getRange("E2").getValue();

  const sheet2 = spreadsheet.getSheetByName('本文');
  if (sheet2 === null) {
    console.log('本文をA1セルに書いたシート名を正しく設定してください');  
  }
  const text = sheet2.getRange(1,1).getValue();

  const today = new Date();
  const this_day = today.getDate();
  const this_month = today.getMonth() + 1;

  for (var i = 1; i < num_rows; i++) {
    var birthDate   = new Date(values[i][2]);
    var birthday    = birthDate.getDate();
    var birthmonth  = birthDate.getMonth() + 1;

    if (birthday !== this_day || birthmonth !== this_month) {
      continue;
    }

    var name = values[i][0];
    var to = values[i][3];
    if (to === "") {
      continue;
    }
    var subject = values[i][4];
    if(subject === ""){
      subject = default_subject;
    }

    var body = text.replace(/{名前}/g, name);
    body = name + "さん\n\n" + body;

    GmailApp.sendEmail(to, subject, body);
  }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/09/10 16:16

    そういえば、リンク先のサイトのスクリプトは何故か「同じ誕生日の人が複数いる場合に未対応だったが、こちらは対応済み。

    キャンセル

  • 2020/09/10 17:03

    本当にすごいですね!!!
    ありがとうございます!!!!!!
    大変感謝です

    キャンセル

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

  • ただいまの回答率 88.57%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る