Googleスプレッドシートで、今日以前の行を非表示にする方法。

#はじめに
下記のようなスプレッドシートでシフトを管理しているとします。

| 日付       |       ジョバンニ |   カムパネラ    |
|----------------:|:-----------------:|:------------------:|
| 2018/10/01             |              早番 |        遅番        |
| 2018/10/02           |            早番 |       遅番       |
| 2018/10/03           |            早番 |       遅番       |
| 2018/10/04           |            通し |       休       |
| 2018/10/05           |            遅番 |       早番       |

二人のバイト歴が長くなるにつれて、スプレッドシートの行が長くなってしまうため、2行目から前日までの行は自動で非表示されるようにしたい。

#完成したコード
```javascript:Code.gs
function HideRowsBeforeToday() {
  
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const s = ss.getSheetByName('Sheet1'); // シート名で指定
  const values = s.getRange('A:A').getValues(); //A列に日付けが入っているので、配列で取得。
  const today = new Date(new Date().setHours(0, 0, 0, 0)); //本日の0時の日付を作成
  
  //後続でIndexOfするので、それぞれ文字列にする。
  const arrayDateToString = values.map(String); 
  const todayToString = Utilities.formatDate(today, 'JST', "E MMM dd yyyy HH:mm:ss 'GMT'Z '(Japan Standard Time)'");
  
  //今日の日付のindexを取得
  const indexOfToday = arrayDateToString.indexOf(todayToString);
  
  //2行目から前日までの行を非表示する。
  s.hideRows(2, indexOfToday-1);  
  
}
```
#コードの説明

```javascript:Code.gs
function HideRowsBeforeToday() {
  
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const s = ss.getSheetByName('Sheet1'); // シート名で指定
  const values = s.getRange('A:A').getValues(); //A列に日付けが入っているので、配列で取得。
```
スプレッドシートを指定して、A列にある日付けを配列で取得します。
A列には時間の情報が含まれていませんが、値を取得してみると0時0分0秒になっているようです。

> [Wed Aug 03 00:00:00 GMT+09:00 2016]

```javascript:Code.gs
  const today = new Date(new Date().setHours(0, 0, 0, 0)); //本日の0時の日付を作成
```
A列と比較するために。`new Date()`で本日の日付けを取得します。
`setHours()`でA列に合わせて時刻を0時0分0秒にしますが、このままでは戻り値が数値になってしまいます。

>戻り値
協定世界時 (UTC) 1970 年 1 月 1 日 00:00:00 から更新された日時までの間のミリ秒単位の数値。
[Date.prototype.setHours() - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date/setHours)

なので、再度`new Date()`してDateオブジェクトにします。

> 1.5380604E12 ←new Date().setHours(0, 0, 0, 0)
Fri Sep 28 00:00:00 GMT+09:00 2018 ←new Date(new Date().setHours(0, 0, 0, 0))

日付けが出揃ったので、`IndexOf`を使って、A列（日付け）の配列から、今日の日付けの行番号を取得しようとしても、`-1`が返ってしまいうまくいきません。

理由は下記の通りで、オブジェクトの型が一致しないことが原因のようです。

>indexOf は searchElement と配列の要素を 厳密な同値（三重イコール演算子 === で使われるのと同じ方法）を使って比較します。
 [Array.prototype.indexOf() - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf)

```javascript:Code.gs
  //後続でIndexOfするので、それぞれ文字列にする。
  const arrayDateToString = values.map(String); 
  const todayToString = Utilities.formatDate(today, 'JST', "E MMM dd yyyy HH:mm:ss 'GMT'Z '(Japan Standard Time)'");
```
そこで、それぞれを文字列にして比較できるようにします。
後者の文字列への変換方法がかなり力技ですが、気にしないでください。

>**formatDate(date, timeZone, format)**
Formats date according to specification described in Java SE SimpleDateFormat class. Please visit the specification at http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
[Class Utilities  |  Apps Script  |  Google Developers](https://developers.google.com/apps-script/reference/utilities/utilities#formatDate(Date,String,String))

```javascript:Code.gs  
  //今日の日付のindexを取得
  const indexOfToday = arrayDateToString.indexOf(todayToString);
  
  //2行目から前日までの行を非表示する。
  s.hideRows(2, rowNumHidden-1);  
  
}
```
`indexOf`で今日の日付の行番号(正確には`arrayDateToString`のindex)を取得します。

>引数に与えられた内容と同じ内容を持つ配列要素の内、最初のものの添字を返します。存在しない場合は -1 を返します。
[Array.prototype.indexOf() - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf)

`hideRows`で先頭行と行数を引数に指定し、行を非表示にします。

>**hideRows(rowIndex, numRows)**
Hides one or more consecutive rows starting at the given index.
[Class Sheet  |  Apps Script  |  Google Developers](https://developers.google.com/apps-script/reference/spreadsheet/sheet#hideRows(Integer,Integer))

冒頭の例で本日の日付が`2018/10/03`だとすると、先頭行は`2`で非表示にする行数は`2`になります。

| 日付       |       ジョバンニ |   カムパネラ    |
|----------------:|:-----------------:|:------------------:|
| 2018/10/01           |            早番 |      遅番        |
| 2018/10/02           |            早番 |       遅番       |
| 2018/10/03           |            早番 |       遅番       |
| 2018/10/04           |            通し |       休       |
| 2018/10/05           |            遅番 |       早番       |

このとき行数は、`const rowNumHidden = arrayDateToString.indexOf(todayToString)`から`-1`した値になります。

#トリガーの設定
コードが完成したので、日次でトリガーを設定してあげればOKです。

#やり残したこと
```javascript:Code.gs  
  //後続でIndexOfするので、それぞれ文字列にする。
  const arrayDateToString = values.map(String); 
  const todayToString = Utilities.formatDate(today, 'JST', "E MMM dd yyyy HH:mm:ss 'GMT'Z '(Japan Standard Time)'");
  
  //今日の日付のindexを取得
  const indexOfToday = arrayDateToString.indexOf(todayToString);
}
```
今日の行数文字列に変換して比較するのが力業なので、よりスマートな方法を知りたい。

Stack Overflowではスマートな方法が紹介されていましたが、うまくいかなかったので採用を見送りました。

- [How to correctly use JavaScript indexOf in a date array - Stack Overflow](https://stackoverflow.com/questions/27450867/how-to-correctly-use-javascript-indexof-in-a-date-array)