Apps Script API を使って Google Apps Script を呼び出してみよう

Apps Script API

こんにちは、サポート部のまさよしです。

春の足音を今か今かと心待ちにしている冷え性の私ですが、進級や進学、新社会人といった切り替わるシーズンとなり春から新生活や新たなステージに進む方も多いかと思います。

そういった区切りのタイミングということで、私が今シーズンに紹介したテクニカルブログの棚卸をしてみたところ、ほぼ PowerBuilder と Google API の連携でした。Google Sheets API(このブログは明石さんでしたね 汗) から Gmail API、Google Drive API とご紹介したのですが、皆さん、試してみましたか?

まだの方は是非チャレンジしてみてくださいね!

そして今回は若干総決算的なところもありますが、読んでいただいた皆様のテクニカルの幅がより広がる可能性を秘めた「PowerBuilder と Google Apps Script」の連携についてご紹介します。


はじめに

Web 上で「Google Apps Script」を検索するとどういうことができるのか紹介しているページがたくさんありますので、改めて私から説明する必要はないかと思いますが、簡単にお伝えすると Google Apps Script(以降は「GAS」と省略)は、Google が提供しているプログラミング言語で、JavaScript をベースに作られています。そのため、Google アカウントを持っていれば開発環境なしで簡単に利用でき、スプレッドシートやドキュメント、フォーム、ドライブなど Google サービスと連携して比較的簡易なソースコードで様々な処理を自動的に行うことができます。ただ、GAS はサーバー上で実行されるためウィンドウなどのオブジェクトは使用できませんが、Slack や Chatwork、Redmine など外部アプリケーションとの連携も可能です。

GAS を利用すれば PowerBuilder で構築する(した)アプリもより進化できそうな感じがしますね。それでは次に PowerBuilder から GAS を呼び出すための準備を説明します。


事前準備

Google API を利用する定番として、いつもの通り Google Cloud Platform 上でプロジェクトの作成を行わないといけませんが、それ以外に Apps Script API で GAS を利用するには、プロジェクトと GAS を紐づける必要があります。今回、プロジェクト作成は割愛(過去のテクニカルブログ「Google Drive API で Google ドライブへアクセス」のプロジェクト作成を参照)させていただき、プロジェクトと GAS の紐づけ設定を説明しますが、プロジェクト作成時の「API ライブラリ画面」では「Apps Script API」を選択することをお忘れなく。なお、プロジェクト作成後に発行される「クライアント ID」と「クライアント シークレット」以外にプロジェクトと GAS の紐づけ用に「プロジェクト ID」も必要となるので、メモしておいてください。

プロジェクトを作成したら早速 GAS を作成しましょう!G ドライブ上で右クリックから「その他」を選択して「Google Apps Script」をクリックしてください。そうすると「myFunction」というファンクションのひな型が表示されます。今回は以下のようなプログラムを記述してみました。

Apps Script 画面

「myFunction」は最初にプログラムする際によく使われる「Hello, World!」という文字列を呼び出し元に返す処理、「translateFunction」は translate メソッドを使って、引数で渡された文字列(日本語)を英語に翻訳して呼び出し元に返す処理となっています。

それでは次にデプロイ&プロジェクトと GAS の紐づけです。画面右上の [デプロイ] ボタンをクリックして「新しいデプロイ」をクリックします。種類の選択から「実行可能 API」を選択後、[プロジェクトの種類を変更] ボタンをクリックします。そして [プロジェクトを変更] ボタンをクリックすると「GCP のプロジェクト番号」という入力欄が表示されますので、メモしてあった「プロジェクト ID」を入力後、 [プロジェクトを設定] ボタンをクリックすることで設定が完了します。そうそう。その際に画面に表示されている「スクリプト ID」をメモっておいてください。後で PowerBuilder から呼び出す際に利用します。

Apps Script 設定画面

これで Google 側の設定は終わりです。


Authorization Code の生成と Access Token の取得

それでは PowerBuilder アプリケーションを作成します。

Apps Script API も他の Google API シリーズ同様、利用するには承認済みのリクエストとして Access Token をあわせて送信する必要があります。流れとしては、まず Google にログインして Authorization Code を生成後、Authorization Code とクライアント ID、クライアント シークレットを送信すると Access Token が取得できます。

今回は【2019 R3】WebBrowser コントロールを使ってみたでも紹介したように Google のログインなど Web ページ表示用のウィンドウ(w_webbrowser)を作ります。 ウィンドウには WebBrowser コントロールのみを配置し、Open イベントで WebBrowser コントロールの Navigate 関数(引数は Message オブジェクトの StringParm プロパティ)を実行します。作り方はとても簡単ですが詳しくは「【2019 R3】WebBrowser コントロールを使ってみた」を確認してみてください。そしてメインとなるウィンドウ(w_main)からこのウィンドウを表示させるために、[Authorization Code 生成] ボタンを配置します。ボタンクリック時のサンプルスクリプトは以下のとおりです。

[Authorization Code 生成] ボタン Clicked イベント

// 変数宣言
String ls_id
String ls_redirect
String ls_scope
String ls_url

// クライアント ID と Redirect URI、Scope を設定
ls_id = "生成されたクライアント ID"
ls_redirect = "urn:ietf:wg:oauth:2.0:oob"
ls_scope = "https://www.googleapis.com/auth/groups"

// 認証リクエスト用 URL 作成
ls_url = "https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=" + ls_id + "&redirect_uri=" + ls_redirect + "&scope=" + ls_scope
// URL を引数としてウィンドウをオープン
OpenWithParm(w_webbrowser, ls_url, w_main)

// 終了
Return

変数 ls_id にはメモしておいたクライアント ID を設定(忘れても Google Cloud Platform の認証情報画面で再確認可能)し、変数 ls_redirect は urn:ietf:wg:oauth:2.0:oob を指定しています。 この値は Google の承認サーバーが承認コードをブラウザーのタイトル バーに返すことを意味しているとのことです。生成した Authorization Code は Access Token を取得する際にリクエストパラメーターとして送信するので、インスタンス変数やシングルラインエディットで保持しておきましょう。

Authorization Code の生成が完了したので Access Token を取得する処理を実装します。作りをシンプルにするために [Access Token 取得] ボタンを配置します。またあわせてインスタンス変数を用意して、取得した Access Token をセットしておきましょう。

Instance Variables

String is_access_token

以下は OAuthClient オブジェクトを使用した Access Token を取得するサンプルスクリプトです。Access Token 取得には、事前準備でメモしたクライアント ID とクライアント シークレットが必要となります。

[Access Token 取得] ボタン Clicked イベント

// 変数宣言
Integer li_rtn
String ls_id
String ls_secret
String ls_redirect
String ls_scope
String ls_authorization
OAuthClient loa_client
TokenRequest ltr_request
TokenResponse ltr_response

// Access Token 初期化
is_access_token = ""

// パラメーター設定
ls_id = "生成されたクライアント ID"
ls_secret = "生成されたクライアント シークレット"
ls_redirect = "urn:ietf:wg:oauth:2.0:oob"
ls_scope = "https://www.googleapis.com/auth/groups"
// シングルラインエディットから Authorization Code 取得
ls_authorization = sle_1.Text
IF IsNull( ls_authorization ) OR Trim( ls_authorization ) = "" THEN

  Return

END IF

// OAuthClient 作成
loa_client = CREATE OAuthClient

// Authorization Code から Access Token を取得する
ltr_request.Tokenlocation = "https://accounts.google.com/o/oauth2/token"
ltr_request.Method = "POST"
ltr_request.Granttype = "authorization_code"
ltr_request.Clientid = ls_id
ltr_request.Clientsecret = ls_secret
// パラメーターを追加
ltr_request.ClearParams()
ltr_request.AppendParam( "grant_type", "authorization_code" )
ltr_request.AppendParam( "client_id", ls_id )
ltr_request.AppendParam( "client_secret", ls_secret )
ltr_request.AppendParam( "scope", ls_scope )
ltr_request.AppendParam( "code", ls_authorization )
ltr_request.AppendParam( "redirect_uri", ls_redirect )
// Content-Type ヘッダーを設定
ltr_request.ClearHeaders()
ltr_request.SetHeader( "Content-type", "application/x-www-form-urlencoded" )

// トークン情報取得をリクエスト
li_rtn = loa_Client.AccessToken( ltr_request, ltr_response )

// 破棄
DESTROY loa_client

IF li_rtn = 1 AND ltr_response.GetStatusCode() = 200 THEN

  // Access Token 取得
  is_access_token = ltr_response.GetAccessToken()
  // メッセージ
  MessageBox( "確認", "Access Token を取得しました" )

ELSE

  MessageBox( "エラー", "Access Token の取得に失敗しました", StopSign! )

END IF

// 終了
Return

AccessToken 関数でリクエストを送信することで Access Token が取得できます。

関数を呼び出す前までに認証サーバーの URL やプロセスの種類、HTTP メソッドなどを TokenRequest オブジェクトに設定しておく必要がありますのでご注意ください。


PowerBuilder から Google Apps Script を実行

最後は PowerBuilder から Google Apps Script を実行して結果を取得する処理を記述します。

ポイントとして、Google Apps Script を実行するには https://script.googleapis.com/v1/scripts/XXXXXXXXXX:run に POST 形式でリクエストします。XXXXXXXXXX には事前準備でメモしたスクリプト ID を指定します。また POST 時に実行する function 名や必要な場合は引数を JSON 形式のデータであわせて送信します。

また function の戻り値といった実行結果も JSON 形式のデータで返ってくるので、JsonParser オブジェクトを使って解析し、ハンドルやキーから値を取得してください。

「myFunction」や「translateFunction」を実行する時のサンプルスクリプトは以下のとおりです。ラジオボタンで実行する Function を切り替えてあります。

[実行] ボタン Clicked イベント

// 変数宣言
Integer li_rtn
Long ll_response_object
Long ll_root
Long ll_root_object
String ls_returnjson
String ls_data
String ls_url

JsonParser ljp_parser
HTTPClient lnv_httpclient
JsonGenerator lnv_jsongenerator

// 1. HTTPClient 作成
lnv_httpclient = CREATE HTTPClient

// リクエストヘッダーを設定
lnv_httpclient.SetRequestHeader( "Content-type", "application/json" )
lnv_httpclient.SetRequestHeader( "Authorization", "Bearer " + is_access_token )
lnv_httpclient.SetRequestHeader( "Accept", "application/json" )

// 2. 実行する GAS のデータ(関数や引数)を JSON 形式でパラメーターに追加する
// JsonGenerator 作成
lnv_jsongenerator = CREATE JsonGenerator


// オブジェクトのルート項目に GAS データをセットする
ll_root_object = lnv_jsongenerator.CreateJsonObject()
IF rb_excec_myFunction.checked = true THEN
	// 関数名
	lnv_jsongenerator.AddItemString(ll_root_object , "function", "myFunction" )
ELSEIF rb_excec_translateFunction.checked = true THEN
	// 関数名
	lnv_jsongenerator.AddItemString(ll_root_object , "function", "translateFunction")
	// 引数
	lnv_jsongenerator.AddItemString(ll_root_object , "parameters", mle_2.text)
END IF

// 作成した JSON 形式のデータを取得
ls_data = lnv_jsongenerator.GetJsonString()

// 3. GAS実行リクエストを Post
ls_url = "https://script.googleapis.com/v1/scripts/XXXXXXXXXX:run"
li_rtn = lnv_httpclient.SendRequest("POST", ls_url, ls_data)

IF li_rtn <> 1 THEN

  // 破棄
  DESTROY lnv_jsongenerator
  DESTROY lnv_httpclient
  
  // 終了
  Return
  
END IF

// 4. GAS実行結果(JSON 形式)を取得
lnv_httpclient.GetResponseBody(ls_returnjson)

// JsonParser 作成
ljp_parser = CREATE JsonParser

// ルートアイテムのハンドルを取得
ljp_parser.LoadString(ls_returnjson)
ll_root = ljp_parser.GetRootItem()

// キー「response」の子項目のハンドルを取得(オブジェクト型)
ll_response_object = ljp_parser.GetItemObject(ll_root, "response")
// キー「result」の項目を取得
mle_1.text = ljp_parser.GetItemString(ll_response_object, "result")

// 破棄
DESTROY ljp_parser
DESTROY lnv_jsongenerator
DESTROY lnv_httpclient

// メッセージ
MessageBox( "完了", "GAS の実行が終わりました" )

// 終了
Return

アプリケーションの実行

それでは最後に作成したアプリケーションを実行してみます!それぞれ無事に GAS を実行できたでしょうか。

Authorization Code の生成や Access Token を取得して、「myFunction」をチェック後 [実行] ボタンをクリック。「Hello, World!」が表示されましたね!

GAS(myFunction) の実行

次に「translateFunction」をチェック後 [実行] ボタンをクリック。入力した日本語が英語に翻訳されました!確認完了。

GAS(translateFunction) の実行

まとめ

今回もコード量的には多くなく Google API シリーズを流用できたのまではよかったのですが、設定やリクエスト方法などの調査にかなり時間がかかりました。Apps Script のエディターがバージョンアップされ、参考にしたサイトのスクリーンショットは旧バージョンの内容ばっかりだったので、メニューが変わったり微妙に設定箇所が違って苦戦しましたが、なんとか連携まで漕ぎ着けました。

Google Apps Script は Google アプリの機能拡張することで手作業で行っていた業務の自動化などが図れますが、一方で利用制限もあります。Microsoft Office と連携できなかったり、6 分以上の処理は強制終了(G Suiteの有料サービスを使えば 30 分以上まで伸ばせる)するようなので、例えば Web スクレイピングで取得したデータを Microsoft Excel に直接出力するには、取得した結果を一旦データウィンドウ(データストア)にセットして SaveAs 関数で出力する、ビジネスロジックといった複雑な時間のかかる処理は PowerBuilder 側で行うなど、お互いのメリットを引き出せられればアプリとしてより成果を期待できるのではと個人的に思いました。

以上、まさよしでした。

テクニカルブログ 一覧を見る
PowerBuilder マイグレーション
PowerBuilder学習、動画で始めちゃう?