Google Apps Script で毎週自動実行されるスクリプトを作る

# はじめに
[こちらの記事](https://qiita.com/h-yuki/items/4ba27e415a740d10b870)で書いた毎週行っている共同作業を、Google Apps Script で自動化していきます。この記事の主な目的は全体の基本設計を示すことで、今後の記事に共通する内容となります。そして、毎週決まった時間に処理を起動するスクリプトの骨格部分を作ります。

# 基本設計
## 機能
自動化したい処理は次の2つです。

- 情報元サイトのHTMLから、作業結果を埋め込むHTMLファイルの雛型を生成する
- 作業分担のためのスプレッドシートを作成する

処理の流れを分解すると、以下のようになります。

1. 情報元サイトからHTMLを取得して解析し、作業に必要な情報を抽出する
1. Google ドライブに作業用フォルダを作成する
1. 作業結果を埋め込むHTMLの雛型ファイルを作成して、Google ドライブに保存する
1. 雛型ファイルのリンクを Slack に通知する
1. 担当調整用のスプレッドシートを作成する
1. シートのリンクを Slack に通知する
1. シートのリンクを メーリングリストに通知する

## スクリプトタイプの選択
Google Apps Script には 2つのタイプがあります。

- [スタンドアローンスクリプト(Standalone Script)](https://developers.google.com/apps-script/guides/standalone)
    - 文字通り単独で動作するスクリプトです
    - Google ドライブに表示されます
    - [Google Apps Script ダッシュボード](https://script.google.com/)から作成します
- [コンテナーバウンドスクリプト(Container-bound Script)](https://developers.google.com/apps-script/guides/bound)
    - スプレッドシート、ドキュメント、スライド、フォームのファイル(コンテナーと呼びます)に関連付けられます
    - Google ドライブには表示されません
    - コンテナーになるファイルを開いて、メニューの「ツール」→「スクリプトエディタ」を選択することでプロジェクトを作成できます
    - コンテナーファイルの読み書きが簡単にできます
    - コンテナーファイルを削除する(ゴミ箱に入れる)と、関連付けられているスクリプトも削除されます(ゴミ箱に入る)
    - コンテナーファイルを複製すると、関連付けられているスクリプトも複製されますが、プロジェクトのプロパティやトリガーは複製されません

今回やりたいことはどちらでもできそうですが、最初はよくわからなかったので、スプレッドシートを扱うからコンテナーバウンドかな、くらいの感じで始めました。結果的には、毎週作成するスプレッドシートは、コンテナーファイルとは関係なく新規に作成するようにしたので、スタンドアローンでも実現できたかも知れません。コンテナーファイル上にスクリプトの動作に必要な設定を記載したり、処理を実行するボタンを配置することができるのが便利でした。そのあたりはまた別の記事で説明します。

# プロジェクトを作成する
- Google ドライブでもスプレッドシートアプリでもよいので、新規にスプレッドシートを作成します
- メニューの「ツール」→「スクリプトエディタ」を選択します

![image.png](https://qiita-image-store.s3.amazonaws.com/0/354068/8d8f619d-e331-500e-2f11-1a112f9d158d.png)

これだけです(^^;

スクリプトエディタが開きます。見えているのがプロジェクトの編集画面です。プロジェクト名はわかりやすい名前に変更しました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/354068/5916fe1f-3ab6-e1b4-ea66-7283b5382ddd.png)


左のサイドバーに「コード.gs」と見えるのがスクリプトファイルです。1つのプロジェクトに、複数のスクリプトファイルを作成することができ、どのファイルに定義した関数でも呼び出すことができます。コードが大きくなってきたら、適切にファイルを分割しましょう。

# 関数を記述する
ファイル名は main.gs に、関数名は weeklyAction に変更し、毎週実行されるコードを記述します。現段階ではログを出力するだけのスケルトンコードです。

```javascript:main.gs
function weeklyAction() {
  const contents = fetchContents();
  const folder = createFolder(contents);
  const template = createHtmlTemplate(folder, contents);
  slackSendTemplate(template);
  const ss = createAssignmentTable(folder, contents);
  slackSendAssignmentTable(ss);
  emailSendAssignmentTable(ss);
}

function fetchContents() {
  Logger.log('情報元サイトからHTMLを取得して解析し、作業に必要な情報を抽出する');
  return null;
}

function createFolder(contents) {
  Logger.log('Google ドライブに作業用フォルダを作成する');
  return null;
}

function createHtmlTemplate(folder, contents) {
  Logger.log('作業結果を埋め込むHTMLの雛型ファイルを作成して、Google ドライブに保存する');
  return null;
}

function slackSendTemplate(template) {
  Logger.log('雛型ファイルのリンクを Slack に通知する');
}

function createAssignmentTable(folder, contents) {
  Logger.log('担当調整用のスプレッドシートを作成する');
  return null;
}

function slackSendAssignmentTable(ss) {
  Logger.log('シートのリンクを Slack に通知する');
}

function emailSendAssignmentTable(ss) {
  Logger.log('シートのリンクを メーリングリストに通知する')
}
```

ツールバーのプルダウンリストで weeklyAction 関数を選択して、三角のアイコンをクリックすると実行できます。実行が終了したら、メニューの「表示」→「ログ」で、出力されたログを確認します。Ctrl+Enterキーでも表示できます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/354068/d2e0e422-fe93-5839-1ace-6788e56ac24a.png)

# トリガーを設定する
関数ができたので、毎週同じ時間に実行されるように設定します。

Google Apps Script では、イベント駆動で関数を実行することができます。そのような関数実行のきっかけのことをトリガーと呼んでいます。トリガーは2種類あります。

- [シンプルトリガー(Simple Trigger)](https://developers.google.com/apps-script/guides/triggers/)
    - 設定は不要です
    - 少数の決まったイベント(例：ファイルのオープン)に対して、決まった関数(例：```onOpen(e)```)が呼ばれます
    - 関数の引数に[イベントオブジェクト](https://developers.google.com/apps-script/guides/triggers/events)が渡されます
    - 認可を必要とするAPIが使えないなど、様々な制約があります
- [インストール可能トリガー(Installable Trigger)](https://developers.google.com/apps-script/guides/triggers/installable)
    - 基本的にはシンプルトリガーと同じですが、制約が少なく、より柔軟です(認可を必要とするAPIも使えます)
    - 時間で駆動することができます
    - 有効にするためには、プロジェクトに対してトリガーを追加する必要があります

毎週実行したいので、時間駆動のインストール可能トリガーを作成します。メニューの「編集」→「現在のプロジェクトのトリガー」を選択すると、トリガーの一覧が表示されます。最初は何もありません。「トリガーを追加」をクリックすると、設定ダイアログが開きます。例えば、下表のように設定します。動作の確認をしたい時は、「分ベースのタイマー」を使うとよいです。「保存」をクリックすれば完了です。

| 項目 | 設定値 |
|:--|:--|
| 実行する関数を選択 | weeklyAction |
| 実行するデプロイを選択 | Head |
| イベントのソースを選択 | 時間主導型 |
| 時間ベースのトリガーのタイプを選択 | 週ベースのタイマー |
| 曜日を選択 | 毎週月曜日 |
| 時刻を選択 | 午前6時～7時  |
| エラー通知設定 | 今すぐ通知を受け取る |

今のところ、実行される関数(weeklyAction)はログを出力するだけですので、ログのタイムスタンプが変わることでしか動作の確認はできませんが、ひとまずこれでスクリプトの骨格は完成です。

# おわりに
2回目の投稿ですが、基本の「き」みたいな内容で終わってしまいました。TIPS だけを残していくつもりでしたが、何だかチュートリアルみたいな記事になってしまいました。せっかくだからと、いろいろ説明を書いていたら、今回も随分長くなってしまいました。記事にするために理路整然とまとめていますが、実際にはもっと試行錯誤しながら進めています。結構たいへんなので、今後もこのスタイルを継続するかはわかりません。