
kintone: レコード取得
この工程は、kintone アプリのレコード(1件)の内容を取得します。
Basic Configs
- 工程名
- メモ
Configs for this Auto Step
- conf_auth
- C1: API トークンを設定した認証設定 *
- conf_basic
- C2: Basic 認証設定(kintone で設定されている場合のみ)
- conf_domain
- C3: ドメイン(xxxxx.kintone.com または xxxxx.cybozu.com) *
- conf_guestSpaceId
- C4: ゲストスペース ID(ゲストスペース内のアプリの場合のみ)
- conf_appId
- C5: アプリ ID *
- conf_recordId
- C6: レコード ID *
- conf_fieldCode1
- C7F: フィールドコード_1
- conf_fieldValue1
- C7V: 値_1 を保存するデータ項目
- conf_fieldCode2
- C8F: フィールドコード_2
- conf_fieldValue2
- C8V: 値_2 を保存するデータ項目
- conf_fieldCode3
- C9F: フィールドコード_3
- conf_fieldValue3
- C9V: 値_3 を保存するデータ項目
- conf_fieldCode4
- C10F: フィールドコード_4
- conf_fieldValue4
- C10V: 値_4 を保存するデータ項目
- conf_fieldCode5
- C11F: フィールドコード_5
- conf_fieldValue5
- C11V: 値_5 を保存するデータ項目
- conf_fieldCode6
- C12F: フィールドコード_6
- conf_fieldValue6
- C12V: 値_6 を保存するデータ項目
- conf_fieldCode7
- C13F: フィールドコード_7
- conf_fieldValue7
- C13V: 値_7 を保存するデータ項目
Notes
- kintone アプリの API トークンを取得するには、アプリの設定画面の「設定(App Settings)」のタブを開き、「API トークン(API Token)」へと進みます
「生成する(Generate)」をクリックし、権限(Permissions)を選択(「レコード参照(View records)」権限が必要です)したあと、「保存(Save)」をクリックします
「アプリを更新(Update App)」をクリックして変更を適用するのも忘れないようにしてください - kintone アプリのゲストスペース ID(アプリがゲストスペースにある場合)とアプリ ID は、API トークンの設定画面で確認することができます
- このモデリング要素がサポートするフィールド型は、レコード番号、レコード ID、リビジョン、ステータス、作成日時、更新日時、文字列(1行)、数値、計算、文字列(複数行)、リッチエディター、ラジオボタン、ドロップダウン、リンク、日付、時刻、日時、ルックアップです
- 各データ型に保存できるフィールド型は下表の通りです:
データ型 | フィールド型 |
---|---|
文字 | サポートされているフィールド型すべて |
数値 | 数値、計算(値が数値型の場合のみ)、ルックアップ(値が数値型の場合のみ) |
選択 | ラジオボタン、ドロップダウン ※ フィールドの値は、一致する選択肢 ID をもつ選択肢として保存されます |
日付 | 日付、計算(値が日付型の場合のみ) |
日時 | 作成日時、更新日時、日時、計算(値が日時型の場合のみ) |
Capture

See also
Script (click to open)
- 次のスクリプトが記述されている XML ファイルをダウンロードできます
- kintone-record-get.xml (C) Questetra, Inc. (MIT License)
- Professional のワークフロー基盤では、ファイル内容を改変しオリジナルのアドオン自動工程として活用できます
const FIELD_NUM = 7; // 扱えるフィールドの数
main();
function main() {
//// == 工程コンフィグ・ワークフローデータの参照 / Config & Data Retrieving ==
const auth = configs.get("conf_auth");
const basic = configs.get("conf_basic");
const domain = configs.get("conf_domain");
const guestSpaceId = configs.get("conf_guestSpaceId");
const appId = configs.get("conf_appId");
const recordId = retrieveRecordId();
const fieldCodeList = [];
const fieldValueDefList = [];
retrieveFieldConfigs(fieldCodeList, fieldValueDefList);
const apiToken = httpClient.getOAuth2Token(auth);
//// == 演算 / Calculating ==
const apiUri = determineApiUri(domain, guestSpaceId, appId, recordId);
const fieldValueList = [];
const fieldTypeList = [];
getRecord(apiUri, apiToken, basic, fieldCodeList, fieldValueList, fieldTypeList);
//// == ワークフローデータへの代入 / Data Updating ==
setDataByLists(fieldValueDefList, fieldValueList, fieldTypeList);
}
/**
* config からレコード ID を読み出す
* @return {String} recordId レコード ID
*/
function retrieveRecordId() {
const recordIdDef = configs.getObject("conf_recordId");
if (recordIdDef.matchDataType("SELECT_SINGLE")) { // 選択型データ項目の場合
const select = engine.findData(recordIdDef);
if (select === null || select.size() === 0) { // 未選択
throw "Record ID is not selected.";
}
return select.get(0).getValue();
}
return engine.findData(recordIdDef); // 文字型データ項目の場合
}
/**
* config のフィールド情報を読み出し、配列に格納する
* 以下の場合はエラーとする
* 1. フィールドコードが空で、値を保存するデータ項目が設定されている
* 2. フィールドコードが設定されていて、値を保存するデータ項目が設定されていない
* 3. 値を保存するデータ項目が重複して設定されている
* 4. フィールドコードが一つも設定されていない
* @param {Array<String>} fieldCodeList フィールドコードを格納する配列
* @param {Array<ProcessDataDefinitionView>} fieldValueDefList フィールドの値を格納するデータ項目の ProcessDataDefinitionView を格納する配列
*/
function retrieveFieldConfigs(fieldCodeList, fieldValueDefList) {
const dataItemNumList = []; // データ項目の重複確認用
for (let i = 0; i < FIELD_NUM; i++) {
const fieldCodeConfigName = `conf_fieldCode${i + 1}`;
const fieldValueConfigName = `conf_fieldValue${i + 1}`;
const fieldCode = configs.get(fieldCodeConfigName);
const fieldValueDef = configs.getObject(fieldValueConfigName);
const dataItemNum = configs.get(fieldValueConfigName); // データ項目の重複確認用
if (fieldCode === "" || fieldCode === null) { // フィールドコードが空
if (fieldValueDef !== null) { // 値を保存するデータ項目が設定されている
throw `Field Code ${i + 1} is empty but Data item that will save Value ${i + 1} is set.`;
} else { // 値を保存するデータ項目が設定されていない
continue;
}
} else { // フィールドコードが設定されている
if (fieldValueDef === null) { // 値を保存するデータ項目が設定されていない
throw `Data item to save the value of ${fieldCode} is not set.`;
}
}
if (dataItemNumList.indexOf(dataItemNum) !== -1) { // 既に指定されているデータ項目
throw "The same data item is set multiple times.";
}
fieldCodeList.push(fieldCode);
fieldValueDefList.push(fieldValueDef);
dataItemNumList.push(dataItemNum); // データ項目の重複確認用
}
if (fieldCodeList.length === 0) { // フィールドコードが一つも設定されていない
throw "No Field Code is set.";
}
}
/**
* kintone REST API のレコード取得の URI を決定する
* ドメインが空、または kintone のドメインとして不正な文字列であればエラーとする
* @param {String} domain ドメイン
* @param {String} guestSpaceId ゲストスペース ID
* @param {String} appId アプリ ID
* @param {String} recordId レコード ID
* @return {String} apiUri API の URI
*/
function determineApiUri(domain, guestSpaceId, appId, recordId) {
checkDomainAndIds(domain, appId, recordId);
let apiUri = "";
if (guestSpaceId === "" || guestSpaceId === null) {
apiUri = `https://${domain}/k/v1/record.json?app=${appId}&id=${recordId}`;
} else {
if (!isValidId(guestSpaceId)) {
throw "Invalid Guest Space ID.";
}
apiUri = `https://${domain}/k/guest/${guestSpaceId}/v1/record.json?app=${appId}&id=${recordId}`;
}
return apiUri;
}
/**
* ドメイン、アプリ ID、レコード ID が空または不正な文字列であればエラーとする
* @param {String} domain ドメイン
* @param {String} appId アプリ ID
* @param {String} recordId レコード ID
*/
function checkDomainAndIds(domain, appId, recordId) {
if (domain === "" || domain === null) { // required="true" なので空になることはないが、チェック
throw "Domain is empty.";
}
const reg = new RegExp('^[0-9a-zA-Z-]{3,32}.(?:kintone.com|cybozu.com)$');
if (!reg.test(domain)) {
throw "Invalid Kintone domain.";
}
if (appId === "" || appId === null) { // required="true" なので空になることはないが、チェック
throw "App ID is empty.";
}
if (!isValidId(appId)) {
throw "Invalid App ID.";
}
if (recordId === "" || recordId === null) { // required="true" だが、データ項目の値が空の可能性がある
throw "Record ID is empty.";
}
if (!isValidId(recordId)) {
throw "Invalid Record ID.";
}
}
/**
* ID が有効か(自然数か)を判定する
* @param {String} idString ID の文字列
* @return {Boolean} 有効な ID かどうか
*/
function isValidId(idString) {
const idReg = new RegExp('^[1-9][0-9]*$');
return idReg.test(idString);
}
/**
* kintone REST API にレコード取得の GET リクエストを送信する
* @param {String} apiUri API の URI
* @param {String} apiToken API トークン
* @param {String} basic Basic 認証設定
* @param {Array<String>} fieldCodeList フィールドコードが格納された配列
* @param {Array<String>} fieldValueList フィールドの値を格納する配列
* @param {Array<String>} fieldTypeList フィールドの型を格納する配列
*/
function getRecord(apiUri, apiToken, basic, fieldCodeList, fieldValueList, fieldTypeList) {
let request = httpClient.begin()
.header("X-Cybozu-API-Token", apiToken);
if (basic !== "" && basic !== null) {
request = request.authSetting(basic);
}
//when error thrown
const response = request.get(apiUri);
const responseJson = response.getResponseAsString();
const status = response.getStatusCode();
if (status >= 300) {
engine.log(`API URI: ${apiUri}`);
const accessLog = `---GET request--- ${status}\n${responseJson}\n`;
engine.log(accessLog);
throw `Failed to get record. status: ${status}`;
}
const json = JSON.parse(responseJson);
extractFieldValues(json.record, fieldCodeList, fieldValueList, fieldTypeList);
}
/**
* レコード情報の JSON オブジェクトからフィールドコードに対応する値を読み出し、配列に格納する
* @param {Object} recordObj レコード情報の JSON オブジェクト
* @param {Array<String>} fieldCodeList フィールドコードが格納された配列
* @param {Array<String>} fieldValueList フィールドの値を格納する配列
* @param {Array<String>} fieldTypeList フィールドの型を格納する配列
*/
function extractFieldValues(recordObj, fieldCodeList, fieldValueList, fieldTypeList) {
for (const i in fieldCodeList) {
if (recordObj[fieldCodeList[i]] === undefined) { // レコード情報に一致するフィールドコードがない場合、エラー
throw `${fieldCodeList[i]} does not exist in the record.`;
}
const fieldValueObj = recordObj[fieldCodeList[i]].value;
const fieldType = recordObj[fieldCodeList[i]].type;
if (fieldValueObj === null) { // null であれば、値の配列に空文字列を push する
fieldValueList.push("");
fieldTypeList.push(fieldType);
} else if (typeof fieldValueObj === 'string') { // String であれば、値の配列に文字列を push する
fieldValueList.push(fieldValueObj);
fieldTypeList.push(fieldType);
} else { // String 以外のクラス(Object)であればエラー
throw `Unable to save the value of ${fieldCodeList[i]}. Field Type ${fieldType} is not supported.`;
}
}
}
/**
* データ項目に出力する
* @param {Array<ProcessDataDefinitionView>} dataDefList 保存先データ項目の ProcessDataDefinitionView が格納された配列
* @param {Array<String>} dataStringList 出力するデータが格納された配列
* @param {Array<String>} fieldTypeList 出力するデータのフィールド型が格納された配列
*/
function setDataByLists(dataDefList, dataStringList, fieldTypeList) {
if ((dataDefList.length !== dataStringList.length) || (dataDefList.length !== fieldTypeList.length)) {
throw "Array length does not match.";
}
for (let i in dataDefList) {
if (dataDefList[i] !== null) {
if (dataDefList[i].matchDataType("STRING")) { // 保存先データ項目が文字型の場合
// 保存先データ項目が改行に対応しておらず、保存する文字列に改行が含まれる場合のエラーは QBPMS のバリデーションに任せる
engine.setData(dataDefList[i], dataStringList[i]);
} else if (dataDefList[i].matchDataType("DECIMAL")) { // 保存先データ項目が数値型の場合
convertTypeAndSetData(dataDefList[i], dataStringList[i], fieldTypeList[i], "DECIMAL", "Numeric");
} else if (dataDefList[i].matchDataType("SELECT")) { // 保存先データ項目が選択型の場合
convertTypeAndSetData(dataDefList[i], dataStringList[i], fieldTypeList[i], "SELECT", "Select");
} else if (dataDefList[i].matchDataType("DATE")) { // 保存先データ項目が日付型の場合
convertTypeAndSetData(dataDefList[i], dataStringList[i], fieldTypeList[i], "DATE", "Date");
} else if (dataDefList[i].matchDataType("DATETIME")) { // 保存先データ項目が日時型の場合
convertTypeAndSetData(dataDefList[i], dataStringList[i], fieldTypeList[i], "DATETIME", "Datetime");
}
}
}
}
/**
* データ項目の型にしたがってデータを変換して出力する
* 対応しないフィールド型の場合はエラーとする
* 変換できない値の場合はエラーとする
* @param {ProcessDataDefinitionView} dataDef 保存先データ項目の ProcessDataDefinitionView
* @param {String} dataString 出力するデータ(変換前の文字列データ)
* @param {String} fieldType 出力するデータのフィールド型
* @param {String} dataType 保存先データ項目のデータ型
* @param {String} dataTypeLabel 保存先データ項目のデータ型の表示名(エラー出力用)
*/
function convertTypeAndSetData(dataDef, dataString, fieldType, dataType, dataTypeLabel) {
const supportedFieldTypes = { // 保存先データ項目が文字型以外の場合にサポートするフィールド型
"DECIMAL": ["NUMBER", "CALC"],
"SELECT": ["DROP_DOWN", "RADIO_BUTTON"],
"DATE": ["DATE", "CALC"],
"DATETIME": ["DATETIME", "CREATED_TIME", "UPDATED_TIME", "CALC"]
};
if (supportedFieldTypes[dataType].indexOf(fieldType) === -1) { // 対応しないフィールド型の場合はエラー
throw `The value of Field Type ${fieldType} cannot be saved to ${dataTypeLabel} type data item.`;
}
let convertedData;
if (dataString === "" || dataString === null) { // 空値の場合は null を設定
convertedData = null;
} else {
try { // CALC 等、フィールド型だけでは変換可否を判定できないものがあるので try-catch でエラーを捕捉
switch (dataType) {
case 'DECIMAL':
convertedData = new java.math.BigDecimal(dataString);
break;
case 'SELECT': // 一致する選択肢 ID がない場合のエラーは QBPMS のバリデーションに任せる
convertedData = new java.util.ArrayList();
convertedData.add(dataString);
break;
case 'DATE':
convertedData = java.sql.Date.valueOf(dataString);
break;
case 'DATETIME':
// DateFormatWrapper#parse() で AddableTimestamp にパース
convertedData = dateFormatter.parse("yyyy-MM-dd'T'HH:mm:ssX", dataString);
break;
}
} catch (e) { // 変換できない値の場合はエラー
throw `Returned value "${dataString}" cannot be saved to ${dataTypeLabel} type data item.`;
}
}
engine.setData(dataDef, convertedData);
}