68
Help us understand the problem. What are the problem?

posted at

updated at

kintone とGoogle Apps Script連携

ライブラリのユーザ様に向けて

2022/1/31 追記
原因不明なのですが、既存のスクリプトキーでライブラリが使えなくなってしまいました。
新しく同じソースコードでプロジェクトを作り直しました。

下記の手順でインストールし直してください

1 既存のKitone Managerライブラリを削除

下記のスクショのようにしてライブラリを削除してください。

スクリーンショット 2022-01-31 16.47.32.png

2  ライブラリ追加ボタンをクリック

Aaa.png

3 新しいスクリプト・キーを入力・保存

下記のスクリプト・キーを使用してください。
1UMIqaatccEb68gRI0rDbupn8UdF5nxMcQghQXzyOLyEHnqunUoIcpU5y

スクリーンショット 2022-01-31 16.54.35.png

以上で以前のように使えるはずです。問題があればまたご報告お願いします。

記事本文

↓こちらからが記事の本文になります。

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トークンを設定
ルックアップなど1つのアプリで複数のトークンが必要な場合はカンマ区切りで指定

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-1,YOUR_API_TOKEN2-2"}
};

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

2021/3/18 追記
プロジェクト・キーの代わりにスクリプト・キーを使うようにG側で修正がありました。
下記のスクリプトキーを使用してください。
1M8DHQSWWGOM2RSRjDZmylHMl03nZHnliaVMGMk84m6jQ05ditPBTCSM8

2022/1/31 追記
原因不明なのですが、上記スクリプトキーでライブラリが使えなくなってしまいました。
新しく同じソースコードでプロジェクトを作り直しました。
下記のスクリプト・キーを使用してください。
1UMIqaatccEb68gRI0rDbupn8UdF5nxMcQghQXzyOLyEHnqunUoIcpU5y

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

スクショ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
Sign upLogin
68
Help us understand the problem. What are the problem?