GASのTips集（サンプルコード付）

# はじめに

GASでちょっとした業務を自動化しています。
この記事では便利だなと感じたTipsをまとめてみたいと思います。

※コード利用時に変更していただきたい内容を【内容】と表記します。

# 突発的なエラー発生時に通知する

運用中のGASで突然
* Exception: フォームのデータを取得できませんでした。しばらくしてからもう一度お試しください
* Service Spreadsheets failed while accessing document with id XXXXXXXX

といったエラーに見舞われることありませんか。


エラー発生時に「Summary of failures for Google Apps Script」というタイトルメールで通知されますが

* トリガー設定者にのみ通知される
* エラー詳細内容は「実行数」で7日間以内に確認する必要がある

という制約があります。
（GWとか年末年始とか7日間以内にみれないこともありますよね）
（トリガー設定者がメールに気づけないこともありますよね）

以下のようにcatch句でチームメンバー宛にメールするようにしておくと
エラー内容を『7日過ぎた後』でも・『宛先メンバーのうちの誰か』が確認できます。

```
function myfunction() {
  try {

  //ここにメインの実装内容をコーディングする
  
  } catch (e) {
    var text = "errormessage:" + e + "\nfileName:" + e.fileName + "\nlineNumber:" + e.lineNumber + "\nstack:" + e.stack;
    console.error(text);
    text += "\n\n 【エラー発生時に確認したい内容を添えておくと便利】";
    GmailApp.sendEmail('【メールアドレス】', '[要確認]GASでエラー発生', text, {noReply: true});  
    throw e;
  }
}
```


> ```throw e;``` としているのは実行数画面でエラー終了した旨を検索しやすくするための対応につき、記載しないことで正常終了扱いにできます。

# 例外処理を発生させたいとき
```
throw new Error("エラーメッセージ");
```
と実装することで例外処理を発生させることができます。

実装例）
代入結果が未定義の場合に例外処理に分岐させたいケース
```
　const words = ['みかん', 'マンゴー', 'さくらんぼ'];
　let result = words.find((element) => element === "りんご" );
  if(typeof result === 'undefined'){
    throw new Error("【resultオブジェクトが未定義です、リスト内容を確認してください】");
  }
```

参照記事（ありがとうございます！）：
https://qiita.com/kou1121/items/149e7e14f04207adf622
https://www.javadrive.jp/javascript/var/index6.html


# 本番用のGASとテスト用のGASで変数を管理する

絶賛運用中GASでの大きめな修正時、テスト用GASを用意して検証したくなることもありますよね
そんなときプロパティサービスを用いることで、コードはそのまま・GASごとに使い分けたい部分だけ別途管理するという手が。



例）テストと本番でメールアドレスを使い分けたいケース：
```
const MAIL_TO = PropertiesService.getScriptProperties().getProperty('MAIL_TO');
```
![propertysetting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1297607/d008f2ce-078f-ad66-aa37-dded91182b56.png)


設定＞スクリプトプロパティにて
MAIL_TOとしてテスト時に利用したいメールアドレスを設定（上記画像参照）することで
ワンソースでメールアドレスを本番用とテスト用で使い分けることができます。




# csvファイル内容をスプレッドシートにインポートする

Googleドライブのパソコン版ドライブをインストールしたうえで、
「G:\マイドライブ」や「G:\共有ドライブ」以下に配置したcsvファイルを取り込むコード。
直接スプレッドシートに書き込みできないケースに。

```
/**
 * ■ローカルcsvをスプレッドシートに貼り付ける
 *
 * 
*/
function importFromCSV() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet();
  //CSVファイルを取得
  var files = DriveApp.searchFiles('title = "【ファイル名】"');
  var csvFile = "";
  while (files.hasNext()) {
    //Shift_JISにてCSVをそのままで取り込む
    csvFile = csvFile + files.next().getBlob().getDataAsString("Shift_JIS"); 
  }
  // CSVとしてパースする
  csv = Utilities.parseCsv(csvFile);
  // シートに書き込むために範囲を定義する。範囲はcsvの行数、列数を元にする
  let range = sheet.getSheetByName('【シート名】').getRange(1,1,csv.length, csv[0].length);
  // CSVデータをシートに書き込む
  range.setValues(csv);
  //スプレッドシート保存
  SpreadsheetApp.flush();
}

```
> ```var files = DriveApp.searchFiles('title = "【ファイル名】"');``` で
複数ファイルが検索できる場合、そのファイル数分スプレッドシートに転載されます。

# GASを引き継ぎするときに見るポイント

[マイトリガー](https://script.google.com/home/triggers) にて自身がトリガー実行者として設定しているプロジェクトが表示されます。
![mytrigger.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1297607/73a2ad08-b757-7e54-3e40-ebdbf9e42f78.png)

引継ぎされたいときはこのトリガー画面で表示される情報を元に、
* 後任の方によるトリガー設定
* 自身のトリガー設定を削除

を実施しましょう:cactus:


トリガー画面は「自分」か「他のユーザー」としか表示されないため
後任からすると「このトリガー誰が実行してるんだろう・・・？:thinking_face:」になってしまうので
引継ぎされるときに自身の実行トリガーを見直すことをお勧めします:star:

![trigger.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1297607/2f63c246-d2ee-c220-3358-e188880c9165.png)