GASでの共通ライブラリ作成方法

# はじめに

GASで共通関数を作って使いまわしたいときのメモ。（ライブラリをつくって、他のGASから参照する）

# ライブラリ作成

特にライブラリを作成するからと言って変わったことをする必要はありません。

[Google Apps ScriptのIDE](https://script.google.com/home)を開きます。プロジェクト名をつけて関数を書きます。

ここでは、アロー関数を使っていますが、functionでもかまいません。好みで実装してください。
ライブラリにした場合、super globalと言う領域でないと他から参照できません。（var や functionはsuper globalだそうです。）

詳細を理解していなくても大丈夫なので、おまじないの様に this.hoge = hoge; ライブラリ化したい関数書けばよいです。
もちろん、`this.hoge = () => {};` でもいいです。こっちのほうが自然かな。

今回は、あってもなくてもいいような関数も作っていますが、以下のような関数を作りました。

* google chatにpostする
* emailを送る
* 日付のフォーマットが正しいか？
* 日付をフォーマット
* 今日の日付

```javascript
// google chatにメッセージ送信
this.googleChat = (url) => {
  const post = (text) => {
    const payload = { text, };
    const options = {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json; charset=UTF-8',
      },
      payload: JSON.stringify(payload),
    };
    const res = UrlFetchApp.fetch(url, options);
    return JSON.parse(res.getContentText());
  };
  return { post, };
};

// メール送信
this.email = (to, title, body, cc = '', bcc = '') => {
  let options = { };
  if(cc) options.cc = cc;
  if(bcc) options.bcc = bcc;
  const send = () => {
    GmailApp.sendEmail(to, title, body, options);
  };
  return { send };
};

this.isValidDate = (date) => {
  try{
    return !Number.isNaN(date.getTime());
  }catch{
    return false;
  }
};

this.formatDate = (date) => {
  if(!isValidDate(date)) return '';

  return Utilities.formatDate(date, 'JST', 'yyyy/MM/dd');
};

this.today = () => {
  const now = new Date();
  return new Date(now.getFullYear(), now.getMonth(), now.getDate());
};
```

## google chatにpostする

google chatのwebhookをつかって、投稿する関数です。スレッドに投稿とかは必要に応じて実装してください。
メソッドチェーンにすると利用箇所で後から見た時に分かりやすいので、あえてメソッドチェーンになるよう実装しました。
これはお好みで実装すればいいと思います。

`googleChat('https://hoge').post('post message')`

## emailを送る

emailを送ります。cc, bccは任意としています。こちらもメソッドチェーンにしましたが、あまり意味がないつくりになってますね・・・。
sendメソッドの引数にtitleとbodyを設定するほうが良いのかな？ sendEmailみたいに一つの関数にしてもいいか。

`email('hoge@hoge', 'タイトル', '本文').send()`

## 日付のフォーマットが正しいか？

スプレッドしーとでセルが日付になってるとDatetime型になってるので引数はDatetime型を期待してるつくりにしています。
もうちょっと作りこんでも良いかな？とは思ったんだけど。サボりました。

日付のフォーマットが正しいかどうかなので、isValidDate としましたが、お好みで isInvalidDate ってしてもいいと思います。
個人的に isInvalidDate == true みたいなコードを見ると、一瞬、考えてしまう。否定的なものをtrueにしたくない。

でも、if文で用いるときは、`if(!isValidDate) thow new Exception()` みたいな感じの使い方が多くて、人によってはこっちのほうが嫌いって人もいると思う。

細かな話、 `if(!isValidDate){}else{}` みたいなelse があるのに否定条件が先になるのも嫌い。これも好みかなぁ。

## 日付をフォーマット

javascriptの間隔で作っててあとからGASには[Utility](https://developers.google.com/apps-script/reference/utilities/utilities)が用意されていることを知りました。
これ英語表記にしたほうが良いです。日本語だとUtilitiesが公共サービスと表示されパニくります。

## 今日の日付

`new Date()` だと時間までついてくるので、スプレッドシートに日付だけで入力されている時に比較がめんどくさいのでつくりました。

## ライブラリ登録

デプロイで、ライブラリを選択して登録します。

更新したときは、デプロイを管理から編集し、新バージョンをデプロイします。

# ライブラリ利用

バッチプログラムを作成してスケジュール実行するケースやスプレッドシートにスクリプトを実装する場合など状況に応じてライブラリを利用することができます。

左メニューのライブラリのプラスボタンを押します。スクリプトIDを入力します。

スクリプトIDは利用するライブラリの歯車マークを押した画面に表示されています。

バージョンを選択します。最新のものでいいでしょう。ライブラリを更新した場合、利用側もそのバージョンを選択する必要があります。

IDを入力します。IDはパッケージ名みたいなイメージで任意の名前で大丈夫です。ここではCommonとつけました。

google chat関数を利用するときは、以下のようになります。

`Common.googleChat('https://hoge').post('post message')`

こうなると共通関数は可読性が悪くなるなぁ・・・。気にしすぎか・・・。

`Common.isValidDate(new Date('2023-03-01'))`

Commonが有効な日付ですか？みたいに見えてしまう気がする。

# バッチプログラムをスケジュール実行

余談ですが、ライブラリを使ってメールとかチャットでお知らせするのはバッチプログラムで実行することが多いと思います。
スプレッドシートに日付が入力されていて、その期限が過ぎている時にはチャットやメールでお知らせするようなバッチプログラムです。

Windowsではタスクスケジューラで実行したり、LinuxだとCronで実行したりすると思います。

これはGoogle Apps ScriptのIDEで設定します。目覚ましアイコンでトリガー設定します。特に難しいことはないので省略します。