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

GASが動かない時に見るところ

はじめに

インターネットのGAS(Google Apps Script)のコードをコピペして動かなくて何時間も悩んだので、次回の時の備忘録としてまとめておきます。
GASに限ることでも無いですけど。

参考サイト

素材として何も無いと分かりにくいので、cybozu developer networkの記事をお借りして、Googleフォームに入力してkintoneにレコードとして登録する処理を参考に見ていきます。

GASはどのように動作するのか

イメージです。
GAS.png

参考サイトの動き

ユーザーがフォーム入力して送信ボタン押下 → フォームに設定したトリガーが起動 →
トリガーに設定したスクリプトが実行される → スクリプトでフォーム内容が処理される → スクリプトからリクエストが送信される → 成功するとレスポンスがスクリプトに返る。外部のDB(kintone)にデータが登録される

動かない時に見るところ

Googleアカウント

Googleフォームとそれに結びつける [Google Apps Script] は同一の [Googleアカウント]でログインして作成する必要があります。

複数のアカウントを利用している場合は合わせること。

トリガーの設定

スクリーンショット 2019-11-02 9.11.18.png

[実行する関数を選択] にプロジェクト内の関数で最初に実行される関数名を選択します。
ここを間違えると実行されません。

デバッグログ

GASのデバッグログの出力はプロジェクトを表示した状態で、フォーム実行直後にメニューから表示→ログで確認します。

スクリーンショット 2019-11-02 10.37.31.png

スクリーンショット 2019-10-31 22.46.57のコピー.png

デバッグ出力

APIのLoggerクラスを利用します。

function gasTest(){
  var str = 'ログの表示'
  Logger.log("ログ=> %s", str);
}
// [19-11-02 10:49:44:699 JST] ログ=> ログの表示

問題の切り分け

GASのAPIとそうで無いものを切り分けて考えます。

参考のコードでは下記はGASのAPIの話しです。

Google Apps API

e.response.getItemResponses()

APIを一つだけ説明します。

e ?

eって何よ?ですが、ここのコンテキストでは Googleフォームの話しなので、ここでの e はフォーム送信時のレスポンスになります。

フォーム送信時のレスポンス

フォーム送信時に設定したトリガーで実行されてフォームの情報をGASの関数で受け取るのですが、その受け取った情報が
Google Forms eventsForm submit になります。

つまり、[e]の中身はこれ

Form submit (installable)
authMode A value from the ScriptApp.AuthMode enum.
FULL
response A FormResponse object, representing the user's response to the form as a whole.
FormResponse
source A Form object, representing the Google Forms file to which the script is bound.
Form
triggerUid ID of trigger that produced this event.
4034124084959907503

それなので、ここからフォームの中身を取得するには e.response で フォームレスポンスオブジェクトを取得して、フォームレスポンスオフジェクトのメソッド getItemResponses() で フォームに含まれる全てのアイテム(フォームのこと)のオブジェクトを配列で取得するという算段です。

取得したアイテムはオブジェクトなので、さらにアイテムにセットされた値を取り出すには、アイテムに対して getResponse() して取得します。
深すぎる...

デバッグの仕掛けどころ

下記の2箇所。

  1. フォームを処理した最後の return records の records の中身
  2. 外部DBにデータを送信した戻り値の中身

特に2.の中で、エラーメッセージが返っていたらそれを確認することで対応できるのではと思います。

こんな感じでログに書き込めばよろしいかと。

    Logger.log('response=> "%s"', response);

2.で具体的に仕掛ける場所は、Step10の39行目の下になります。

参考

エラーだとこんな感じで返ってきてました。

[19-11-01 07:44:55:634 JST] response=> "{"code":"CB_VA01","id":"0HxuEQ8by3JPwVQgOy1Q","message":"入力内容が正しくありません。","errors":{"records[0].attend.value":{"messages":["\"はい、参加します\"は選択肢にありません。"]},"records[0].Email.value":{"messages":["URLの形式が正しくありません。「http://」または「https://」で始まる必要があります。"]}}}"
[19-11-01 07:44:55:635 JST] Response code is "400.0"

ライブラリを使っているとき

修正版が配布されている場合がありますので、最新版を試して見ましょう。

下記KintoneManagerはバージョン5が最新です。(2019-10-31現在)
スクリーンショット 2019-11-04 8.48.17.png


KintoneManagerでBasic認証を使う

KintoneManagerをBasic認証に対応させるパッチを書きました。

diff --git a/KintoneManager.gs b/KintoneManager.gs
index 8dfd784..bda5c7e 100644
--- a/KintoneManager.gs
+++ b/KintoneManager.gs
@@ -1,8 +1,9 @@
 var KintoneManager = (function() {
   "use strict";
   /**
-   * user, passが指定されれば、パスワード認証
+   * auth: {user: 'user', pass: 'pass'}が指定されれば、パスワード認証
    * 指定されなければ、APIトークン認証
+   * auth: {basic: {user: 'user', pass: 'pass'}}が指定されれば、Basic認証
    * appsは以下の形式
    * {
    *    // アプリケーション名はkintoneのデータに依存せず、GAS内のコードで取り扱う専用
@@ -23,16 +24,18 @@ var KintoneManager = (function() {
    * @param {string} pass (optional) password
    * @constructor
    */
-  function KintoneManager(subdomain, apps, user, pass) {
+  function KintoneManager(subdomain, apps, auth) {
     this.subdomain = subdomain;
     this.authorization = null;
     this.apps = apps;

-    if (arguments.length > 3) {
-      this.authorization = Utilities.base64Encode(user + ":" + pass);
-    } else if (arguments.length > 2) {
-      // 引数が3つの場合はエンコード済みの認証情報として処理
-      this.authorization = user;
+    if (arguments.length === 3) {
+      if (auth.user && auth.pass) {
+        this.authorization = Utilities.base64Encode(auth.user + ":" + auth.pass);
+      }
+      if (auth.basic) {
+        this.basic = auth.basic;
+      }
     }
   }
   /**
@@ -197,15 +200,21 @@ var KintoneManager = (function() {
    * @private
    */
   KintoneManager.prototype._authorizationHeader = function(app) {
+    Logger.log('app=> "%s"', app);
+    var auth = {};
     if (this.authorization) {
       // Password authentication
-      return { "X-Cybozu-Authorization": this.authorization };
+      auth["X-Cybozu-Authorization"] = this.authorization;
     } else if (app.token) {
       // API token authentication
-      return { "X-Cybozu-API-Token": app.token };
+      auth["X-Cybozu-API-Token"] = app.token;
     } else {
       throw new Error("Authentication Failed");
     }
+    if (this.basic) {
+      auth["Authorization"] = "Basic " + Utilities.base64Encode(this.basic["user"] + ":" + this.basic["pass"]);
+    }
+    return auth;
   };
   return KintoneManager;
 })();

利用方法

  1. KintoneManagerのGitHubリポジトリから git clone または、ダウンロードしてソースファイルを取得します。
  2. 上記パッチを当てます。
  3. GASのプロジェクトにKintoneManager.gsとしてファイルを作成します。
  4. プログラムから呼び出します。

プログラムからの呼び出しについて

パッチを当てたプログラムを利用する方法です。

  • ライブラリを削除します。(スクリプトエディタからリソース→ライブラリ→削除)
  • ライブラリの呼び出し箇所を修正(下記参照)

APIトークン認証+Basic認証

    var appid = 'アプリID';
    var token = 'アプリAPIトークン';
    var apps = {
      YOUR_APPLICATION1: {appid: appid, name: "kintone Meetup 参加者", token: token}
    };
    // 認証情報を設定
    var basicUser = 'Basic認証 ユーザーID';
    var basicPass = 'Basic認証 パスワード';
    var auth = {
      basic: {
        user: basicUser,
        pass: basicPass
      }
    };

    var manager = new KintoneManager(subdomain, apps, auth);

パスワード認証+Basic認証

    var appid = 'アプリID';
    var apps = {
      YOUR_APPLICATION1: {appid: appid, name: "kintone Meetup 参加者"}
    };
    // 認証情報を設定
    var user = 'ログイン認証時のユーザーID';
    var pass = 'ログイン認証時のパスワード';
    var basicUser = 'Basic認証 ユーザーID';
    var basicPass = 'Basic認証 パスワード';
    var auth = {
      user: user,
      pass: pass,
      basic: {
        user: basicUser,
        pass: basicPass
      }
    };

    var manager = new KintoneManager(subdomain, apps, auth);


Tips

固定値をコードの外部で管理する

スクリーンショット 2019-11-02 9.38.04.png

プロジェクトプロパティで固定値を保存して、スクリプト中に取り出して利用することができます。

あとがき

コピペして行けると思ったのですが、エラーで悩みました。
当たり前ですが、kintone側のフィールドの設定と全く同じにしないとデータが入らない。
kintoneのフィールドでリンク という便利フィールドがあるのですが、ここフォームを設置した後は入力値の種類を確認出来ないし、変更も出来ないのですね。
Googleフォーム側はメールアドレス渡してるのに、kintone側はWebサイトのアドレスにしてあって、随分長い時間悩みました。

kintone ヘルプより引用

入力値の種類
・Webサイトのアドレス
 Webサイトのアドレスを入力する欄を設置できます。
・電話番号
 電話番号を入力する欄を設置できます。
・メールアドレス
 メールアドレスを入力する欄を設置できます。


関連リンク

Google Apps Script関連

API

ライブラリ


sy250f
リモートワークで働くシステムエンジニアです。 要件定義と基本設計、プロジェクト管理が主な業務です。
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
ユーザーは見つかりませんでした