GAS（Google Apps Script）でグラフ（Google Chart Toolsで）をメールに埋め込んで送信する


※ この記事は、2014/02/21にGASの勉強会である[「TokyoGAS #5」](http://connpass.com/event/5044/)でプレゼンさせて頂いた資料の中に登場するものです。
資料はコチラのSlideShareにうｐしてます。この記事以外のTipsもまぁまぁこの資料に書いてあります。

* [「2014-02-20_Tokyo-GAS#5-社内活性化推進にGASを大活用した話」](http://www.slideshare.net/humangas_/2014-0220-tokyogastokyogas5gas)


***
GASでグラフ付きのメールを送るということをしたかったので、サンプルを書きました。

Google SpreadSheetとかにあるデータの源泉に対して、指定したグラフ形状でグラフ化して、レポートメールを送信する。そのグラフを見て、また新しいアクションを起こす。みたいな活用イメージです。
これをさらに、トリガー（スケジューラ）で時間起動とか仕込んどくと、決まった時間に継続してる何かの活動に対するデータの見える化を自動で行えるので、使いこなす価値があると思ってます。


# 今回のゴール
まずは、ゴールの図を見てもらったほうが何がしたいのか分かりやすいです。
指定した件名で、宛先に対して自分で定義したグラフを動的に作成＆仕込んでメール送信します。
ちなみに、このグラフサンプルは、社内でやってる勉強会の過去の参加状況を知るためのグラフと思って下さい。

![スクリーンショット_2014-02-20_02_32_54.png](https://qiita-image-store.s3.amazonaws.com/0/26565/6a1a617e-4315-3c3d-9869-50ab5cbedc10.png "スクリーンショット_2014-02-20_02_32_54.png")

# 処理の流れ
処理の流れはこんな感じです。
どのグラフでもこの流れは同じです。異なるのはそのグラフに応じたデータ構造の定義とそれに合わせたデータを積めるところです。

1. グラフに応じたデータ構造の定義
1. それに、グラフのインプットになるデータを積める
1. グラフにデータ設定済みオブジェクトをセットして画像化
1. メールに画像化したグラフを仕込んで宛先へ送信


# ソースコード

```javascript:sample_sendMailChart

function sample_sendMailChart() {

  // データ構造の定義
  var data = Charts.newDataTable()
      .addColumn(Charts.ColumnType.STRING, '勉強会名')
      .addColumn(Charts.ColumnType.NUMBER, '参加者数')
      .addColumn(Charts.ColumnType.NUMBER, 'キャンセル数');  

  // テストデータを積める
  data.addRow(['A001:勉強会1',10,1])
      .addRow(['A002:勉強会2',8,2])
      .addRow(['A003:勉強会3',9,3])
      .addRow(['A004:勉強会4',14,4])
      .addRow(['A005:勉強会5',22,0])
      .build();

  // グラフにテストデータをセットして画像にする
  var chart = Charts.newColumnChart()
      .setDataTable(data)
      .setOption('legend.position', 'in') //凡例をグラフの内側にする
      .setStacked() //グラフを積み上げ式にする
      .build()
      .getBlob();  

  // メールで作成したグラフ画像を埋め込んで送信
  MailApp.sendEmail({
    to: 'XXXXX@gmail.com', // 自分用に変更する
    subject: '【test】GASでChart',
    htmlBody: "チャートサンプル：<img src='cid:sampleCharts'> です! <br>",
    inlineImages: {
      sampleCharts: chart
    }
  });
}

```


## メソッドチェーン
「メソッドチェーン＝流れるようなインターフェース」です（※本当は＝ではない：後述）。

以下のコードを見てもらうと分かりますが、どんどんプロパティをセットしてってます。
これは、流れるようなインターフェースの言葉の通りで、考えを止めずに流れるように書けるので楽だし、見た目にも分かりやすいです。

```javascript
  // データ構造の定義
  var data = Charts.newDataTable()
      .addColumn(Charts.ColumnType.STRING, '勉強会名')
      .addColumn(Charts.ColumnType.NUMBER, '参加者数')
      .addColumn(Charts.ColumnType.NUMBER, 'キャンセル数');  
```

私、最近コーディングしてなかったので、いわゆるこういう考えを知りませんでした。
なので、初めて見た時、パッと見意味は分かるんだけど、コーディング自体に「ん？」てなったんですね。
なので、この流れるようなインターフェースについて、ちょっと聞いたり、調べたりしてみました。
で、流れるようなインターフェースについては、ひがやすをさんのコチラの記事とかを参考にさせて頂きました。

* 【参考】[流れるようなインターフェースとメソッドチェーンは違うもの](http://d.hatena.ne.jp/higayasuo/20071025/1193319054)


このブログの記事によると、正確にはメソッドチェーン＝流れるようなインターフェースではないそうです。読むと納得しました。私の理解だとこうです。

* メソッドチェーン＝ 単にメソッドをチェーンしていくこと。コーディングスタイルとかについて言ってるわけではない。
* 流れるようなインターフェース＝ 思考を止めずに流れるようなコーディングが出来ること。を、考慮されたインターフェース。それが、メソッドチェーンを使って実現されているかどうか。

なので、「メソッドチェーン＝やり方の呼び名」と「流れるようなインターフェース＝書きやすさを考慮した設計（なので、メソッドチェーンするメソッド名の命名についても深く拘る）」かな。


# GASから、Google Chart Tools 使ってる
GASからグラフ（Chart）を触れるAPIはありますが、APIリファレンスによると、実際にはGASから「Google Chart Tools」を利用しているみたいです。

なので、GASからグラフ作る場合は、Google Chart Toolsのリファレンスも追ってかないと、データ構造とかが分かりません。ということで、そこにどう辿り着くか、リファレンスの辿り方を忘れるんで書いておきます。

## Google Chart Tools リファレンスの辿り方
下記の図の流れの通りです。

GASのCharts→ Google Charts→ 作りたいCharts→ Data Formatで、そのグラフを作成する上で定義されているデータ構造が分かります。後はそれに合わせてデータを定義＆積めるだけ。

あと、Configuration Optionsも重要です。グラフのデフォルトの形を変えたい場合などは、このオプションで色々グラフ自体の見た目をイジれます。使い方は、`setOption('プロパティ名', '設定値')`です。
GASからもグラフの見た目をイジるメソッドがラップされて用意されてますが、全部ではないです。なので、そういう場合はこの方法で対処すればイケます。

```javascript
  // グラフにテストデータをセットして画像にする
  var chart = Charts.newColumnChart()
      ・・・
      .setOption('legend.position', 'in') //凡例をグラフの内側にする
      ・・・
```


![スクリーンショット 2014-02-20 17.48.26.png](https://qiita-image-store.s3.amazonaws.com/0/26565/2d0138fe-3910-01a3-4e0d-8b227e8c556d.png "スクリーンショット 2014-02-20 17.48.26.png")

![スクリーンショット 2014-02-20 17.48.37.png](https://qiita-image-store.s3.amazonaws.com/0/26565/7a6dd1e1-7bc5-f955-e311-a854482687d1.png "スクリーンショット 2014-02-20 17.48.37.png")

## グラフを効率的に作っていくための開発のコツ
最後に、グラフを効率的に開発していくためのコツを書きます。
ココで言う効率的につーのは、つまりこういう問題を解決することです。

* グラフのオプションが多すぎるので、自分の目的のグラフを作るまでに、オプションを調べながら試しながらで、いちいちソース変更して画像化（`getBlob`）してたら凄いしんどい。

### コツを書く前に
分かりにくいので、この記事で使ってるカラムチャートを例にして絵で説明していきます。

このカラムチャート、何もオプションを指定しないデフォルト状態だとこうなります。

![スクリーンショット 2014-02-21 14.21.22.png](https://qiita-image-store.s3.amazonaws.com/0/26565/98cbcf8f-9a2e-fe65-164d-a4507d624686.png "スクリーンショット 2014-02-21 14.21.22.png")

でも、本当は下図の表現にしたいわけです。つまり、デフォルト状態から以下の変更を施さなければならない。

* 凡例をグラフの内側にする
* 積み上げ式に変更

![スクリーンショット 2014-02-21 14.22.56.png](https://qiita-image-store.s3.amazonaws.com/0/26565/0bce1ff0-581e-188e-5ea2-d9985571416c.png "スクリーンショット 2014-02-21 14.22.56.png")

ここから説明する手順は、この変更するためのオプションをどうやって調べていくと効率が良いかのコツです。

先に今回のオプションの答えを書いときます。

* 凡例をグラフの内側にする＝ `setOption('legend.position', 'in')`
* 積み上げ式に変更＝ `setStacked()`

以下は、上記サンプルでそれを行っているソースの抜粋です。

```javascript
  // グラフにテストデータをセットして画像にする
  var chart = Charts.newColumnChart()
      .setDataTable(data)
      .setOption('legend.position', 'in') //凡例をグラフの内側にする
      .setStacked() //グラフを積み上げ式にする
      .build()
      .getBlob();

```

### では、そのコツ
要は、Google SpreadSheet上で、まず好みの形のグラフを作ってみて、いい感じの形になったのを目で見て確認したら、そのグラフのオプション設定を参照して、その設定をソース上でも設定すれば、思い描いたグラフになるのは分かってるので楽。というのがコツです。

意味不明ですね。ということで、その手順をまた絵で説明していきます。

まず、空のスプレッドシート上でグラフを作ります。

![スクリーンショット_2014-02-21_13_58_42.png](https://qiita-image-store.s3.amazonaws.com/0/26565/ca273257-986e-9d6b-fe7c-000109759407.png "スクリーンショット_2014-02-21_13_58_42.png")

次に、グラフを好みの形に変えます。設定後すぐグラフを確認できます。

![スクリーンショット_2014-02-21_14_40_42.png](https://qiita-image-store.s3.amazonaws.com/0/26565/12ba9639-6f3c-2c70-f86d-ef887f0f1e41.png "スクリーンショット_2014-02-21_14_40_42.png")

で、最後が肝心です。
このグラフのオプション名と設定値が知りたいわけなので、ソースコード上では何を書くのか知るために、以下をやります。

![スクリーンショット_2014-02-21_13_59_01.png](https://qiita-image-store.s3.amazonaws.com/0/26565/a1a5353c-92b7-4be3-9520-b89ffe45ee11.png "スクリーンショット_2014-02-21_13_59_01.png")

そうですっ！ ここでグラフのオプションが見れるのです。JSON形式で。
`<script>`タグ内を全コピしてます。

![スクリーンショット_2014-02-21_14_06_35.png](https://qiita-image-store.s3.amazonaws.com/0/26565/040585a3-e20e-b23c-61e2-5d7126167e44.png "スクリーンショット_2014-02-21_14_06_35.png")

なので、後はこれを整形して中身を見てみます。
今回は、[JSON整形サービス](http://www.ctrlshift.net/jsonprettyprinter/)というサイトを利用させて頂きました（ググったら出たとこ）。どんな手段でも、見れればもちろんOKです。
このサイトであれば、先ほどコピーした内容を貼り付けて変換ボタン押下すると、下に変換結果が出ます。

![スクリーンショット_2014-02-21_14_48_53.png](https://qiita-image-store.s3.amazonaws.com/0/26565/5b2544a6-3275-1738-7759-9145f15fa5b6.png "スクリーンショット_2014-02-21_14_48_53.png")

変換された内容を見てみます。何となくココがこれかなぁに当たりをつけといて。。。

![スクリーンショット_2014-02-21_14_49_41.png](https://qiita-image-store.s3.amazonaws.com/0/26565/788f6875-b342-d0e7-f691-cb87f249171f.png "スクリーンショット_2014-02-21_14_49_41.png")

実際のオプションが書かれているAPIリファレンスを見てみると、あぁコレかぁ。となります。
ちょっと慣れるまでは、大変ですが、普通にオプションを一個ずつ試してグラフが出来た結果を確認していくよりは、よっぽど楽かと思います。

このそれぞれのグラフのオプションの調べ方は、前述通りです。
ちなみに、この例の場合だと以下のページ（Google Chart ToolsのAPIリファレンス）を参照してます。
[「Google Charts> Visualization: Column Chart> Configuration Options」](https://developers.google.com/chart/interactive/docs/gallery/columnchart#Configuration_Options)

![スクリーンショット_2014-02-21_14_50_08.png](https://qiita-image-store.s3.amazonaws.com/0/26565/9131e1e4-484e-4b8a-f0d5-58a0dc6bf9be.png "スクリーンショット_2014-02-21_14_50_08.png")

なお、この場合だと、以下のどの方法で設定しても同じグラフになります。

```javascript
// 以下いずれかで設定
.setOption('legend.position', 'in')
.setOption('legend', {position:'in'})
.setOption("legend", "in")
```

積み上げ式にする`setStacked`は、GASでラップされている方のメソッドを使用してます。上記同様に、`setOption('isStacked', true)`とやるのと同じです。


### 最後に：残念なお知らせ
このグラフのオプション結果をJSONで確認する手順、残念ながら新しいスプレッドシートでは無理になってしまいました。新しいスプレッドシートでは以下のように表示されて、中身が見れません。
なので、旧型に一旦戻してからやってます。うーん。それは面倒だし、いずれ出来なくなるだろうし。。
なので、ここまで書きはしましたが、現在（2014/02/21時点）の暫定的な対処方法として捉えて下さい。

![スクリーンショット_2014-02-21_15_13_46.png](https://qiita-image-store.s3.amazonaws.com/0/26565/a354da86-ab2c-c55c-4282-a06026c9de92.png "スクリーンショット_2014-02-21_15_13_46.png")

最後の最後ですが、Googleスプレッドシートが新しいやつかどうか確認する方法と、古いほうへの戻し方は以下です。スプレッドシートの右下を見て下さい。

![スクリーンショット_2014-02-21_16_15_10.png](https://qiita-image-store.s3.amazonaws.com/0/26565/71fc709a-84af-0e8e-e553-2fcef1d6ce19.png "スクリーンショット_2014-02-21_16_15_10.png")

* 新バージョン: 「新しいGoogle スプレッドシート」と表示されてる
* 旧バージョン: 「新しいGoogle スプレッドシートを試す」と表示されてる

ここを押下して、現在が新しいスプレッドシートであれば、「以前のスプレッドシートに戻す」を押下すれば旧バージョンを使えます。