Last active
September 18, 2023 05:45
-
-
Save mura-/b06966117dd25aaedd64 to your computer and use it in GitHub Desktop.
kintone x handsontable
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(() => { | |
'use strict'; | |
let hot; // handsontable用変数 | |
// kintoneのレコード更新・追加時は、レコード番号などアップデートできないフィールドがあるので、除外するためのメソッド | |
const setParams = (record) => { | |
const result = {}; | |
for (const prop in record) { | |
if (['レコード番号', '作成日時', '更新日時', '作成者', '更新者', 'ステータス', '作業者'].indexOf(prop) === -1) { | |
result[prop] = record[prop]; | |
} | |
} | |
return result; | |
}; | |
// kintoneのレコード取得用メソッド | |
const getRecords = (callback, errorCallback) => { | |
kintone.api('/k/v1/records', 'GET', {app: kintone.app.getId(), query: 'order by レコード番号 asc limit 500'}, | |
(resp) => { | |
callback(resp); | |
}, | |
(resp) => { | |
errorCallback(resp); | |
} | |
); | |
}; | |
// kintoneのレコード更新、追加用メソッド | |
const saveRecords = (records, changedDatas, callback, errorCallback) =>{ | |
const requests = []; | |
const updateRecords = []; | |
const insertRecords = []; | |
let changedRows = []; | |
// 変更されたセルの配列から、変更があった行だけ抜き出す | |
for (let i = 0; i < changedDatas.length; i++) { | |
changedRows.push(changedDatas[i][0]); | |
} | |
// 変更があった行番号の重複を排除 | |
changedRows = changedRows.filter((x, i, self) => { | |
return self.indexOf(x) === i; | |
}); | |
// 変更があった行から、レコード追加か変更かを判断し、クエリをつくる | |
for (let i = 0; i < changedRows.length; i++) { | |
if (records[changedRows[i]]['レコード番号'].value === null) { | |
insertRecords.push( | |
setParams(records[changedRows[i]]) | |
); | |
} else { | |
updateRecords.push({ | |
id: records[changedRows[i]]['レコード番号'].value, | |
record: setParams(records[changedRows[i]]) | |
}); | |
} | |
} | |
// 更新用bulkRequest | |
requests.push({ | |
method: 'PUT', | |
api: '/k/v1/records.json', | |
payload: { | |
app: kintone.app.getId(), | |
records: updateRecords | |
} | |
}); | |
// 追加用bulkRequest | |
requests.push({ | |
method: 'POST', | |
api: '/k/v1/records.json', | |
payload: { | |
app: kintone.app.getId(), | |
records: insertRecords | |
} | |
}); | |
// bulkrequestで一括で追加、更新。 | |
// 失敗した場合はロールバックされる。 | |
kintone.api('/k/v1/bulkRequest', 'POST', {requests: requests}, | |
(resp) => { | |
console.dir(requests); | |
console.dir(resp); | |
callback(resp); | |
}, | |
(resp) => { | |
errorCallback(resp); | |
} | |
); | |
}; | |
// kintoneのレコード削除用メソッド | |
const deleteRecords = (records, index, amount, callback, errorCallback) => { | |
let i; | |
const ids = []; | |
for (i = index; i < index + amount; i++) { | |
ids.push(records[i]['レコード番号'].value); | |
} | |
kintone.api('/k/v1/records', 'DELETE', {app: kintone.app.getId(), ids: ids}, | |
(resp) => { | |
callback(resp); | |
}, | |
(resp) => { | |
errorCallback(resp); | |
} | |
); | |
}; | |
// 定期的にkintone上のデータを再取得する | |
const autoload = () =>{ | |
getRecords((resp)=> { | |
hot.loadData(resp.records); | |
}); | |
setTimeout(()=> { | |
autoload(); | |
}, 10000); // 10秒。APIの呼び出し数の上限があるので、必要に応じて変更してください。 | |
}; | |
// 一覧ビュー表示用のイベントハンドラ | |
kintone.events.on(['app.record.index.show'], (event) => { | |
if (event.viewId !== 5263125) return; | |
const container = document.getElementById('sheet'); | |
// handsontable初期化 | |
hot = new Handsontable(container, { | |
// この時点ではdataは入力せず、あとから読み込ませるようにする。(データ更新時も再読み込みさせたいため) | |
data: [], | |
// 空白行 | |
minSpareRows: 10, | |
// 表示したいカラム | |
colHeaders: ['レコード番号', '会社名', '先方担当者名', '見込み時期', '確度', '製品名', '単価', 'ユーザー数', '小計'], | |
// コンテキストメニュー(右クリックメニュー)を指定。今回は削除用メニューのみ。 | |
contextMenu: ['remove_row'], | |
// 必要に応じてreadOnlyの指定ができます。 | |
columns: [ | |
{data: 'レコード番号.value', readOnly: true}, | |
{data: '会社名.value'}, | |
{data: '先方担当者名.value'}, | |
{data: '見込み時期.value'}, | |
{data: '確度.value'}, | |
{data: '製品名.value'}, | |
{data: '単価.value'}, | |
{data: 'ユーザー数.value'}, | |
{data: '小計.value', readOnly: true} | |
], | |
// スプレットシート上のレコードを削除したときに呼び出されるイベント | |
// 引数indexは削除する行 | |
// 引数amountは削除する行数 | |
beforeRemoveRow: (index, amount) => { | |
// kintoneのレコードを削除する | |
deleteRecords(hot.getSourceData(), index, amount, | |
(deleteRecordsResp)=> { | |
console.dir(deleteRecordsResp); | |
getRecords((getRecordsResp)=> { | |
// 削除後、データを再読み込み | |
hot.loadData(getRecordsResp.records); | |
}); | |
}, | |
(resp)=> { | |
console.dir(resp); | |
} | |
); | |
}, | |
// スプレットシート上のレコードが編集されたときに呼び出されるイベント | |
afterChange: (change, source) => { | |
console.log(source); | |
// データ読み込み時はイベントを終了 | |
if (source === 'loadData') { | |
return; | |
} | |
// kintoneのレコードを更新、追加する | |
saveRecords(hot.getSourceData(), change, | |
(resp)=> { | |
console.dir(resp); | |
getRecords((saveRecordsResp)=> { | |
// 更新後、データを再読み込み | |
hot.loadData(saveRecordsResp.records); | |
}, | |
(getRecordResp)=> { | |
// レコード取得失敗時に呼び出される | |
console.dir(getRecordResp); | |
}); | |
}, | |
(resp)=> { | |
// 更新・追加時に呼び出される | |
console.dir(resp); | |
} | |
); | |
} | |
}); | |
// レコードを取得してhandsontableに反映 | |
getRecords((resp)=> { | |
hot.loadData(resp.records); | |
autoload(); | |
}); | |
}); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment