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

kintone とGoogle Apps Script連携

More than 3 years have passed since last update.

Google Apps Scriptからkintone APIを呼ぶ

kintoneの標準機能だけで補いきれない部分をGASで補うと便利。
以下のような用途で便利。

  • 帳票を作成
  • 自動メール送信
  • 定期実行バッチ処理

コード

kintone_manager.gs
var KintoneManager = (function() {
    "use strict";
    // user, passが指定されれば、パスワード認証
    // 指定されなければ、APIトークン認証
    // appsは以下の形式
    // {
    //    // アプリケーション名はkintoneのデータに依存せず、GAS内のコードで取り扱う専用
    //    YOUR_APP_NAME1: {
    //       appid: 1,
    //       guestid: 2,
    //       name: "日報",
    //       token: "XXXXXXXXXXXXXX_YOUR_TOKEN_XXXXXXXXXXXXXX" // パスワード認証する場合は省略化
    //    },
    //    YOUR_APP_NAME2: {
    //       ...
    //    }
    // }
    function KintoneManager(subdomain, apps, user, pass){
        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;
        }
    }
    // レコードの作成
    KintoneManager.prototype.create = function(app_name, records) {
        var app = this.apps[app_name];
        var payload = {
          app: app.appid,
          records: records
        };
        var response = UrlFetchApp.fetch(
            "@1/records.json".replace(/@1/g,this._getEndpoint(app.guestid)),
           this._postOption(app, payload)
        );
        return response;
    };
    // レコードの検索
    KintoneManager.prototype.search = function(app_name, query){
       var q = encodeURIComponent(query);
       var app = this.apps[app_name];
       var response = UrlFetchApp.fetch(
         "@1/records.json?app=@2&query=@3"
            .replace(/@1/g, this._getEndpoint(app.guestid))
            .replace(/@2/g, app.appid)
            .replace(/@3/g, q),
         this._getOption(app)
       );
       return response;
    };
    // レコードの更新
    KintoneManager.prototype.update = function(app_name, records) {
        var app = this.apps[app_name];
        var payload = {
          app: app.appid,
          records: records
        };
        var response = UrlFetchApp.fetch(
            "@1/records.json".replace(/@1/g, this._getEndpoint(app.guestid)),
           this._putOption(app, payload)
        );
        return response;
    };
    // レコードの削除
    KintoneManager.prototype.destroy = function(app_name, record_ids){
       var app = this.apps[app_name];
       var query = "app=" + app.appid;
       for(var i=0; i<record_ids.length;i++){
           query += "&ids[@1]=@2".replace(/@1/g,i).replace(/@2/g,record_ids[i]);
       }
       var response = UrlFetchApp.fetch(
         "@1/records.json?@2"
            .replace(/@1/g, this._getEndpoint(app.guestid))
            .replace(/@2/g, query),
         this._deleteOption(app)
       );
       return response;
    };
    // GETメソッドの時のオプション情報
    KintoneManager.prototype._getOption = function(app) {
       var option = {
          method: "get",
          headers: this._authorizationHeader(app),
          muteHttpExceptions: true
       };
       return option;
    };
    // POSTメソッドの時のオプション情報
    KintoneManager.prototype._postOption = function(app,payload) {
       var option = {
               method: "post",
               contentType: "application/json",
               headers: this._authorizationHeader(app),
               muteHttpExceptions: true,
               payload: JSON.stringify(payload)
       };
       return option;
    };
    // PUTメソッドの時のオプション情報
    KintoneManager.prototype._putOption = function(app,payload) {
       var option = {
               method: "put",
               contentType: "application/json",
               headers: this._authorizationHeader(app),
               muteHttpExceptions: true,
               payload: JSON.stringify(payload)
       };
       return option;
    };
    // DELETEメソッドの時のオプション情報
    KintoneManager.prototype._deleteOption = function(app) {
       var option = {
          method: "delete",
          headers: this._authorizationHeader(app),
          muteHttpExceptions: true
       };
       return option;
    };
    // エンドポイントの取得
    KintoneManager.prototype._getEndpoint = function(guest_id) {
      var endpoint = "https://@1.cybozu.com".replace(/@1/g,this.subdomain);
      if (guest_id == null) {
        return endpoint + "/k/v1";
      } else {
        return endpoint + "/k/guest/@1/v1".replace(/@1/g, guest_id);
      }
    };
    // ヘッダーの認証情報
    KintoneManager.prototype._authorizationHeader = function(app) {
      if (this.authorization) {
         // パスワード認証
         return { "X-Cybozu-Authorization": this.authorization };
      } else if (app.token) {
         // APIトークン認証
         return { "X-Cybozu-API-Token": app.token };
      } else {
        throw new Error("kintone APIを呼ぶための認証情報がありません。");
      }
    };
    return KintoneManager;
})();

初期化

初期化時に扱うアプリの情報と認証情報を渡す。

パスワード認証

アプリのAPIトークンは使わず、kintoneのユーザー名とパスワードを使うパターン
ゲストスペースのアプリの場合はguestidを下記のYOUR_APPLICATION2のように設定する。

var subdomain = "YOUR_COMPANY";
var apps = {
  YOUR_APPLICATION1: { appid: 1, name: "アプリ1"},
  YOUR_APPLICATION2: { appid: 2, guestid: 1, name: "アプリ2"}
};
var user = "YOUR_KINTONE_USER_NAME";
var pass = "YOUR_KINTONE_PASSWORD";

var kintone_manager = new KintoneManager(subdomain, apps, user, pass);

APIトークン認証

パスワードは使わず、各アプリのAPIトークンを設定

var subdomain = "YOUR_COMPANY";
var apps = {
  YOUR_APPLICATION1: { appid: 1, name: "アプリ1", token: "YOUR_API_TOKEN1" },
  YOUR_APPLICATION2: { appid: 1, name: "アプリ2", token: "YOUR_API_TOKEN2"}
};

var kintone_manager = new KintoneManager(subdomain, apps);

CREATE

recordsの形式の詳細は公式ドキュメントを参照してください。
responseで返ってくるのはGASのクラスであるHTTPResponseクラスです。

var records = [
        {   // 1件目のデータ
            "(フィールドコード)": {
                "value": (フィールド値)
            },
            "(フィールドコード)": {
                "value": (フィールド値)
            },
            :
        },
        {   // 2件目のデータ
            "(フィールドコード)": {
                "value": (フィールド値)
            },
            "(フィールドコード)": {
                "value": (フィールド値)
            },
            :
        },
        :
        {   // n件目のデータ
            :
        }
];
var response = kintone_manager.create("YOUR_APPLICATION1", records);
// ステータスコード
// 成功すれば200になる
var code = response.getResponseCode();

UPDATE

recordsの形式の詳細は公式ドキュメントを参照してください。

var records = [
        {   // 1件目のデータ
            "id": (更新するレコードのID),
            "revision": (更新するレコードのリビジョン),// 不要の場合は記載しない
            "record": {
                "(フィールドコード)": {
                    "value": (フィールド値)
                },
                "(フィールドコード)": {
                    "value": (フィールド値)
                }
            }
        },
        {   // 2件目のデータ
            "id": (更新するレコードのID),
            "revision": (更新するレコードのリビジョン),// 不要の場合は記載しない
            "record": {
                "(フィールドコード)": {
                    "value": (フィールド値)
                },
                "(フィールドコード)": {
                    "value": (フィールド値)
                }
            }
        },
       {   // n件目のデータ
            "id": (更新するレコードのID),
            "revision": (更新するレコードのリビジョン),// 不要の場合は記載しない
            "record": {
                "(フィールドコード)": {
                    "value": (フィールド値)
                },
                "(フィールドコード)": {
                    "value": (フィールド値)
                }
            }
        }
];
var response = kintone_manager.update("YOUR_APPLICATION1", records);
// ステータスコード
// 成功すれば200になる
var code = response.getResponseCode();

SEARCH

クエリの書き方は公式ドキュメントを参照してください。

var query = 'property1 = "hoge"'
var response = kintone_manager.search("YOUR_APPLICATION1", query);
// ステータスコード
// 成功すれば200になる
var code = response.getResponseCode();
var content = JSON.parse(response.getContentText());
// レコードの配列が取得できる。
var records = content.records;

DESTROY

// 削除するレコード番号の配列
var record_ids = [1,3,5];
kintone_manager.destroy("YOUR_APPLICATION1", record_ids);
// ステータスコード
// 成功すれば200になる
var code = response.getResponseCode();

制限

CREATEは1回100件まで、SEARCHは500件までなどのkintone APIの制限がありますので、制限を超える場合はループで回すなどの処理を適宜書いてください。

公開

公開してみました。
プロジェクト・キーは以下です。
MDT2NQ9jkAGYJ-7ftp_A0v08CaFRWuzzx

下記スクショみたいな感じで導入できます。

スクショ1

first.png

スクショ2

second.png

スクショ3

third.png

ライブラリ利用時の初期化

// パスワード認証
var manager = new KintoneManager.KintoneManager(subdomain, apps, user, password);
// APIトークン認証
var manager = new KintoneManager.KintoneManager(subdomain, apps);
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
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