見出し画像

【GAS活用術⑩】過ぎた日付の予定行を「毎日」自動的に削除・移動する

Google Apps Script (GAS)を、もっと身近に、日々の暮らしに。

今回は、以下のような予定表で、予定の日付が過ぎたら、その予定行を削除・移動する方法についてです。

上記の「日付」、「区分」、「予定」と3列だけのシンプルな予定表ですが、これを私は以下のようにフル活用しています。

このフルフルに活用している予定表ですが、以前は、過去日付の予定行を手動で削除していました。月に数回程度だし、まぁ、いいかと。。

が、最近になって、それまで裏方だったこの予定表を、表舞台となるサイトで表示するようになり、ようやく自動的に過去日付の予定行を削除したり、移動したりするGASについて考えることにしました。

これが、単純なようで、意外に深かったので、備忘録をかねて記事として残しておくことにします。

今回は「毎日」チェックバージョン

今回は、削除・移動すべき予定があるか毎日、チェックすることを考えてみます。

もちろん、毎日チェックするのは私ではなく、GASです。正確には、日付ベースのトリガーを設定して、毎日、同じ時間帯に、GASの関数(対象の予定があるかをチェックして、条件にあえば予定行を削除・移動する)が実行されるようにします。

過去日付の予定行を「削除」するなら

削除と移動の2パターン紹介しますが、先に削除する方を説明していきます。

具体的に、「毎日、夜中の1~2時に起動するトリガーを設定して、朝起きたら、昨日の予定データが消えている」、これを実現するにはどうしたらいいか考えてみましょう。

予定表は日付順に並んでいて、かつ、毎日、古くなった予定データは削除されることを前提とすると、一番上の日付データだけ、削除すべきかどうかチェックすればよいことになります。

この予定表でいえば、日付データはA列にあり、1行目のヘッダー行は除くので、A2のセルの日付データを見て、過去日付かどうか判断し、過去日付であれば2行目だけを削除すればいいわけです。

この時、まず気を付けたいのが、予定表の2024/06/05(水)の日付は2024/06/05 00:00:00と、実際は時間を含む日時データとして認識されることです。

そのため、例えば、トリガーが実行されるのが2024/06/05の午前1時~2時だとしたら、予定表の2024/06/05(水)は2024/06/05 00:00:00と認識されるので、単純にトリガーの実行日時と予定の日付と比較すると、予定表の2024/06/05(水)の方が古いと判断され、削除対象となってしまいます。

つまり、夜中の1時〜2時に、肝心の当日の予定を削除することになり、朝起きたら当日の予定が消されている!?という事態に陥ります。

それではまずいので、トリガーが実行された日時を一日前にずらして、それより過去のデータであれば削除する、ということにします。

もし、少し余裕を持たせて、予定日を3日過ぎてから消したいのであれば、4日前の日付にしてから削除する、という風に考えればいいわけですね。

ということで、この場合のGASは以下のような感じになります。

function deleteOldPlan(){           //古くなった予定行を削除
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sh = ss.getSheetByName("予定表");          //「予定表」シートを取得
  const date = new Date();          //トリガー実行時の現在日時を取得
  date.setDate(date.getDate() -1);  //1日前の日付に変更
  const planDate = sh.getRange(2,1).getValue();   //A2セルの値を取得

  if ( planDate !== '' && planDate < date ) {
    sh.deleteRow(2);           //2行目を削除
    //ここにこのタイミングで実行したい関数があれば記述する
    //updateDateList();          //フォームのプルダウンの日付の選択肢を更新
  }
}

予定表にまったく予定がない場合のことも考えて、if文の条件として”A2セルが空白でない”「planDate !== ''」も追加しています(私の所属する読み聞かせボランティアの活動は、小学校が夏休みなど長期休暇の時は、一か月ほどお休みになることもあります)。

1行のみ削除する場合は、deleteRowメソッドで。削除する行番号の2を指定します。

また、コメントアウトしていますが、もし予定データを削除した後、何らかの関数を実行をしたい場合は、if文の中に入れておきます。

私の場合、予定表の日付データから、フォームのプルダウンの選択肢を生成しているので、updateDateList() という関数をコールしています(詳細は【GAS活用術⑦-2】を参照)。

後は、このdeleteOldPlan関数を、毎日、深夜1~2時に自動実行されるトリガーを仕込んでおけば、朝起きたら、古い予定が消えてるわけですね。

過去日付の予定行を別シートに「移動」するなら

上ではざくっと予定を削除しましたが、場合によってはその予定を別シートに残しておきたいときもあると思います。

次は、「毎日、夜中の1~2時に起動するトリガーを設定して、朝起きたら、昨日の予定データが別のシートへ移動している」を考えてみます。

まず、移動先のシートを用意しましょう。基本的には「予定表」シートをコピーして、ヘッダー行だけ残して、データ行のデータを消去して、シート名を「アーカイブ」などわかりやすい名前に変えておけばOKです。

続けて、GASのコードですが、実はこれ、削除バージョンを少し変更するだけでいけます。

というのは、移動といいましたが、実際は、対象データを、移動先のシートへコピーし、その後、元のデータを削除することになります。コピー+削除=移動、ってことですね。

はじめ、moveRowsメソッドが使えるかと思いましたが、パラメータの指定方法が複雑な上に、移動先が同じシートでないと駄目なようです。

調べた結果、セル範囲のデータを別のセル範囲にコピーする、copyToメソッドの使い勝手がよさそうです。使用方法は、図にすると、↓こんな感じです。

getValuesしてsetValuesする必要はなく、「コピー元の範囲.copyTo(コピー先の範囲)」でOKとのこと。これだけで、値と書式設定の両方をコピーしてくれます。

なお、リファレンスには、コピー先の範囲指定では、「左上のセル位置のみ有効です」とあり、初めは?と思いましたが、左上のセルの位置だけ指定すれば、コピー元の範囲にあわせてペーストしてくれるようです。うーん、便利。

ということで、以下が移動(コピー+削除)バージョンのGASのコードです。

function moveOldPlan(){                     //古くなった予定行を別シートへ移動
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const org_sh = ss.getSheetByName("予定表");      //「予定表」シートを取得
  const arc_sh = ss.getSheetByName("アーカイブ");  //「アーカイブ」シートを取得
  const date = new Date();                 //トリガー実行時の現在日時を取得
  date.setDate(date.getDate() -1);         //1日前の日付に変更
  const planDate = org_sh.getRange(2,1).getValue();   //元シートのA2セルの値を取得

  if ( planDate !== '' && planDate < date ) {
    const lastCol = org_sh.getLastColumn();     //元シートの最終列を取得
    const arc_lastRow = arc_sh.getLastRow();    //アーカイブ先シートの最終行を取得

    //元シートの2行目の範囲を取得後、copyToでアーカイブ先シートの最終行+1のA列のセルにコピー
    org_sh.getRange(2,1,1,lastCol).copyTo(arc_sh.getRange(arc_lastRow+1,1));

    //アーカイブ先シートの交互の背景色を拡張させるために一行挿入
    arc_sh.insertRowAfter(arc_lastRow+1);    

    org_sh.deleteRow(2);           //2行目を削除
    //ここにこのタイミングで実行したい関数があれば記述する
    //updateDateList();          //フォームのプルダウンの日付の選択肢を更新
  }
}

コピー部分が追加されているので、削除バージョンよりは長くなりましたが、結構、共通している所は多いと思います。

このmoveOldPlan関数を、日付ベースのトリガーを設定して、毎日、同じ時間帯に実行するようにすれば、朝起きたら昨日の予定がアーカイブシートに移動していて、予定表シートには常に次の予定が一番上に来ているわけです。

夜中に小人(こびと)さんが、せっせと過日付の予定を別シートに移動してくれてるようなイメージをもつのは、私だけでしょうか。。

こんな仕組みを無料で提供してくれるGoogleさん、本当に素晴らしいです。

おわりに

今回の内容に興味があるのは、まったくのGAS初心者ではないと思ったので、おもいきってGASの登録方法や実行方法、プロジェクトの承認方法、トリガーの設定方法などは省いちゃいました。

必要でしたら、下記の記事など参考にしてください。
GASの登録方法や実行方法、プロジェクトの承認方法は、↓こちら。

トリガーの設定については、↓こちら。

次回は、「毎日」ではなくて、「週に一度、過ぎた日付の予定行をまとめて削除・移動する」GASについてみていきたいと思います。

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