Help us understand the problem. What is going on with this article?

GAS ビギナーが GAS を使いこなすために知るべきこと 10 選

はじめに

Google Apps Script (GAS) は Web ブラウザ上の JavaScript とも Node.js とも環境が異なります。その違いや、 GAS 特有の機能を理解するとさらに開発が捗るので、それらをこの記事で紹介しようと思います。

Tokyo GAS で 5 分 LT した内容です。

スライドはこちら > GAS ビギナーが GAS を使いこな すために知るべきこと 10 選

1. ローカル環境で開発する

GAS を好きなエディタで開発したり、ローカルで開発したものを github に上げたりしたくなる。

Google ブログの記事 Apps Script による高度な開発プロセス で紹介されているが、 node-google-apps-script という npm パッケージをローカル環境にグローバルインストールことで、ローカルで開発したものを GAS に push することができる。

node-google-apps-script
// clone
$ gapps clone <scriptId>
// push
$ gapps push

clasp というライブラリだと push だけでなく pull もできたり、コマンドも豊富なので、 clasp の方が良さげ。

clasp
// clone
$ clasp clone <scriptId>
// push
$ clasp push
// pull
$ clasp pull

2. github でソースコードを管理する

  1. の方法でローカルで開発する場合は、その状態を github と連携してソースコード管理すれば良い。もう一つの方法としては、 Google Apps Script Github アシスタント という Chrome Extension があるので、これを使えば、 github に push / pull することができる。

スクリーンショット 2018-04-01 10.11.53.png

3. 複数の *.gs 間で関数を呼び出す

GAS では複数の *.gs ファイルを持つことができる。これらの関数はグローバル関数となるので、そのまま他のファイルで呼び出すことができる。以下のように書くと util.gs の add 関数は正常に呼び出せる。

main.gs
function main() {
  var num = add(1, 2);
  Logger.log(num);
}
util.gs
function add(a, b) {
  return a + b;
}

グローバル関数となるので、複数ファイルで同一の名前の関数名をつけてはならない。

4. 様々な実行方法

GAS では、主に以下の実行方法から選択する。

  • トリガー
  • G Suite アプリケーションの特定のイベントをハンドリング
  • Web 公開

トリガー

毎週月曜の朝に実行するような場合はトリガーを利用する。 Heroku でいう Scheduler みたいなもの。タイマー(分/時/日/週/月)を利用して、実行タイミングを細かく指定できる。編集 > 現在のプロジェクトのトリガー から設定する。

スクリーンショット 2018-03-21 16.43.37.png

トリガーの例: Google Apps Script (GAS) で毎週 30 分の雑務を自動化した話

G Suite アプリケーションの特定のイベントをハンドリング

  • 特定の Docs を開いた時
  • スプレッドシートの更新時
  • Google フォームの回答時

など、様々なタイミングで実行することができる。公式の Event Objects
で補足できるイベントと、イベント発火時に渡される値を知ることができる。

Web 公開

公開 > ウェブアプリケーションとして導入 を選択すると、公開することができる。簡単な API を作って公開することができ、これはかなり強力。

スクリーンショット 2018-03-21 17.54.30.png

公式の Web Apps の通り、GET の場合は doGet 関数、 POST の場合は doPost 関数を実装する必要がある。ミニマムな GET, POST API 実装を以下に記述する。

minimum-api.gs
function doGet(e) {
  return ContentService.createTextOutput("hello world!");
}

function doPost(e) {
  return ContentService.createTextOutput("OK");
}

返り値は TextOutput か HtmlOutput のいずれかである必要がある。 HtmlService と絡めると、 html を公開できるので、簡単な Web アプリケーションを提供することも可能。

Web 公開の例: 3 分で作る無料の翻訳 API with Google Apps Script

5. スクリプト毎のデータストアがある

前回の実行結果など、スクリプト毎に簡単なデータを保存する保存領域が用意されている
。公式ドキュメントはこちら Class PropertiesService | Apps Script

以下のように呼び出せる。

var properties = PropertiesService.getScriptProperties();
properties.getProperty(key);// 取得
properties.setProperty(key, value);// 設定
properties.deleteProperty(key);// 削除

これで、スクリプトの途中結果を保存して、次の実行時に利用する値を参照できる。

6. スクリプトからトリガーをセットできる

TriggerBuilder を使ってスクリプトからもトリガーを設定できる。以下のコードは、 1 分後main という名前の関数を実行するトリガーを登録している。

var functionName = 'main';
var d = new Date();
d.setMinutes(d.getMinutes() + 1);// 1 分後
ScriptApp.newTrigger(functionName).timeBased().at(d).create();

7. 実行時間の制限と対策

1 回の実行で 6 分間の時間制限があり、スクリプトの実行途中でも強制的に終了する。 6 分を超える場合には以下のような対策が取れる。

例として、スプレッドシートに対して各行処理するスクリプトだとすると

  1. 実行時間が 5 分になるのを検知
  2. 次回処理を開始する行数を PropertiesService で保存
  3. TriggerBuilder を使って新しいトリガーを 1 分後に設定
  4. 処理を終了させる

これは、上の 5, 6 で紹介した Tips を用いた方法。 5 分や 1 分という値は仮なので、よさげな値を使ってください。

その他の制限は公式ガイドの Quotas を参照。

8. G Suite 以外のサービスの API をたたく

GAS は G Suite のアプリケーションを簡単に操作できるが、UrlFetchApp を使って外部サービスとの連携も簡単にできる。

例として Slack にメッセージ投稿するコードを以下に示す。

Slack連携
function postSlack(slackWebhookUrl) {
  var body = { text: 'message' };
  var payload = JSON.stringify(body);
  var res = UrlFetchApp.fetch(slackWebhookUrl, {
    method: 'POST',
    headers: { "Content-Type": 'application/json' },
    payload: payload
  });
}

9. Web スクレイピングの方法

GAS における Web スクレイピングは以下の流れで行う

  1. UrlFetchApp.fetch で html を取得
  2. html を parse

1 は直前で紹介したので省略する。 2 については、 GAS 公式の Parsing HTML で紹介された方法で Web ブラウザ上の JavaScript のような HTML のパースができるが、 XmlService を使っているため、エラーになる場合も多い。

エラーになる時は独自の抽出ロジックを実装する必要がある。以下はその一例。

var html     = UrlFetchApp.fetch(url).getContentText();
var username = find(html, '<p id="username">', '</p>'),

/** 
 * 特定の文字列の間に挟まれた文字列を抽出する
 * @param { string } text 検索対象となる文字列
 * @param { string } from 前方の文字列
 * @param { string } to   後方の文字列
 * @return { string } 検索結果
 */
function find(text, from, to) {
  var fromIndex = text.indexOf(from);
  if (fromIndex === -1) return '';
  text = text.substring(fromIndex + from.length);
  var toIndex = text.indexOf(to);
  if (toIndex === -1) return '';
  return text.substring(0, toIndex);
}

ちなみに、スクレイピングのマナーで1 秒間に 1 回しかアクセスしない というものがあるが、 GAS で sleep するには、 Utilities クラスの sleep を呼び出す。そもそもクローリング拒否してるかどうかは robots.txt を見て判断する。

Utilities.sleep(1000);

Utilities は GAS に適した便利関数群が用意されているので、一度眺めてみるのを勧める。

10. GAS ライブラリの仕組み

GAS で npm モジュールを使えれば非常に便利なのだが、普通に npm install しても動作しない。ローカルでコンパイルするといける方法はあるそうなので、後日調べたら記事化します

代わりに GAS にはライブラリという仕組みがあり、他の人が作った GAS ライブラリを呼び出したり、自分の GAS を登録することができる。詳しくは公式の Libraries に書かれている。

まとめ

ここ数ヶ月で GAS を始めて、調べていて有益だと思った情報をまとめました。私もまだまだ勉強中なので、またネタを仕入れたら記事書きます。

他の GAS ネタ

tanabee
Vice President, RPG TEC. Google Developers Expert / Licensed Scrum Master
https://tanabee.github.io
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした