kintone の一覧画面に「この一覧を印刷」「この一覧を集計」のようなボタンを置くと、すぐに2つの壁に当たります。
- 画面に出ているのは1ページ分(20件など)だけ。
event.recordsでは全件にならない。 - REST API のレコード一覧の取得(
GET /k/v1/records.json)は、1回で500件まで。
この記事では、建設向けの kintone プラグイン(作業日報の印刷、工程表、原価の予実表、出面の集計、写真台帳)で共通に使っている取り方を、実際のコードで見ます。中身は次の4つです。
- 一覧の絞り込みと並び順を、そのまま REST API に渡す
-
limitとoffsetで500件ずつ取り、上限で止める -
totalCountで「取りきれなかった件数」を知らせる - 添付ファイルを
fetchで取り、同時に4本まで読む
コードは2026年11月8日に kintone の開発環境で動かして確かめています。画面の写真は、その環境の架空のデータです。
1. 一覧の絞り込みを引き継ぐ:getQuery と getQueryCondition
利用者が一覧で絞り込んだ条件をそのまま使えると、「印刷したい物だけ先に絞る」という自然な使い方ができます。kintone には、そのための関数が2つあります。
| 関数 | 返るもの |
|---|---|
kintone.app.getQuery() |
絞り込み + 並び順 + limit / offset(いま画面に出ているページ) |
kintone.app.getQueryCondition() |
絞り込みの条件だけ |
並び順も引き継ぎたいときは getQuery() を使い、末尾のページ指定だけを外します(kintone/daily-report/src/js/desktop.js)。
function listQuery() {
return (kintone.app.getQuery() || '').replace(/\s*limit\s+\d+(\s+offset\s+\d+)?\s*$/i, '').trim();
}
getQuery() の末尾には limit 20 offset 0 のようなページ指定が付いているので、それを正規表現で取り除きます。残るのは 作業日 >= "2026-11-01" order by 作業日 asc のような「条件 + 並び順」です。
自分で条件を足したいときは getQueryCondition() を使います。出面(人工)の月次集計では、一覧の絞り込みに「その月」の範囲を足しています(kintone/dezura/src/js/desktop.js)。
var condition = (kintone.app.getQueryCondition() || '').trim();
var range = config.date + ' >= "' + month + '-01" and ' + config.date + ' <= "' + month + '-' + pad(daysIn(month)) + '"';
var query = (condition ? '(' + condition + ') and ' : '') + range + ' order by $id asc';
元の条件を かっこで包んでから and でつなぐのが大事です。元の条件に or が入っていると、かっこがないと優先順位が変わって別の条件になります。
2. 500件ずつ取り、上限で止める
取得は、offset をずらしながら自分を呼び直す形にしています。作業日報の印刷の例です(kintone/daily-report/src/js/desktop.js)。
var MAX_RECORDS = 100;
var FETCH_LIMIT = 500;
// (中略)
function fetchRecords(query) {
var collected = [];
var total = null;
function step(offset) {
var size = Math.min(FETCH_LIMIT, MAX_RECORDS - collected.length);
var body = {app: kintone.app.getId(), query: (query ? query + ' ' : '') + 'limit ' + size + ' offset ' + offset};
if (offset === 0) body.totalCount = true;
return kintone.api(kintone.api.url('/k/v1/records.json', true), 'GET', body).then(function(response) {
if (offset === 0 && response.totalCount !== null && response.totalCount !== undefined) total = Number(response.totalCount);
collected = collected.concat(response.records);
if (response.records.length < size || collected.length >= MAX_RECORDS) return {records: collected, total: total};
return step(offset + size);
});
}
return step(0);
}
読みどころは3つです。
(1) 1回の件数を「残り」で決める。 size = Math.min(500, 上限 − 取った件数) なので、上限ちょうどで止まり、余分に取りません。
(2) 終わりの判定は「返ってきた件数 < 頼んだ件数」。 最後のページは頼んだより少なく返るので、そこで止めます。ちょうど割り切れたときは、もう1回だけ空の結果を取りに行って止まります。
(3) プラグインごとに上限を決める。 同じ関数を、用途に合わせた上限で使っています。
| プラグイン | 上限 | 理由 |
|---|---|---|
| 作業日報・KY記録の印刷 | 100件 | 1件がA4の1枚。100枚を超える印刷は、絞ってからのほうがよい |
| 原価の予実表(一覧) | 2,000件 | 表の1行が1件で軽い |
| 写真台帳 | 写真300枚 | 画像の読み込みが重い |
| 工程表 | 1,000件 | 1件が1行。A3横で数ページに収まる量 |
| 出面の月次集計 | 5,000件 | 1か月分だけを取る。1日に何十件も入るアプリがある |
offset で取る方法は、offset が大きくなるほど遅くなり、kintone では offset に上限(10,000)もあります。ここでは上限をどれも5,000件以下にしているので、その範囲に収まります。もっと多く取るときは、$id の大きい順に並べて「前回の最後の $id より小さいもの」を取る方法や、カーソル API を使います。
開発環境の出面のアプリ(1か月に620件)で集計すると、500件と120件の2回に分けて全件を取り、合計が620になりました。
必要なフィールドだけ取る
原価の予実表では、使うフィールドだけを fields で指定して、通信量を減らしています(kintone/genka/src/js/desktop.js)。
var fields = ['$id', config.table, actualTable, config.contract, config.project, config.no].filter(function(code, index, all) { return code && all.indexOf(code) === index; });
設定で選ばれなかったもの(空)と、同じコードの重なりを filter で除いています。同じテーブルを2回指定しないようにするためです。
3. totalCount で取りきれなかった件数を知らせる
最初の1回だけ totalCount: true を付けると、条件に合う全件数が返ります。毎回付けると数える手間が増えるので、最初だけにしています。
上限で止めたときは、黙って一部だけ印刷せず、残りの件数を画面に出します(kintone/daily-report/src/js/desktop.js)。
var notes = [];
if (found.total !== null && found.total > found.records.length) {
notes.push('上限' + MAX_RECORDS + '件。残り ' + (found.total - found.records.length) + '件は、絞り込んでから印刷してください');
}
105件ある一覧で押すと、100件の帳票を作り、上に次のように出ます。
「全部印刷したつもりが途中まで」を防ぐための1行です。
4. 添付ファイルを取る:file.json と同時に4本
写真台帳のプラグインは、添付ファイルの画像を取って台帳に並べます。添付ファイルは GET /k/v1/file.json に fileKey を渡して取ります。中身は JSON ではなくファイルそのものなので、kintone.api ではなく fetch で取ります(kintone/photo-ledger/src/js/desktop.js)。
function fetchImage(fileKey) {
var url = kintone.api.urlForGet('/k/v1/file.json', {fileKey: fileKey}, true);
return fetch(url, {headers: {'X-Requested-With': 'XMLHttpRequest'}, credentials: 'same-origin'}).then(function(response) {
if (!response.ok) throw new Error('HTTP ' + response.status);
return response.blob();
}).then(function(blob) {
return URL.createObjectURL(blob);
});
}
-
kintone.api.urlForGetで、クエリ文字列つきの URL を作れます。第3引数のtrueはゲストスペースへの対応です。 - ログイン中のセッションで REST API を呼ぶときは、
X-Requested-With: XMLHttpRequestのヘッダーが要ります。kintone.apiは自動で付けますが、fetchでは自分で付けます。 - 取った Blob は
URL.createObjectURLで<img>に渡し、台帳を閉じるときにURL.revokeObjectURLで解放しています。
300枚を一度に取りに行くと、ブラウザーにも kintone にも負担がかかります。そこで、同時に4本までにしています。
var CONCURRENCY = 4;
// (中略)
function loadImages(photos, onProgress) {
var next = 0;
var finished = 0;
function worker() {
if (next >= photos.length) return Promise.resolve();
var photo = photos[next++];
return fetchImage(photo.file.fileKey).then(function(src) {
// (中略:img に読み込ませる)
}).catch(function() {
photo.failed = true;
}).then(function() {
onProgress(++finished);
return worker();
});
}
var workers = [];
for (var i = 0; i < CONCURRENCY; i++) workers.push(worker());
return Promise.all(workers);
}
開発環境で写真8枚のアプリを開くと、file.json の呼び出しは8回、同時に走ったのは最大4本で、8枚とも表示されました。
4つの「作業者」が、共有の next から次の写真を取っていきます。1枚が終わると同じ作業者が次を取るので、常に4本までしか走りません。1枚が失敗しても catch で印を付けて先へ進むので、全体は止まりません。最後に「読み込み失敗 ○枚」として画面に出しています。
ライブラリーを入れずに、ES5 の範囲(var と Promise)で書いているのは、kintone のプラグインとしてそのまま読み込めるようにするためです。
まとめ
- 一覧の絞り込みは
getQuery()の末尾のlimit/offsetを外して使う。条件を足すならgetQueryCondition()をかっこで包む。 - 500件ずつ
offsetで取り、用途ごとの上限で止める。止めたらtotalCountで残りを知らせる。 - 添付ファイルは
file.jsonをfetchで。X-Requested-Withを忘れない。同時に走らせる数は絞る。
ソースと配布先
この記事のコードは kintone プラグイン「作業日報・KY記録プリント」ほか(MIT License)の一部です。入れ方と設定:https://genbakoe.com/kintone/daily-report/?utm_source=qiita&utm_medium=referral&utm_campaign=kintone-rest-api-records-offset / ソース:https://github.com/Genbacoe/kintone-plugins
※ kintone はサイボウズ株式会社の登録商標です。このプラグインと記事は、サイボウズ株式会社の公式のものではありません。

