LoginSignup
2
1

More than 3 years have passed since last update.

GASを使ってGoogleスプレッドシートからFilemakerにデータを持ってくる方法(認証付き)

Last updated at Posted at 2020-09-18

目的

  • 前回の方法だと公開範囲ガバガバなので認証を付けることに・・・
  • スプレッドシートが親のケースで任意のタイミングでFilemakerにデータを同期する。

方法

  • GoogleのAPIを使ってリフレッシュトークンを取得し、トークンを自動で取得して操作する
    (じゃないと1時間でアクセストークンを手動で取得するというね)
  • この記事の作成に当たっては以下の記事を大いに参考にさせていただきました。この場を借りて感謝いたします。
    https://qiita.com/sikkim/items/7002e9a1551fc347dab4

GAS

前記事とGASのスクリプトは変わりません。公開範囲を狭くします。
ソースは以下からお借りし、元ネタはJSONP向けのようでそのままでは使えないっぽかったので改変しました。
具体的にはjsondataあたりを消してMimeTypeをJSONにしました(これいる?)(素人)。

元ネタ:https://www.koreyome.com/web/make-spreadsheet-to-json-at-google-apps-script/
引用記事:https://qiita.com/taichi0514/items/ee6dedff45f9d9e58ef4

Script

    function getData(id, sheetName) {
      var sheet = SpreadsheetApp.openById(id).getSheetByName(sheetName);
      var rows = sheet.getDataRange().getValues();
      var keys = rows.splice(0, 1)[0];
      return rows.map(function(row) {
        var obj = {}
        row.map(function(item, index) {
          obj[keys[index]] = item;
        });
        return obj;
      });
    }

    function doGet(request) {
      var data = getData('~ここにスプレッドシートのID~', '~シート名~');
      return ContentService.createTextOutput( JSON.stringify(data, null, 2) )
      .setMimeType(ContentService.MimeType.JSON);
    }

設定

公開>Webアプリケーションとして導入
公開範囲はAnyone, even anonymousにする(cURLでアクセスするため)。

公開範囲はonly meですぜ。
お次はgoogle側での操作よー

Google側のあれこれ

APIの有効化

  • GCPのコンソールを開き、左メニューのAPIとサービス→ライブラリを開きます。
    今回はスプレッドシートを使いたいのでスプレッドシートAPIを有効化します。

OAuth2.0クライアントIDを作成する

  • 次にAPIとサービス→認証情報を開きます。
    分かりやすい名前を付けて保存します。アプリケーションの種類は参考にした記事ではその他を選択していましたが、無かったのでデスクトップアプリあたりしました。どれでも関係ないとか?
  • 表示されたクライアントIDとクライアントシークレットを環境変数に設定します。
    画面右上の方の「Cloud Shellをアクティブにする」を使うとブラウザだけで全て完結します。
$ export CLIENT_ID=hoge
$ export CLIENT_SECRET=fuga

環境変数に設定しておくとこの記事や参考記事のコマンドをコピペできるので推奨しますぜ。

リダイレクトURIの設定

  • cloudshellでもとりあえずリダイレクトURIは固定値の
    urn:ietf:wg:oauth:2.0:oobで良い模様です。
    WEBアプリでやる場合とかはすごい人に聞いて下さい。
    コピペ用に環境変数に設定しておきます。
$ export REDIRECT_URI=urn:ietf:wg:oauth:2.0:oob

スコープの設定

スコープに設定する値はここから調べます。
https://developers.google.com/identity/protocols/googlescopes
今回のケースではスプレッドシートを操作するのですが、謎のエラーが出たのでとりあえずドライブも一緒に設定しました。
2つ設定したので間を%20で繋ぎます。例によって環境変数行き。

$ export SCOPE=https://www.googleapis.com/auth/spreadsheets%20https://www.googleapis.com/auth/drive

Authorization Codeの取得

以下のコマンドを実行し、URLを踏みます(ターミナルでやる人はブラウザに貼る)。

$ echo "https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=$CLIENT_ID&redirect_uri=$REDIRECT_URI&scope=$SCOPE&access_type=offline"

ユーザーを指定して許可するとAuthorization Codeが表示されるのでやはり環境変数に設定します。

$ export AUTHORIZATION_CODE=piyo

Authorization Codeを使ってリフレッシュトークンを取得

以下のcURLコマンドを実行するとリフレッシュトークンを取得出来ます。ここまでがコンソールでの作業になります。

$ curl --data "code=$AUTHORIZATION_CODE" \
--data "client_id=$CLIENT_ID" \
--data "client_secret=$CLIENT_SECRET" \
--data "redirect_uri=$REDIRECT_URI" \
--data "grant_type=authorization_code" \
--data "access_type=offline" \
https://www.googleapis.com/oauth2/v4/token

Filemakerのスクリプト設定

黒い所は全部一つのスクリプトに順次記述するやつです。

リフレッシュトークンを使ってアクセストークンを取得

Filemakerのスクリプトステップ、URLから挿入を使用します。
* ターゲット:変数$resultに格納します。
* URLを指定:https://www.googleapis.com/oauth2/v4/token
* cURLオプション:クッソめんどいのでコピペ推奨です。全体をダブルクォートでくくり、中身のダブルクォートはバクスラでエスケープします。
* hoge兄弟は各自取得した値で書き換えてくださいね。

"--data \"refresh_token=hage\"
 --data \"client_id=hoge\"
 --data \"client_secret=fuga\"
 --data \"grant_type=refresh_token\""

受信した結果はJSONで返ってきますが必要なのはアクセストークンだけです。
これも変数$access_tokenに格納します。

変数を設定 [$access_token; 値: JSONGetElement ( $result ; "access_token" )]

ついでに上の方で発行したGASのURLを変数に格納します。

変数を設定 [$url; 値: "https://script.google.com/macros......"]

cURLオプションを書く

変数で入れ替えるために、テキストを挿入ステップでcURLオプションを$option_tempに格納します。
__token__が下のステップでアクセストークンに切り替わります。
(ここは統合できるかもしれませんがテスト時に出来ていちいち変えるのは面倒なのでこのままにします)

テキストを挿入 [選択; ターゲット:$option_temp; "curl -H "Authorization: Bearer __token__" -L @$url"]

cURLオプションを変数に格納

可読性にもつながるのでcURLオプションは$optionに格納します。
ここでアクセストークンがcURLオプションに入りました。

変数を設定 [$option; 値: Substitute ( $option_temp ; "__token__" ; $access_token )]]

データを取得する

URLから挿入 [選択; ダイアログあり:オフ; ターゲット:$result; $url; cURL オプション: $option
  • ターゲットは変数の$resultに上書き。どうせ起動の度に上からスクリプトが動くので問題無し。
  • URLの指定は$urlです。上で格納したやつですね。
  • cURLオプションは$optionです。前回よりは洗練したでしょ?

レコードの更新は公式のここを参考にしました。[" & $i & "]の後に半角スペースあると泣くので詰めよう。

https://fmhelp.filemaker.com/help/17/fmp/ja/index.html#page/FMP_Help%2Fjson-functions.html%23

変数を設定 [$ProductCount ; 値: 
   ValueCount ( 
      JSONListKeys ($result ; "") //←例のようにオブジェクトは無いので""にした 
   )] 
変数を設定 [$i ; 値: 0]
If [$ProductCount > 0]
   全レコードを表示
   対象レコード削除 [ダイアログあり:オフ] //←消さないと同じレコードがどんどん増えるよ
   Loop
      新規レコード/検索条件
      フィールド設定 [製品::ID ; 
         JSONGetElement ($result ; "JSONGetElement ( $result ; "[" & $i & "]ID" )")] 
   //↑この部分、例では[" & $i & "]の後に半角スペースあるけど、オブジェクトが無い場合?詰めないとnullが出力される(なんで?)
      フィールド設定 [製品::価格 ; 
         JSONGetElement ($result ; "JSONGetElement ( $result ; "[" & $i & "]品名" )")] 
      フィールド設定 [製品::在庫 ; 
         JSONGetElement ($result ; "JSONGetElement ( $result ; "[" & $i & "]価格" )")]
      レコード/検索条件確定 [ダイアログあり: オフ]
      変数を設定 [$i ; 値 : $i + 1] 
      Exit Loop If [$i ≥ $ProductCount]
   End Loop
End If
  • スクリプトを仕込んだボタンを置けばワンボタンでレコードがリフレッシュされます。

まとめ

  1. セキュリティの為にアクセストークンを利用する
  2. 毎回手動取得等でボタンポチは面倒なのでリフレッシュトークンを使う
  3. cURLで単に叩かれてもトークンが無いので大丈夫

今回は、スプレッドシートがマスターだったのでこういった感じになりました。チカレタ...

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1