Google Apps Script 入門

どうも、gloopsの今川です。

最近、スプレッドシートの拡張にはまっていてGoogle Apps Scriptなるものに触れたので、導入までを投稿したいと思います。

※以下、2016年投稿当時の内容となっています。


# はじめに

> **[Google Apps Script](https://developers.google.com/apps-script/)** は、Googleが提供するサーバーサイド・スクリプト環境です。Googleが提供する一大スクリプト環境を是非使いこなしてください。

# 基本

>　Google Apps（グーグル アップス）とは、99.9% の稼働率が保証された Google の提供するコミュニケーションツールとコラボレーションツールがセットになったグループウェアとしても利用可能な組織向けのオンラインアプリケーションパックです。[引用](http://www.appsupport.jp/googleapps/)

　~~また、それらGoogleのサービスをJavaScriptによるスクリプトで操作するためのスクリプト環境がGoogle Apps Scriptです。~~

　 **現在では、Googleアカウントを持ち、Googleドキュメントやその他のサービスを利用している者なら誰でも利用できるようになりました。** 

## 事前準備

　まずは、Chrome拡張機能に **Google Apps Script** を入れましょう。これで効率的にGoogle Apps Scriptが作成できます。
 
 　[Google Apps Script](https://chrome.google.com/webstore/detail/google-apps-script/eoieeedlomnegifmaghhjnghhmcldobl?hl=ja)よりCHROMEに追加を行ってください。
  
  これで **GoogleDrive** より **Google Apps Script** を新規作成できるようになりました。

　新規作成を行うと以上のような無題のプロジェクト ( **Standalone Script** プロジェクト) が作られます。
 
　 Google Apps Scriptは、
  
 * **Standalone Script** (ドライブ上に単独で存在するもの)
 *  **Container Bound Script** (スプレッドシートに紐づくもの)
 

　 が存在します。スプレッドシートからスクリプトエディタを選択すると自動的に**Container Bound Script** プロジェクトが作成されます。また、各種承認（カレンダー等）はプロジェクト単位で必要となります。
  
   １つのプロジェクト内に複数のスクリプトファイルを持つことが可能です。
   また、１つのスプレッドシート内に複数のContainer Bound Scriptプロジェクトを持つことも同様に可能です。
   
 　複数のプロジェクトがスプレッドシートに存在する場合、スクリプトエディタ起動時にどのプロジェクトを選択するか促されます。

## Hello Google Apps Script

　それでは、GASで最初のプログラムを書いてみましょう。
プログラムを書いたことがある人にはおなじみの "Hello World"  を表示してみます。

```js:HelloWorld.gs
function myFunction() {
  Logger.log("Hello World!!");
  Browser.msgBox(Logger.getLog());
}
```

　Standalone Scriptでは `Browser.msgBox()`は使うことができません。  
 Container Bound Scriptで上記のスクリプトを実行するとメッセージボックスに *Hello World!!* が表示されます。また、Standalone Scriptでも `Logger.log()` のみ実行し、 **Ctrl + Enter**を押してログを確認すると*Hello World!!* が表示されます。
 
 
## Standalone Script と Container Bound Script の違い

　**Standalone Script** と **Container Bound Script** は前章で述べた通り **スプレッドシート** (その他サービス)に紐づいているか否かの違いがあります。また、以下のような比較があります。

|  |Container Bound Script  |Standalone Script  |
|---|---|---|
|作成方法  |各コンテナ(Sheets,Forms,Sites)のメニューから作成  |Drive上またはhttps://script.google.com へアクセス  |
|Sitesでリンクから呼び出し |Sites上に作成すれば可能  |不可能  |
|Spreadsheetでの独自関数 |Spreadsheet上に作成すれば可能  |不可能  |
|onOpenトリガーの自動登録 |可能  |不可能  |
|Webアプリケーションとして動作 |可能  |可能  |
|ソースコードのダウンロード	 |不可能  |可能  |
|ScriptEditor以外での開発	 |不可能  |可能  |

　基本、独自関数などContainer Bound Scriptでないとできない場合以外はStandalone Scriptにするのが良いと思います。
 
# ライブラリ

　ライブラリは、関数を他のスクリプトで実行可能なプロジェクトです。
 >A library is a project whose functions can be reused in other scripts. 
 [GAS Reference](https://developers.google.com/apps-script/guide_libraries)

　自身のプロジェクトをライブラリ化したり、他の人が作ったライブラリを利用したりすることが可能です。

## ライブラリ化
  
  　ライブラリ化するのは簡単です。ライブラリ化を意識して関数を作るのには気を使いますが、手順はそれほど多くありません。
   
### ライブラリの公開方法
 
  1. たくさん関数やメソッドだけを集めた **プロジェクト** を用意します。ソレ以外の **ルーチン** や **構文** は入れないようにします。
  2. スクリプトエディタの画面で、 **「ファイル」⇒「版を管理」** にて **版** を保存します。
  3. スクリプトエディタの画面で、 **「ファイル」⇒「プロジェクトのプロパティ」** にて、 **Project Key** を **コピー** しておきます。
  4.  **Project Key** を使いたいユーザに教えます。
  5. その **ライブラリ** が詰まった **プロジェクト** への **パーミッション** を **公開** や、対象のユーザに **閲覧権限** を与えておきます。

　以上でライブラリ化完了です。
 
*  **プロジェクト名** はわかりやすいものに。
*  **バージョン毎** に **ライブラリ** は **保持** 、 **公開** される。
*  **公開** したくない **関数** は `_` をつける。

##### 以上の点を注意して作成しましょう。

### ライブラリの参照方法

  1. スクリプトエディタ画面にて、 **「リソース」⇒「ライブラリ」** を開きます。
  2. 出てきた画面で、 **Project Key** を検索ボックスに入れて選択ボタンを押します。
  3.  **バージョン** を選択します。これは保存された版の一覧です。
  4.  **識別子**をつけます。 **識別子** とは、 **関数** を利用する時の頭につける文字列です。
  5.  **関数** を呼び出す時は、 **関数名** を直接書くのではなく、 **識別子.関数名** というスタイルで書きます。
  6.  **識別子** が **既存のクラス名** などとバッティングした場合、 **オーバーライド** されてしまうので **注意** です。
  7.  **オートコンプリート** で **ライブラリ内** の **関数** がすべて出てきますので、選んでください。

　Google提供のGAS用ライブラリは以下のサイトで公開されています。
 　[google apps script samples](https://github.com/google/google-apps-script-samples/)

## ライブラリでClass化と補完

　GASのライブラリは補完が有効になるため、  **メソッド** 名など。 **オートコンプリート** で出てきてくれます。しかし、 **ライブラリ化** と **クラス化** は、少し相性が良くありません。

　理由は **ライブラリ化** した際、 **補完メソッド** として表示されるのは、 **グローバルメソッド** のみだからです。


```js:complemented.gs
/**
 * このメソッドはライブラリを利用する方で補完できる
 * @param {string} templateName テンプレートの名称
 * @return {Page} 見つけたテンプレートページ
 */ 
function getTemplateByName(templateName) {
   //処理
}
```
```js:not_complemented.gs
function HogeClass(fuga) {
  this.fuga = fuga;
}
//このHogeClass.getFugaは補完できない
HogeClass.prototype.getFuga = function() {
  return this.fuga;
};
```

　そこで、 **グローバルメソッド** に **ダミー** を置くことで、 **クラス化** と **補完** を共に行います。

```js:class_complemented.gs
function create(hoge) {
  return new HogeClass(hoge);
}

function set(fuga) {
  throw new Error("このメソッドは直接呼び出せません。createメソッドをコールし取得したインスタンスより呼び出してください。");
}

(function(global) {
  var HogeClass;
  HogeClass = (function() {
  
    HogeClass.name = 'HogeClass';
    
    function HogeClass(hoge) {
      this.hoge = hoge;
      if (!(this.hoge != null)) throw new Error("the hoge is required");
    }
    
    HogeClass.prototype.set = function(fuga) {
      this.fuga = fuga;
    };
    
    return HogeClass;
  })();
  return global.HogeClass = HogeClass;
})(this);
```

　これにより、ライブラリの利用側では、`Hoge.create('hoge').set('fuga')`の全てが補完可能になります。

参考サイト：

- [YahooJaTextApi](https://script.google.com/d/1SUrdiAP_Dys7qFTR6XnNgK4zGxIpMmKFxWv4_6kCi-H1QgEVUJubE_CH/edit)
- [Google Apps Scriptにおける「プロジェクト」の関係](http://qiita.com/sebisawa/items/4faa6d859f480e306f46)
- [初心者のためのGoogle Apps Scriptプログラミング入門](http://libro.tuyano.com/index2?id=638001)
- [Google Apps（グーグル アップス）とは](http://www.appsupport.jp/googleapps/)