GAS開発のデバッグログは Logger / consoleを使わないで、デバッグ機能を使おう。

:::note info
対象：初心者や、エンジニアではないけど業務効率化でGASを書いている人
:::

Google App Scirptを教えている時に、デバッグでログを表示するのに、いちいち
```javascript
console.log(hoge);
Logger.log(hoge);
```
上記のコードを各所に仕込んで、いちいち変数の中身を表示している方がいました。
結構めんどくさいことしているなぁと思ったので、そういうやり方をしている人を撲滅しようと思います。

:::note warn
実運用でエラーが出た時のログを仕込みたい場合はこの限りではありません。
ぜひともログをたくさん仕込みましょう。
:::

```text:シート1
名前	        性別	  身長	     ホームページ
田中 太郎	男性	  175 cm	 https://tanaka.example.com
佐藤 花子	女性	  160 cm	 https://sato.example.com
鈴木 一郎	男性	  180 cm	 https://suzuki.example.com
高橋 直美	女性	  158 cm	 https://takahashi.example.com
伊藤 翔太	男性	  170 cm	 https://ito.example.com
山田 愛	    女性	  165 cm	 https://yamada.example.com
松本 大輔	男性	  178 cm	 https://matsumoto.example.com
小林 優子	女性	  162 cm	 https://kobayashi.example.com
斎藤 健	    男性	  173 cm	 https://saito.example.com
渡辺 美咲	女性	  159 cm	 https://watanabe.example.com
```

```javascript:GAS
function myFunction() {
  const properties = PropertiesService.getScriptProperties();
  const spreadsheetId = properties.getProperty('SPREADSHEET_ID');
  
  const sheetName = 'シート1';
  
  // スプレッドシートとシートを取得
  const sheet = SpreadsheetApp.openById(spreadsheetId).getSheetByName(sheetName);
  
  // データ範囲を取得
  const dataRange = sheet.getDataRange();
  const data = dataRange.getValues();
  
  // ログに出力
  for (let i = 0; i < data.length; i++) {
    Logger.log('名前: ' + data[i][0] + ', 性別: ' + data[i][1] + ', 身長: ' + data[i][2] + ', ホームページ: ' + data[i][3]);
  }
}
```

開発中、変数の中身がどうなっているか `console` や `Logger` を使わって確認することがあるでしょう。
これをGASの標準機能の「デバッグ」を使って確認するようにしましょう。

# 想定ケース1：sheetの読み込みが出来ていない！
例えば以下のようなエラーが出たとします。
```
Exception: Unexpected error while getting the method or property openById on object SpreadsheetApp.
myFunction	@ コード.gs:8
```
どうやら以下のsheetの読み込みでエラーが出ているようです。
```javascript:8行目
const sheet = SpreadsheetApp.openById(spreadsheetId).getSheetByName(sheetName);
```
ここでいつものあなたなら、sheetの変数代入の前に、
```javascript:
console.log(spreadsheetId, sheetName);
// or Logger.log(spreadsheetId, sheetName);
```
としていたことですが、デバッグ機能を使ってみましょう。
本来ログを出力したかった行番号のすぐ左をクリックすると、紫色のポチがつきます。「ブレイクポイント」と呼ばれる部分ですね。

![スクリーンショット 2024-06-24 1.35.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374872/c6e40de9-82b0-fa5d-d082-d98bbebd1366.png)

その後に、実行ボタンのすぐ右にある「デバッグ」ボタンを押しましょう。
すると右にデバッガが開き、その地点まで呼び出された変数のリストも一緒に表示されます。
出力したかった、`spreadsheetId` と `sheetName` もきちんと表示されています。

![スクリーンショット 2024-06-24 1.41.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374872/4cd18437-10cb-3bce-ff41-300bc05856d5.png)

どうやら`SPEADSHEET_ID`が変な文字列になっていたようです。
ということで修正してめでたしです。
GASの開発の際にわざわざ `conosle` だったり `Logger` を使う必要はないのを理解してもらえましたか？

# ケース2: 処理の流れを確認する
新たに「身長170cm以上の人の列の背景色を黄色にする」という要件を追加します。
以下のコードを追加しました。
```javascript:背景色を追加
function highlightTallPeople() {
  const properties = PropertiesService.getScriptProperties();
  const spreadsheetId = properties.getProperty('SPREADSHEET_ID');
  
  const sheetName = 'シート1';
  
  const sheet = SpreadsheetApp.openById(spreadsheetId).getSheetByName(sheetName);
  
  // データ範囲を取得
  const dataRange = sheet.getDataRange();
  const data = dataRange.getValues();
  
  // 行数と列数を取得
  const numRows = dataRange.getNumRows();
  const numCols = dataRange.getNumColumns();
  
  // 背景色を設定するための範囲を初期化
  const rangeToHighlight = [];
  
  // データをループし、身長が170cmを超える行を見つける
  for (let i = 1; i < numRows; i++) { // i = 1 から始めるのは、ヘッダー行をスキップするため
    const height = data[i][2];
    // "cm"を取り除いて数値に変換
    const heightValue = parseInt(height.replace(' cm', ''));
    
    if (heightValue >= 170) {
      // ハイライトする行を範囲に追加
      rangeToHighlight.push(i);
    }
  }
  
  // ハイライトする範囲に背景色を設定
  rangeToHighlight.forEach(function(row) {
    sheet.getRange(row, 1, 1, numCols).setBackground('yellow');
  });
}
```
これを実行すると以下のようになりました。
![スクリーンショット 2024-06-24 2.18.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374872/59e05402-7646-7c9a-5923-f0109f63bd41.png)

ヘッダーに黄色が来たり、要件通りになっていない。これは困りました。
GASでスプレッドシートを扱う際にインデックスの取り扱いでこんがらがるの、あるあるですね。

条件分岐がうまく行ってるのか確かめるために、 `if` のところでブレイクポイントを貼ってみましょう。
```javascript:ブレイクポイント
    if (heightValue >= 170) {
// → ここで貼ってみる
      rangeToHighlight.push(i);
    }
```
![スクリーンショット 2024-06-24 2.24.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374872/1491f16f-def5-3f23-4938-79034485694f.png)

170cm以上判定はできていそうです。
次のループも見てみたいので、 デバッガの`|▶︎` みたなボタンを押します。これを押すと処理が再開します。ループが続く限り同じ箇所でまた処理が止まります。

![スクリーンショット 2024-06-24 2.41.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374872/18141323-bc38-9662-4e19-bd39692679f1.png)

このまま続けていきましたが、身長判定は正しくできていそうです。
では色を塗る場所がおかしいと見て、ブレイクポイントを設定します。

![スクリーンショット 2024-06-24 2.44.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374872/5c113813-d7f4-521d-791a-19fee6d107d5.png)

すると、`getRange` のrowが 1 になっているのが確認できます。 `getRange` は行/列番号で場所判定するので、`1,1`だとヘッダーに色が入ってしまいます。

![スクリーンショット 2024-06-24 2.53.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374872/50b24e2d-13fe-1867-a456-d915538e748d.png)

ということで、以下の箇所がおかしかったので修正します。

```javascript:ブレイクポイント
    if (heightValue >= 170) {
      rangeToHighlight.push(i+1); // シートの行は1から始まるため、インデックスを1加える
    }
```

そして実行すると、正しく背景色がセットされました。

![スクリーンショット 2024-06-24 2.56.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374872/d5112ac4-18b7-6bc0-f78f-57183064a30f.png)

このようにデバッグして、時間節約していきましょう。