やりたいこと
大量のフィールドをアプリに登録するのがめんどくさいので、スプレッドシートにフィールド情報を入力してkintoneにフィールドを登録&配置させたい。
※利用するAPI
おおまかな流れ
- 空のアプリを作る
- APIトークンを生成(アクセス権はアプリ管理だけでOK)
- スプレッドシートにフィールド名やらフィールドコードとかを入力する
- スプレッドシートに入力された情報を元にkintoneにフィールドを登録する
- スプレッドシートに入力された情報を元にフィールドを配置する
注意
↓のフィールドは対象外。ルックアップとかは設定が多すぎてめんどくさくなった...そのうち作るかも
レコード番号とかは配置はできそうだけどめんどくさくなった...そのうち作るかも
・レコード番号、作成者、更新者、作成日時、更新日時、ルックアップ、関連レコード、サブテーブル
とりあえずフィールドを置く作業を軽減したかったのでフィールド設定の更新には対応してないです。
急ぎで動くものがほしかったのでバリデーションは甘々です。
スプレッドシートの構成
A列:ここに入力した数字でレイアウトを調整※
D列:対象外以外のフィールドで入力規制
E列:true or false
F列:true or false
※行1が↓に該当します。行数は昇順にしか対応してないので1,10,8とかで入力されると想定どおりに動かないです。すみません...
コード全体
const main = (data) => {
try{
const ss = SpreadsheetApp.getActive();
const sheet = ss.getActiveSheet();
const columnLength = sheet.getMaxColumns();
const lastRow = sheet.getLastRow();
const values = sheet.getRange(2, 1, lastRow - 1, columnLength).getValues();
const apiToken = data.token;
const appId = data.appId;
const domain = data.domain;
const fieldsBody = getFieldsBody(appId, values);
const layoutBody = getLayoutBody(appId, values);
const options = {
"method": "post",
"contentType": "application/json",
"headers": {
"X-Cybozu-API-Token": apiToken
},
"payload": JSON.stringify(fieldsBody)
};
const fetchFieldsUrl = `https://${domain}.cybozu.com/k/v1/preview/app/form/fields.json`;
UrlFetchApp.fetch(fetchFieldsUrl,options);
options.method = "put";
options.payload = JSON.stringify(layoutBody);
const fetchLayoutUrl = `https://${domain}.cybozu.com/k/v1/preview/app/form/layout.json`;
UrlFetchApp.fetch(fetchLayoutUrl,options);
Browser.msgBox(`処理が完了しました。設定画面で結果を確認して下さい。https://${domain}.cybozu.com/k/admin/app/flow?app=${appId}#section=form`);
} catch (err) {
Browser.msgBox(err)
console.log(err);
}
}
const getFieldsBody = (appId, values) => {
const fieldsBody = {
"app": appId,
"properties": {}
}
values.forEach(e => {
const fieldLabel = e[1];
const fieldCode = e[2];
const fieldType = e[3];
const required = e[4] !== "" ? e[4] : false;
const unique = e[5] !== "" ? e[5] : false;
fieldsBody.properties[fieldCode] = {
"type": fieldType,
"code": fieldCode,
"label": fieldLabel,
"required": required,
"unique": unique,
}
if (e[6] !== "") {
const options = e[6].split(',');
const optionsObj = {}
for (let i = 0; i < options.length; i++) {
optionsObj[options[i]] = {
"label": options[i],
"index": i
}
}
fieldsBody.properties[fieldCode].options = optionsObj;
}
if (fieldType === "LINK") {
if (e[7] === "") {
throw new Error(`フィールドコード${fieldCode}にリンクタイプを指定してください。`)
}
fieldsBody.properties[fieldCode]["protocol"] = e[7];
}
if (fieldType === "CALC") {
if (e[8] === "") {
throw new Error(`フィールドコード${fieldCode}に計算式を指定してください。`)
}
fieldsBody.properties[fieldCode]["expression"] = e[8];
}
});
return fieldsBody;
}
const getLayoutBody = (appId, values) => {
const layoutBody = {
"app": appId,
"layout": []
}
const rows = [];
values.forEach(e => {
const rowValue = e[0];
const fieldCode = e[2];
const fieldType = e[3];
if (rows.indexOf(rowValue) === -1) {
rows.push(rowValue);
layoutBody.layout.push({
"type": "ROW",
"fields": [
{
"type": fieldType,
"code": fieldCode
}
]
})
} else {
const index = rows.indexOf(rowValue);
layoutBody.layout[index].fields.push({
"type": fieldType,
"code": fieldCode
})
}
});
return layoutBody;
}
コードの補足
const main = (data) => {
try{
const ss = SpreadsheetApp.getActive();
const sheet = ss.getActiveSheet();
const columnLength = sheet.getMaxColumns();
const lastRow = sheet.getLastRow();
const values = sheet.getRange(2, 1, lastRow - 1, columnLength).getValues();
const apiToken = data.token;
const appId = data.appId;
const domain = data.domain; // https://〇〇〇〇.cybozu.comの〇〇〇〇部分だけ
mainの引数のdataは↓のダイアログに入力したものが入ります。コードに直接情報を記載してもらっても問題ないです。
ダイアログの作り方は こちら の記事を参考にしてます。
const fieldsBody = getFieldsBody(appId, values);
getFieldsBody メソッドの処理でフィールド登録用のJSONを作成
const layoutBody = getLayoutBody(appId, values);
layoutBody メソッドでフィールドの配置を設定するためのJSONを作成
UrlFetchApp.fetch(fetchFieldsUrl,options);
これでまずフィールドをアプリに登録する。
options.method = "put";
options.payload = JSON.stringify(layoutBody);
const fetchLayoutUrl = `https://${domain}.cybozu.com/k/v1/preview/app/form/layout.json`;
UrlFetchApp.fetch(fetchLayoutUrl,options);
methodとpayloadの中身を更新して、配置を設定するリクエストを送る