見出し画像

ワンストップでわかる! Google Apps Scriptライブラリの使い方と作り方

ライター

本記事では、Google Apps Scriptのライブラリの使い方と作り方、JSDocコメントやコード補完まで、ワンストップで全部わかるように詳しく解説しています。(目的に応じて読み飛ばすこともできます)

株式会社シクミヤではGoogle Apps Scriptを活用して低コストで仕組みによる現場業務の課題解決(自動化・効率化)を行っております。ぜひお気軽にご相談ください。

💡 この記事で得られる知識
・ Google Apps Scriptのランタイムについて
・ ライブラリの使い方
・ ライブラリの作り方と公開方法
・ JSDocコメントの書き方
・ スクリプトエディタのコード補完について

1. はじめに

Google Apps Scriptでは作成したスクリプトをライブラリとして一般公開することができます。もちろん組織内や特定ユーザーに限定することも可能です。また、公開されているライブラリを自身のスクリプトで利用することもできます。

次よりライブラリの使い方と、ライブラリの作り方から公開するまでの手順を解説していきます。


2. 注意事項

ライブラリを使う際、作る際に共通する注意事項です。
必ず事前に目を通して留意してください。

2.1 ランタイムのバージョンとJavaScript仕様

Google Apps Scriptには「ランタイム」というスクリプトを実行するためのエンジンがあります。

Google Apps Scriptは元々「Rhino」と呼ばれるランタイムで動作していました。その後の2020年2月に「V8」と呼ばれる新しいバージョンのランタイムが公開されました。これに伴い、執筆時点では新規にスクリプトを作成する場合はV8ランタイムがデフォルトで有効になっています。

Google Apps ScriptはJavaScriptベースのスクリプト言語ですが、ランタイムによって実装できるJavaScriptの仕様が異なります。

表1. Google Apps Scriptランタイムの歴史年表

画像24

RhinoランタイムとV8ランタイムでの構文や実装の違いは以下の記事を参照ください。

Migrating scripts to the V8 runtime | Apps Script | Google Developers
Google Apps ScriptのV8 Runtime対応を検証してみた - Officeの社

このランタイムのバージョンに違いがあることによる注意事項です。

作成しているスクリプトと、使用しているライブラリとで、有効なランタイムと実装されているJavaScript仕様が異なる場合、スクリプトが動作しないケースが存在します。

表2. 有効なランタイムとJavaScript仕様の差異と実行可否

画像25

表2の通り、ECMAScript構文はV8ランタイムでしか動作しません。逆に下位互換性があるため、ES5構文はV8ランタイムでも動作します。

例えば、以下の「let」はECMAScriptに対応した構文であるため、Rhinoでは動作しません。

上記のコードは保存する際に以下のようなエラーになります。

画像1

このように、ライブラリがECMAScriptに準拠した実装となっている場合、V8ランタイムが無効(=Rhinoランタイムが有効)な状態ではライブラリ内のスクリプトでエラーになります。

執筆時点では未だRhinoランタイムは有効ですので、以下の点に注意してください。

・使う:ライブラリがどちらの仕様に準拠しているのか
・作る:どちらの仕様に準拠させてライブラリを実装するのか(公開する際には明記しておくと良いでしょう)


3. ライブラリの使い方

ここからは外部から自身のスクリプトへライブラリを取り込む方法について説明します。ライブラリは、スクリプトエディタからスクリプトIDを指定して取り込むことができます。

以下より詳しく解説していきます。

3-1. ライブラリを取り込む

スクリプトエディタでライブラリを使用するには以下の手順に従ってライブラリを追加します。 

1) メニュー > 「リソース」 > 「ライブラリ」 を選択する

画像2


2) スクリプトのIDを入力してライブラリを追加する

「Add a library」の欄にスクリプトのIDを入力し、「追加」を押下します。

画像3

---
📝 スクリプトIDとは

このスクリプトIDについてですが、Googleドライブ上のファイルにはユニークなIDが付与されています。スクリプトファイルはGoogleドライブ上に作成しますが、スクリプトエディタで開くと以下のようなURLが表示されます。

https://script.google.com/a/{ドメイン}/d/{スクリプトID}/

また、これはスクリプトエディタのメニュー > 「ファイル」 > 「プロジェクトのプロパティ」からも確認できます。

画像4

画像5


つまり、ライブラリを公開する際にはスクリプトに採番されているスクリプトIDが共有・公開され、そのスクリプトIDを使ってライブラリとして取り込むということです。

尚、「プロジェクトキー」もライブラリとして取り込む際に指定できますが、執筆時点では非推奨となっています。スクリプトIDを使用するようにした方が無難そうです。
---

3) ライブラリのバージョンを選択して保存する

ライブラリの使用するバージョンを選択して「保存」を押下します。バージョンによって使える機能や不具合の解消状況などが異なりますので注意してください。

画像6

---
📝 APIドキュメント

ライブラリのタイトルを押下するとAPIドキュメントが表示されます。ライブラリのAPIについて参考にすると良いでしょう。

画像7

画像8

---
📝 Identifier

スクリプト内で使用する際の任意の識別子です。パッケージ名のようなものです。Google Apps Scriptが標準で提供している「DriveApp」や「SpreadsheetApp」などに相当するものです。

画像9


例えばIdentifierを「TeamDriveLibrary」とした場合は、「識別子.関数名」のようにして利用できます。

​---
📝 Development mode

主に開発版として使用する場合に便利なモードです。ONにすると、バージョンを指定する必要がなく、常に最新バージョンのライブラリが自動で参照されます。

画像10

---

3-2. ライブラリを実装に組み込む

取り込みが完了したらライブラリを実装に組み込むことができるようになります。識別子(Identifier)を用いてライブラリの機能を利用しましょう。

折角ですので、Google Apps Scriptで利用できる便利なライブラリを紹介しつつ説明します。ここで紹介するライブラリ以外にも様々なライブラリが公開されています。

参考)こちらの記事にたくさん紹介されていますのでリンクを掲載させていただきます
GASのおすすめライブラリ18選!使い方やインポート手順についても解説! | monoblog

---
📝 「Moment.js」ライブラリ

日付計算を容易にするライブラリです。

JavaScriptで日付を扱う場合には「Date」を使うのが一般的ではありますが、日付の書式設定や加減算をしたい場合などはやや煩雑です。

Moment.jsはDateをラッピングして、より簡便でスッキリとしたコードを書くことができます。

プロジェクトキー: MHMchiX6c1bwSqGM1PZiW_PxhMjh3Sh48

ライブラリを使用しない場合と、使用した場合のコードを比較してみましょう。

識別子を「moment」とした場合の例です。

▶︎ Dateでの処理

​▶︎ Moment.jsでの処理

スッキリしましたね!​

---

4. ライブラリの作り方

4-1. ライブラリを作る

ライブラリの作成手順を説明します。

1) 新しいスクリプトファイルを作成する

Googleドライブで新規に「Google Apps Script」ファイルを作成します。

画像11


2) コードを書く

画像12

3) 新しい版として保存する

メニュー > 「ファイル」 > 「版を管理」を選択します。

画像13

版(=バージョン)の説明を「Desribe what has changed...」に記載し、「Save new version」で新しい版として保存します。

画像14

4) 共有設定をする

全公開、全公開(リンクを知っているユーザーのみ)、組織内、組織内(リンクを知っているユーザーのみ)、特定のユーザーのみ、などの共有設定をします。

画像15


5) スクリプトIDを公開する

3-1.に記載した手順にてスクリプトIDを参照し、公開します。利用者はスクリプトIDさえ知っていれば良いので、ブログやQiita、GitHubなど、公開場所は好きな場所で構いません。

4-2. ライブラリ作成時の注意事項

ライブラリを作成する際に気を付ける点について説明します。ECMAScriptより実装可能なクラスの利用、スクリプトエディタでのコード補完について解説します。

4-2-1. クラスの利用

ライブラリ内にクラスを自作した場合、「識別子.クラス名」としてもライブラリのクラスを参照することはできません。

下記のような結果になります。

▶︎ ライブラリ側(識別子=Lib)

​▶︎ 利用側

​これを解消するためには、以下のような方法があります。

1) クラスをsuper global領域にセットする
2) クラスを取得するsuper globalな関数を作成する
3) クラスのインスタンスを生成し取得するsuper globalな関数を作成する

---
📝 globalについて

JavaScriptのランタイムではいくつかのオブジェクトを持っていますが、このオブジェクトはツリー構造になっています。

共通して出てくる「super global」という言葉ですが、ここで言う「super global」とはその最上位を指しています。

Google Apps Scriptではネストのない場所か、ネストのない場所に書いた「this」がsuper globalな階層に該当します。ただし、ネストのない場所に書いたletやconstはsuper globalのひとつ下の階層(local globalと呼称します)に位置します。

以下の「宣言」と「階層の確認」のコードでそれが確認できます。

▶︎ 宣言

▶︎ 階層の確認

​test()を実行すると、以下のようなログが出力されます。

1
2
undefined
undefined
5

1
2
3
4
5

letで宣言したc、constで宣言したdはthisの直下には存在しませんが、test()内からは参照できる場所に位置していることがわかります。

つまり、以下のことが言えます。

・a, b, e()はsuper globalに位置している
・a, b, c, d, e()はlocal globalに位置している

尚、「super global」や「local global」は、あくまでも本記事内での説明のために使用している用語です。正確な用語があるかもしれません。

---

話を戻して、次よりクラスを利用する3つの方法について実際のコードを交えて説明していきます。

1) クラスをsuper global領域にセットする
2) クラスを取得するsuper globalな関数を作成する
3) クラスのインスタンスを生成し取得するsuper globalな関数を作成する

1) クラスをsuper global領域にセットする
thisのプロパティに対してクラスを代入します。

▶︎ ライブラリ側(識別子=Lib)

​▶︎ 利用側

2) クラスを取得するsuper globalな関数を作成する
クラスを取得するfunctionを作成します。

▶︎ ライブラリ側(識別子=Lib)

​▶︎ 利用側①

​▶︎ 利用側②

3) クラスのインスタンスを生成し取得するsuper globalな関数を作成する
クラスのインスタンスを生成して返却するfunctionを作成します。

▶︎ ライブラリ側(識別子=Lib)

▶︎ 利用側

​4-3. JSDocとコード補完

4-3-1. JSDoc

JSDocの説明について、Wikipedia記事からの引用を拝借します。

JSDocは、JavaScriptのソースコードにアノテーションを追加するために使われるマークアップ言語である。JSDocをコメントの中に含めることで、プログラマーは自分が書いたコードのAPIを記述するドキュメントを追加することができる。JSDocをさまざまなツールで処理することで、HTMLやRich Text Formatなどの形式のアクセス可能なドキュメンテーションを自動生成することができる。JSDocは、Apache License 2.0の元にライセンスされている自由ソフトウェアである。

引用元:
https://ja.wikipedia.org/wiki/JSDoc

Google Apps Scriptでサポートされているアノテーションは以下です。

表3. Google Apps Scriptでサポートされているアノテーション

画像26

Libraries | Apps Script | Google Developers より引用

Only the @param and @return annotations are currently supported.

JSDocですが、3-1.で触れたAPIドキュメントを生成するための元ネタになります。メンテナンスする際や、GitHubなどでライブラリのソースコードを公開する際にも、使い方のヒントになりますので記述しておくと良いです。

▶︎ JSDocドキュメンテーションの例

4-3-2. コード補完

Google Apps Scirptのスクリプトエディタにはコード補完の機能があります。

ライブラリについてもコード補完することが可能ですが、残念ながら完全ではありません。ライブラリ内にclassを定義して利用してもらう場合には注意が必要です。

注意点については検証を交えながら解説していきますが、先に結論を記載します。

・ライブラリ内のglobalなfunctionはコード補完が効く
・classについては補完に問題がある

従って、以下のいずれかの方針でライブラリの作成を検討する。

・ コード補完の完全性までを考慮してライブラリを作成するのであれば、classは使わずにglobalなfunctionのみで構成する
・ ライブラリのAPIを別途ドキュメントで補うという方針であれば、classを使っても問題はない
参考)TypeScriptベースですが、こちらの記事でも検証されていますので、リンクを掲載させていただきます
Google Apps Script でクラス型のコードを書いたさいのスクリプトエディタでの補完への対処方法 (Bad Hack) - ChangeLog - noissefnoc

補完検証 step1
前述の2)のコードの補完は以下のようになります。

▶︎ ライブラリ側(識別子=Lib)

▷ 検証結果

画像16

foo()は認識されましたが、戻り値の型がvoidになっています。

補完検証 step2
JSDocを追加してみます。

▶︎ ライブラリ側(識別子=Lib)

▷ 検証結果

画像17

戻り値の型がドキュメント通りになりました。

補完検証 step3
次に、Fooクラスのメソッド、プロパティが補完されるかを検証します。

▶︎ ライブラリ側(識別子=Lib)

​▷ 検証結果

画像18


残念ながら、何も補完されませんでした。

補完検証 step4
さて、ではどのようにすれば補完されるでしょうか。以下の方法で補完されるようになります。検証してみましょう。

1) Fooクラスのインスタンスを生成するfunctionを作成、さらにJSDocの戻り値の型は識別子にする

2) Fooクラスのメソッドをglobalなfunctionとして宣言、さらにJSDocもメソッドと同じ内容にする

▷ 検証結果

画像19

hogeが補完されるようになりました。

補完の副作用
しかしながら、この方法には副作用があります。先に完全ではないと述べた理由がこちらです。

❗️ Fooインスタンスからの補完にcreateメソッドが表示されてしまう

画像20

❗️ Lib識別子からの補完にhogeメソッドが表示されてしまう

画像21

余計なものが表示されてしまう上に、これらは全て実行可能であるため、予期せぬトラブルの原因にもなります。

さらに言うと、重複したようなコードとコメントを書かなければならないため、ライブラリの改修コストも上がります。

補完の補足
ちなみに、ES5仕様でオブジェクト指向実装をした場合ですが、classと同じようなJSDocを書いても補完されません。

▶︎ ES5での定義

​▷ 検証結果

画像22

画像23

hogeES5は補完されません。

結論
これまでの検証より、以下のことがわかります。

・ライブラリ内のglobalなfunctionはコード補完が効く
・classについては補完に問題がある

従って、コード補完の完全性までを考慮してライブラリを作成するのであれば、classは使わずにglobalなfunctionのみで構成する、といった作り方になるでしょう。

ライブラリのAPIを別途ドキュメントで補うという方針であれば、classを使っても問題はないでしょう。

ライブラリを作成する際には上記の点について注意が必要です。


5. おわりに

作成したライブラリはclaspでダウンロードしてGit上で管理しておくと良いです。

claspについては、以下の記事が参考になりますのでリンクを掲載させていただきます。Bitbucketで管理する方法が書かれています。
claspを使い、Google Apps Scriptプロジェクトをgitでバージョン管理する

何度も同じコードを実装するのはトータルコストが上がりやすい傾向にありますので、ライブラリの活用をオススメします。

この記事が気に入ったら、サポートをしてみませんか?
気軽にクリエイターの支援と、記事のオススメができます!
スキありがとうございます!
5
株式会社シクミヤが運営するVisionaryBaseの編集部です。経営管理・業務自動化・その他経営など実務で活用できる内容を発信して行きます。

こちらでもピックアップされています

経営管理テクニックブック
経営管理テクニックブック
  • 8本

経営管理について色々陥りがちな罠を書いておきます

コメントを投稿するには、 ログイン または 会員登録 をする必要があります。