見出し画像

実践編:Google Workspace:GAS(App Script)で当番通知➔その②

前に作成したGAS当番通知を1週間1回通知したいと社内で要望が出たので、その修正を紹介したいと思います。

前回の作成したものは ➔ こちら

テストを行う環境を作成

修正、開発で大事な事はテストを短時間で何度も回せる環境を作る事だと考えています。GASの実行は遅いので修正して結果を確認するまで時間がかかります。

今回はNodeJs環境で疑似データを準備してテスト開発していきます。
NodeJsの環境構築は ➔ こちら を参考にしてください

まず前回のコードを確認

function sendChat(msg)
{
  var url = "https://chat.googleapis.com/v1/spaces/xxxxxxxx"

  var message = {'text': msg}
  var options = {
    'method': 'POST',
    'headers': {
      'Content-Type': 'application/json; charset=UTF-8'
    },
    'payload':JSON.stringify(message)
  };
  
  UrlFetchApp.fetch(url, options);
}

function myFunction() {
  
  const mySheet = SpreadsheetApp.getActiveSheet()
  const lastRow = mySheet.getDataRange().getLastRow()
  const values = mySheet.getDataRange().getValues()
  const toDay = new Date();
  
 
  for(let i=0; i < lastRow; i++)
  {
    const name = values[i][0]
    const date = values[i][1]

    if(!date || 
      date.getFullYear() != toDay.getFullYear() ||
      date.getMonth() != toDay.getMonth() ||
      date.getDate() != toDay.getDate()
    )
    {
      sendChat(`今日の当番は${name}です`)
      mySheet.getRange(i+1,2).setValue(toDay)
      break
    }
  }

}

NodeJsで動作するように以下のように修正します

function sendChat(msg)
{
  console.log(msg)
}

const values = [
    ["担当1", null],
    ["担当2", null],
    ["担当3", null],
]

const lastRow = values.length

function myFunction() {
  
//   const mySheet = SpreadsheetApp.getActiveSheet()
//   const lastRow = mySheet.getDataRange().getLastRow()
//   const values = mySheet.getDataRange().getValues()
  const toDay = new Date();
  
 
  for(let i=0; i < lastRow; i++)
  {
    const name = values[i][0]
    const date = values[i][1]

    if(!date || 
      date.getFullYear() != toDay.getFullYear() ||
      date.getMonth() != toDay.getMonth() ||
      date.getDate() != toDay.getDate()
    )
    {
      sendChat(`今日の当番は${name}です`)
    //   mySheet.getRange(i+1,2).setValue(toDay)
      values[i][1] = toDay
      break
    }
  }

  console.log(values)
}

myFunction()

↑スプレッドシートからデータを取得してる箇所を const values = …
で疑似データを用意しています。 sendChat はログを表示するだけです。
mySheet.getRange(i+1,2).setValue(toDay) スプレッドシートの設定処理は valuesに直接データを設定します。

実行すると以下のようになります

今日の当番は担当1です
[
  [ '担当1', 2023-02-24T07:20:35.923Z ],
  [ '担当2', null ],
  [ '担当3', null ]
]

ひとまず環境ができました。

toDay も擬似データにして1週間に一度呼ばれたようにしてみます

function sendChat(msg)
{
  console.log(msg)
}

const values = [
    ["担当1", null],
    ["担当2", null],
    ["担当3", null],
]

const lastRow = values.length

function myFunction(toDay) {
  
//   const mySheet = SpreadsheetApp.getActiveSheet()
//   const lastRow = mySheet.getDataRange().getLastRow()
//   const values = mySheet.getDataRange().getValues()
//   const toDay = new Date();
  
 
  for(let i=0; i < lastRow; i++)
  {
    const name = values[i][0]
    const date = values[i][1]

    if(!date || 
      date.getFullYear() != toDay.getFullYear() ||
      date.getMonth() != toDay.getMonth() ||
      date.getDate() != toDay.getDate()
    )
    {
      sendChat(`今日の当番は${name}です`)
    //   mySheet.getRange(i+1,2).setValue(toDay)
      values[i][1] = toDay
      break
    }
  }

  console.log(values)
}


for(var i=0; i < 3; i++)
{
    const toDay = new Date(2023,2-1,1 + i * 7, 16, 01)
    myFunction(toDay)
}

7日ステップで3回呼び出していきます結果は、1番目の担当者がずっと呼ばれています。

今日の当番は担当1です
[
  [ '担当1', 2023-02-01T07:01:00.000Z ],
  [ '担当2', null ],
  [ '担当3', null ]
]
今日の当番は担当1です
[
  [ '担当1', 2023-02-08T07:01:00.000Z ],
  [ '担当2', null ],
  [ '担当3', null ]
]
今日の当番は担当1です
[
  [ '担当1', 2023-02-15T07:01:00.000Z ],
  [ '担当2', null ],
  [ '担当3', null ]
]

プログラムの修正

修正していきます。

function sendChat(msg)
{
  console.log(msg)
}

const values = [
    ["担当1", 0],
    ["担当2", null],
    ["担当3", null],
]

const lastRow = values.length

function myFunction() {
  
//   const mySheet = SpreadsheetApp.getActiveSheet()
//   const lastRow = mySheet.getDataRange().getLastRow()
//   const values = mySheet.getDataRange().getValues()
//   const toDay = new Date();
  
    let index = values[0][1]

    if(index == null || index == undefined)
        index = 0

    if(index >= lastRow)
        index = 0
    const name = values[index][0]
    sendChat(`今日の当番は${name}です`)
    
//  mySheet.getRange(1,2).setValue(index+1)
    values[0][1] = index+1
}


for(var i=0; i < 10; i++)
{
    myFunction()
}

Dateによる日付比較を廃止して、現在何番目の人が担当かを保存するようにしました。日付で処理すると何周も実行できない、途中で間に人が増えたらなど問題がいろいろありました。

実行結果。何度 繰り返しても問題ありません。

今日の当番は担当1です
今日の当番は担当2です
今日の当番は担当3です
今日の当番は担当1です
今日の当番は担当2です
今日の当番は担当3です
今日の当番は担当1です
今日の当番は担当2です
今日の当番は担当3です
今日の当番は担当1です

GASに戻す

次にGASで動作する形に戻します。

function sendChat(msg)
{
  var url = "https://chat.googleapis.com/v1/spaces/AAAAIFV92vw/messages?key=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI&token=Ky0XWTUHdnnpmyRmZma4mcRunYuZ-zKpwkYvbKGMQMw%3D"

  var message = {'text': msg}
  var options = {
    'method': 'POST',
    'headers': {
      'Content-Type': 'application/json; charset=UTF-8'
    },
    'payload':JSON.stringify(message)
  };
  
  UrlFetchApp.fetch(url, options);
}

function myFunction() {
  
  const mySheet = SpreadsheetApp.getActiveSheet()
  const lastRow = mySheet.getDataRange().getLastRow()
  const values = mySheet.getDataRange().getValues()

  let index = values[0][1]

  if(index == null || index == undefined)
      index = 0

  if(index >= lastRow)
      index = 0

  const name = values[index][0]
  sendChat(`今日の当番は${name}です`)

  mySheet.getRange(1,2).setValue(index+1)

}

トリガー設定

実行トリガーを1週間に1度に修正します

これで完成!

お詫び

今回は毎日➔1週間にした修正でしたが、そもそも毎日の場合にも最初の担当者が永遠に呼ばれる不具合があったと思います。反省、、、
タイマーをトリガーにしたプログラムは疑似的な日付データを使ってテストする事が重要ですね。

この記事が気に入ったらサポートをしてみませんか?