Google Apps Scriptのローカル開発環境を整える

  • 7
    いいね
  • 0
    コメント

概要

これは、Google Apps Scriptを実行して結果を取得するためのCLIツールです。

背景

Google Apps Script(GAS)で何かを作ろうとするとき、ブラウザを使ってGoogleへログインし、スクリプトエディタを使って作成、実行、結果取得といった流れが最も多いかと思われます。これをローカルの使い慣れたエディタ上でできれば良いなと思ったことがきっかけでこれを作成しました。最初は個人用として作って使用していたのですが、他の方のお役に立てることができればと公開させていただきました。

まずはDemoをご覧ください。

Demo 1

sublimedemo.gif

sheet.png

このデモではSublime Text上で下図のシートからデータを取得するCoffeeScriptで書いたGASを実行させています。

Demo 2

spreadsheetdemo.gif

このデモではSublime Text上でスプレッドシートへデータを入力するGASを実行させています。Sublime Textの横にブラウザを置いて同時に記録しました。定性的にですが各応答速度を知ることができるかと思います。

ダウンロード

実行ファイルはこちら(https://github.com/tanaikech/ggsrun/releases)、あるいはgo getで取得して下さい。

$ go get -u github.com/tanaikech/ggsrun

GitHub : https://github.com/tanaikech/ggsrun

GAS実行のフロー

最初にGASを実行させるために何が必要かを考えた結果、次の3つの案を想定しました。この中でプロジェクトと表記しているものは、スクリプトエディタで通常作成しているスクリプトのことを指しています。このスクリプトには複数のスクリプトを内包することができるため、説明する際に分かりやすいかと思い、プロジェクトと表記しました。

第一案

GASをローカルから実行させようとするとき、最初に思いつくことはExecution APIの使用です。Execution APIは許可を与えたプロジェクト内にある関数を実行し、結果を取得することができるAPIです。実行の際に値を渡すこともできます。Execution APIを使用した場合に想定されるフローは下記の通りです。

Flow_exe1.png

  1. ローカルでスクリプトを作成
  2. Google Driveから実行許可を与えたプロジェクトをダウンロードしてそこへ作成したスクリプトを追加
  3. スクリプトを追加したプロジェクトをGoogle Drive上のプロジェクトへ上書きアップデート
  4. プロジェクト内の追加したスクリプト(関数)を実行

この流れでは、APIを3回使用する必要があります。プロジェクト自体を上書きアップデートするのであれば2回のAPI使用で実行できるのですが、プロジェクト内でもスクリプトを残したい場合も想定し、バックアップを行い、上書きあるいは追加ができるように考えました。プロジェクト内に存在しないスクリプト名のみでプロジェクトをアップデートすると、送ったスクリプトでプロジェクト全体を上書きされてしまうためにこのようなフローを想定しました。

まずはこのフローで作ったのですが、実際に送ったスクリプトを実行、結果回収を行ってみたところ、少し動作が遅いと感じました。

第二案

第二案として、APIの使用回数を第一案よりも減らすとともに、プロジェクトのアップデートも行わずに送ったスクリプトを直接実行することができれば応答速度は第一案より速くなるだろうと考え、下記のようなフローを考えてみました。

Flow_exe2.png

  1. ローカルでスクリプトを作成
  2. Execution APIの使用許可を与えたプロジェクトへサーバスクリプトを設置し、そこへローカルからスクリプトを送って実行、結果を取得

このような方法でスクリプトが実行できるかどうか、さらに複雑なスクリプトが動作するかどうかは不安でしたが、結果としてうまくいきました。(制限事項は次セッションに記載の比較表をご覧ください。)APIの使用は実行時の1度だけになるため、応答速度は第一案より倍近く速くなりました。この場合の速度は、スクリプト実行時間が数秒レベルの話です。スクリプト実行時間が数分レベルであれば第一案も第二案もそれほど大きな差は感じないかと思われます。

第三案

第二案ではローカルから送ったスクリプトを実行させるために送り先の関数をサーバスクリプトで実行させていますので、Execution APIのようにプロジェクト内の関数を自由に実行する必要はなく、固定された関数であっても実行さえできれば同様の効果を得ることができるのではないかと考え、Web Appsの利用を考えました。流れは第二案と同じです。Web AppsはdoGet()doPost()で使用することのできるサービスです。doGet()はクエリ文字数に制限がありますので、doPost()を使って同様の機能があるかどうか調べました。結果としてうまくいきました。ただ、Web Appsは"Anyone, even anonymous"でデプロイしなければ使用できませんので、evalを使う今回の場合はセキュリティ上あまりよろしくないかと思われます。

これら3つの案を検討した結果、ローカルのGASを実行させるための方法として3つとも使用可能と分かりましたので、これら3つの案を選択できるようにしました。3つの案を比較した表は下記の通りです。

比較

第一案、第二案、第三案をそれぞれコマンド名exe1, exe2, webappsとしました。3つのコマンド全てでGASを実行することができますので比較表をご確認いただき、選択してお使いください。exe1はスクリプトを送って実行させる場合と、プロジェクト上に既にある関数を実行させる場合の2つを選択して使用することができます。そのため、比較表は

  1. exe1
  2. exe1(スクリプトを送らず、既存の関数を実行)
  3. exe2
  4. webapps

の4種にしています。

Command Execution method Security Response speed Access token Server Authorization
for Google Services
Script Available scripts Call function Limitation Error Message*4 Library*5
1 exe1
(e1)
Execution API High Slow Yes No No Upload
& Save to project
Only standalone script Functions in project Some limitations Error message
Line number
Yes
2 exe1
(e1)
-f
Execution API High Fast Yes No No No upload
& Only execute function on project
Standalone and Container-bound Script Functions in project Some limitations Error message
Line number
Yes
3 exe2
(e2)
Execution API High Fast Yes Yes No Upload
& No save
Standalone and Container-bound Script Functions in execution script Some limitations Error message No
4 webapps
(w)
Web Apps Low*1 Fast No*1 Yes Yes*2 Upload
& No save
Standalone and Container-bound Script Functions in execution script *3 Error message No
  • *1: webappsを使用する場合アクセストークンは不要です。
  • *2: スクリプト実行時に例えばスプレッドシートへのアクセスする際などにクリック認証が必要になります。
  • *3: webappsを使用してGASを実行する場合、今のところ実行できないスクリプトとは遭遇することができていません。
  • *4: exe1を使用する場合は、エラーメッセージはexe2やwebappsよりも充実しています。スクリプトエディタで表示されるエラーと同じようにエラーのライン番号も表示されます。一方、exe2, webappsではエラー内容は表示されますが、エラーのライン番号は取得できません。
  • *5: exe2, webappsはサーバスクリプト上で動作するため、他のライブラリへのアクセスはできません。exe1の場合は他のインストールしたライブラリを使用することができます。

使用方法

GASを実行するまでの流れは下記の通りです。基本はExecution APIの使用手順、Web Appsの使用手順をそのまま適応することができます。

install.png

Execution APIのデプロイ

本家のドキュメントはこちらです。

  1. スクリプトエディタでスタンドアロンスクリプトを開く。
    • こちらのリンクをクリックしてもスクリプトエディタが開きます。https://script.google.com これを名前を付けて保存してください。
  2. スクリプトエディタの上部にある公開をクリック -> 実行可能APIとして導入 -> 新規作成でバージョンを適当な名前で作成 -> スクリプトにアクセスできるユーザは自分のみ -> OKをクリック
  3. スクリプトエディタの上部にあるリソースをクリック -> Could Platform プロジェクト -> このスクリプトが現在関連付けられているプロジェクト: の下部のリンクをクリック -> APIコンソールが開くので左側のライブラリをクリック -> Google Apps Script Execution APIを検索 -> 有効にする -> 左側のライブラリをクリック -> Google Drive APIを検索 -> 有効にする
  4. 左側の認証情報をクリック -> 認証情報を作成 -> OAuthクライアントID -> 「その他」にして適当な名前を入力して作成 -> OKをクリック
  5. 作成したクライアントの一番右側にある「JSONをダウンロード」をクリックしてダウンロード
    • このとき、ダウンロードしたファイルのファイル名をclient_secret.jsonに変更してください。このファイルは、本CLIツールを使用するディレクトリへ入れてください。
  6. 最初に開いているスクリプトエディタへ戻る。
  7. スクリプトエディタの保存ボタンあるいは「Ctrl + s」でそのままの状態で問題ないので保存する。
    • 実はこれが重要でした。保存することでExecution APIの許可が反映されるようです。初めは上記の設定を行ってもエラーが発生したりしなかったりで、理由が分からずハマってしまいました。

以上でExecution APIのデプロイは完了です。

コマンド exe1の動作確認

この時点で、exe1は使用可能です。ただし、初回のみ認証手続きが必要です。

認証手続き

ターミナルを開いてclient_secret.jsonのあるディレクトリへ移動し、下記コマンドを実行してください。

$ ggsrun auth

ブラウザが使用できる環境下では自動でブラウザが立ち上がり、Googleのログイン画面が表示されます。ログインして認証してください。認証のクリックを押すと、ターミナルに戻ってください。Done.が表示され、ディレクトリ内にggsrun.cfgが作成されます。これで準備完了です。この作業は最初の1度だけでOKです。スコープを変更する場合は、ggsrun.cfgを編集して再度$ ggsrun authを実行すると、編集したスコープでリフレッシュトークンを取得することができます。

もしもブラウザが立ち上がらない場合は自動で手動操作でのコード取得に移行します。ブラウザが立ち上がらずすぐに手動操作へ移行しない場合は、30秒お待ちいただくと手動操作に切り替わりますので、画面に従ってURLをコピーしてブラウザへペーストし、認証の後、コードを取得してターミナルの入力待ち状態へペーストしてください。

以上で認証手続きは完了です。

動作確認続き

サンプルとして、例えば下記のようなスクリプトをsample.gsとして用意します。

function main(values) {
  return values + 1;
}

コマンドラインから下記を実行します。

$ ggsrun e1 -s sample.gs -v 1 -j -i スクリプトID
  • -v 1 : main(values)valuesへ1を渡すことを意味します。
  • -j : 結果を表示する際、JSONデータへインデントを付けて見やすくします。
  • -i スクリプトID : Execution APIをデプロイしたスクリプトIDを指します。スクリプトエディタを開いている状態で ファイル -> オブジェクトのプロパティ を選択したときに表示される一覧の中から、スクリプトIDの項目でIDをコピーして使用します。この-i スクリプトIDは、一度実行すると、ggsrun.cfgに保存されますので、2度目以降はこのオプションは不要です。スクリプトを変更した場合は、ggsrun.cfgの該当個所を変更するか、もう一度-iを使って実行時にスクリプトIDを入力すると自動で保存されます。
  • 結果の回収は、実行する関数main()内へreturnを使って行います。

次のような結果が表示されると成功です。

{
  "result": 2,
  "TotalElapsedTime": 4.195,
  "API": "Execution API without server",
  "message": [
    "Project was updated.",
    "Executed default function 'main()'.",
    "Function 'main()' was run."
  ]
}

上記結果のresultはスクリプトの実行結果です。オプションへ-rを追加して実行すると、結果のみが表示されます。TotalElapsedTimeはAPIのやり取りやスクリプトの実行など、全体の実行時間(秒)です。APIは使用したAPIを表示しています。今の場合はExecution APIをサーバスクリプト無しで動作させていることを意味します。あとは、messageの中にその都度、情報が表示されます。今の場合はmain()が実行されたことを意味します。デフォルトでは全てのコマンドで実行させたいスクリプト内のmain()が初めに実行されます。ファイルをアップロードやダウンロードした場合はその情報が表示されます。

もしもスクリプトの構文やスペルなどにエラーがあればアップロード時にエラーが表示されます。アップデートが完了し、スクリプト実行時にエラーがあると、resultはnullになり、messageへエラー内容が表示されます。

CoffeeScript

CoffeeScriptがインストールされているとsample.coffeeとして下記を実行することもできます。CoffeeScriptを使用する際に注意することは、GASはまだES2015には対応していないため、CoffeeScript 2は使用できないところです。今の時点(2017年4月)では、バージョンは1シリーズをお使いください。動作確認したバージョンは現時点で最新の1.12.5です。いろいろ複雑なスクリプトで試していますが幸いにも今のところ異常は認められていません。

main = (values) ->
    values + 1
$ ggsrun e1 -s sample.coffee -v 1 -j

上記と同じ結果が表示されれば動作確認完了です。

Web Appsのデプロイ

本家のドキュメントはこちらです。Web Appsを使用しない場合はこのセクションはスキップしてください。

  1. スクリプトエディタでスタンドアロンスクリプトを開く。
    • こちらのリンクをクリックしてもスクリプトエディタが開きます。https://script.google.com この場合は名前を付けて保存してください。また、Execution APIを許可したスクリプトへWeb Appsをデプロイして使用していただいても問題なく動作します。
  2. スクリプトエディタの上部にある公開をクリック -> ウェブアプリケーションとして導入 -> プロジェクトバージョンを新規作成で適当な名前で作成 -> 次のユーザとしてアプリケーションを実行では自分にセット -> アプリケーションにアクセスできるユーザを全員(匿名ユーザを含む)にする -> OKをクリック

以上でWeb Appsのデプロイは完了です。

サーバスクリプトのインストール

サーバスクリプト本体はこちら(https://github.com/tanaikech/ggsrun/blob/master/server/server.gs)で確認していただけます。exe2, webappsを使用するにはExecution APIやWeb AppsをデプロイしただけではローカルにあるGASを実行することはできません。インターフェースとなるサーバスクリプトをインストールする必要があります。

サーバスクリプトはライブラリとして用意しましたので、そちらを利用することができます。ライブラリの設定方法は下記の通りです。

本家のドキュメントはこちらです。

  1. スタンドアロンスクリプトのスクリプトエディタを開く。
  2. スクリプトエディタの上部にあるリソースをクリック -> ライブラリを選択 -> ライブラリを追加のテキストボックスへ下記を入力(これは公開しているサーバスクリプトのライブラリのスクリプトIDです)
    • 115-19njNHlbT-NI0hMPDnVO1sdrw2tJKCAJgOTIAPbi_jq3tOo4lVRov
  3. -> 追加ボタンをクリック -> 識別子がggsrunifになっていることを確認して、バージョンは最新のもの、デベロッパーモードを有効にして保存

以上でサーバスクリプトのインストールは完了です。

コマンド exe2の動作確認

コマンドexe2を使用したGASの実行は、Execution APIが使用でき、サーバスクリプトをインストールしている状況下で、上で説明した認証手続きを行うことで使用することができます。下記をsample.gsとしてスクリプトファイルを作成し、その下のコマンドを実行してください。

function main(values) {
  return values + 1;
}
$ ggsrun e2 -s sample.gs -v 1 -j -i スクリプトID

既に-i スクリプトIDとして一度でも実行している場合は、-i スクリプトIDは省略することができます。実行後、下記のような結果を得ることができれば成功です。

{
  "result": 2,
  "GoogleElapsedTime": 0.001,
  "TotalElapsedTime": 1.395,
  "ScriptDate": "2017-0101_00:00:00_GMT",
  "API": "Execution API with server",
  "message": [
    "'main()' in the script was run using ggsrun server. Server function is 'ggsrunif.ExecutionApi()'."
  ]
}

APIの使用回数がexe1よりも少ないため、TotalElapsedTimeがexe1よりも短時間になっていることが認められるかと思われます。コマンド exe2ではサーバスクリプトを使用しているため、Google上のスクリプト実行時間をGoogleElapsedTimeとして表示することができます。これにより、どの程度の通信時間を要しているかが分かるかと思います。

以上でexe2の動作確認は完了です。

コマンド webappsの動作確認

webappsの場合はサーバスクリプトさえインストールしていると、認証不要のため、client_secret.json$ ggsrun authなどの認証関係の作業は不要です。そのまま使用することができますが、下記スクリプトをプロジェクトへ設置する必要があります。

Web Appsでサーバスクリプトを使用するためにスクリプトエディタへ下記をコピーペーストします。

function doPost(e) {return ggsrunif.WebApps(e, "password")}

この場合、doPost()がスクリプトの入り口になります。"password"は、ggsrunで実行する際に必要になるものです。ここで自由に設定することができます。

上記をコピーペーストした後、Web Appsへ反映させます。

  1. スクリプトエディタの上部にある公開をクリック -> ウェブアプリケーションとして導入 -> プロジェクトバージョンをさらに新規作成で適当な名前で作成 -> 次のユーザとしてアプリケーションを実行では自分にセット -> アプリケーションにアクセスできるユーザを全員(匿名ユーザを含む)にする -> OKをクリック
  2. 「現在のウェブ アプリケーションのURL」をコピーしておく。

ターミナルを開いて下記スクリプトをsample.gsとして保存し、コマンドを実行します。

function main(values) {
  return values + 1;
}
$ ggsrun w -s sample.gs -v 1 -j -p password -u https://script.google.com/macros/s/#####/exec

-p passwordのところで先ほどdoPost()で設定したしたパスワードを入力します。実行して結果が表示されれば動作確認は完了です。

URLは毎回入力する必要があります。さらに、一度Web Appsをデプロイしていてもスクリプトを変更すると、バージョンを新規作成してデプロイしなおす必要があります。さらに、使うスクリプトによってはその初回のみGoogle上でのクリック認証が必要になります。この点で一定のセキュリティは感じるものの、操作性を考えるとExecution APIを使うexe1, exe2の方が使いやすいかもしれません。Execution APIではスクリプト実行時のクリック認証は不要です。これはスコープで対応されています。

Web Appsを使用しない場合

Execution APIの制限によりWeb Appsでなければ実行できないメソッドもありますが、ほとんどのスクリプトははexe1あるいはexe2で動作します。私はWeb Appsを使用するとき以外はWeb Appsのウェブの「アプリケーションを無効にする」として、専らexe2を使用しています。

ログの記録

ggsrunは実行ログの記録も行います。ログは、Google Driveのサーバスクリプトをインストールしたプロジェクトと同じフォルダにスプレッドシートとして作成されます。ログの記録方法は、対応している各コマンドでオプション-lを追加して使用します。exe1ではサーバスクリプトを使用しないためログを記録することはできません。exe2はデフォルトではログの記録は行いません。-lを付加したときのみログを記録します。webappsについては、デフォルトでログを記録します。-lを付加したときのみログ記録を停止します。

ログの中身は、スクリプトを実行した日時、どのコマンドで実行されたか、実行したスクリプト本体が記録されています。

その他機能

GASの実行に加えて、自分で使用していて必要になった機能をいくつか付加しています。

Google Driveからのファイルダウンロード

Google Drive上にある全てのファイルに対応しています。(と思われます。)ダウンロード時、Google Document, Google Slide, Google Spreadsheetについては、拡張子を指定しない場合はそれぞれdocx, pptx, xlsxに変換されてダウンロードされます。プロジェクトについてはオプション指定がない場合、プロジェクト内のスクリプト毎にファイルに保存されます。オプション-rを付けると、ダウンロードしたそのままのJSONファイルが保存されます。

$ ggsrun d -f ファイル名
$ ggsrun d -i ファイルID

下記のようにオプション-e 拡張子を付加することで、ダウンロードする際にフォーマットを変換するこtができます。

$ ggsrun d -f ファイル名 -e pdf

Google Driveへのファイルアップロード

$ ggsrun u -f ファイル名

オプションを付けずにアップロードすると、ファイルは自動でGoogle Appsに合わせて変換されます。docx, pptx, xlsxはGoogle Document, Google Slide, Google Spreadsheetにそれぞれ変換されます。 -ncのオプションを付けると、そのままアップロードされます。

Google Driveへのプロジェクトアップロード

Google Drive上にプロジェクトを新規作成します。下記はサンプルです。

$ ggsrun u -pn 新規作成するプロジェクト名 -f script1.gs,script2.gs,index.html

ファイルとファイルの間にスペースを入れたい場合は下記のようにダブルコーテーションで囲って下さい。

$ ggsrun u -pn 新規作成するプロジェクト名 -f "script1.gs, script2.gs, index.html"

Google Drive上のプロジェクトアップデート

Google Drive上の既存のプロジェクトを更新します。下記はサンプルです。

$ ggsrun ud -p プロジェクトID -f [script .gs, .gas, .htm, .html]

ここでのプロジェクトIDとは、スクリプトエディタを開いてファイル -> プロパティにあるスクリプトIDのことを指します。プロジェクト内のファイル名と同一名を指定すると、上書きされますので注意してください。プロジェクト内に存在しないファイル名の場合はプロジェクトへ追加されます。

ファイルリスト表示

Google Drive上のゴミ箱内を除く全てのファイル、フォルダを取得します。

$ ggsrun ls -j

これだけだとGoogle Drive上のファイルの統計が表示されるのみです。オプションとして-sを追加すると全てのファイル、フォルダが表示されます。-fを使用するとファイルに保存されます。

サーバスクリプトをインストールしている場合は、下記のコマンドでGoogle Drive上にあるフォルダのフォルダツリーを取得することができます。

$ ggsrun e2 -t -j

ファイル検索

Goolge Drive上のファイルやフォルダを検索します。

$ ggsrun ls -sn ファイル名 -j
$ ggsrun ls -si ファイルID -j

下記のような結果を取得することができます。

{
  Name: "[file name]",
  ID: "[file id]",
  ModifiedTime: "2017-01-01T00:00:00.000Z",
  URL: "https://docs.google.com/spreadsheets/d/#####/edit?usp=drivesdk"
}

上記の他にもSublime Textでの使用方法や、サンプル、応用例、Q&Aなども用意しています。また、Sublime Textで使用するためのコード補完機能は今のところ付加させていません。

詳細はサンプルと一緒にこちら(https://github.com/tanaikech/ggsrun)にまとめさせていただきましたので宜しければご覧ください。

参考

Go言語について

Execution APIのデプロイ

Web Appsのデプロイ

Google Drive APIについて

Google Apps Scriptのインポート、エクスポート

Authorization code取得について下記サイトを参考にさせていただきました。

本ツールが皆様のお役に立つことができれば幸いです。