こんにちは。サイボウズの楊です。
今回は関連レコードもCSV出力したい!というニーズにお応えしたいと思います。
kintoneアプリでは、他アプリのレコードを参照できる関連レコード一覧機能があります。
ひとつのフィールドをキーとし、関連するレコードを現在のレコード詳細画面に表示できます。
しかし、この場合関連レコードのデータは表示させているだけで、閲覧しているレコードにデータとして所持している訳ではありません。
またkintoneにはデータをCSV形式でダウンロードする機能があります。
レコードをCSVファイルで書き出す場合、関連レコードはそのデータを保持していないため、通常は関連レコードをCSV出力できません。
今回は、関連レコードを含めたCSVを出力するTipsを紹介できればと思います。
デモ環境で実際に動作を確認できます。
ログイン情報は
cybozu developer networkデモ環境
で確認してください。
完成したアプリには、以下のようにCSVファイル出力ボタンが表示されます。
ダウンロードしたCSVファイルのイメージは以下のとおりです。
今回使用するのはアプリストアにある「案件管理」と「顧客リスト」アプリを応用したものです。
のちほど「顧客リスト」アプリの関連レコードのフィールド設定で「案件管理」アプリが必要となりますので、先に「案件管理」のアプリの追加をしてください。
フィールドコードが異なると、正常に動作しないため注意して変更しましょう。
案件管理アプリのフィールドの設定は以下のとおりです。
なお、記載していないフィールドはデフォルトのままです。
フィールドタイプ |
フィールド名 |
フィールドコード |
文字列(1行) |
会社名 |
company |
ドロップダウン |
製品名 |
product |
計算 |
小計 |
subtotal |
顧客リストアプリに「関連レコード」フィールドを追加します。
関連レコード一覧の設定の詳細は以下のとおりです。
フィールドコードが異なると、正常に動作しないため注意して変更しましょう。
顧客リストアプリのフィールドの設定は以下のとおりです。
なお、記載していないフィールドはデフォルトのままです。
フィールドタイプ |
フィールド名 |
フィールドコード |
文字列(1行) |
会社名 |
company |
文字列(1行) |
部署名 |
division |
文字列(1行) |
担当者名 |
assignee |
文字列(1行) |
TEL |
TEL |
文字列(1行) |
メールアドレス |
Mail |
関連レコード一覧 |
関連レコード一覧 |
reference |
サンプルコードは以下のとおりです。
JSファイルはURL指定もしくはローカルから「顧客リスト」アプリに適用してください。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
/*
* related records sample program
* Copyright (c) 2014 Cybozu
*
* Licensed under the MIT License
*/
(() => {
'use strict';
kintone.events.on('app.record.index.show', (event) => {
const records = event.records;
const appId = kintone.app.getRelatedRecordsTargetAppId('reference');
// ボタンの有無をチェック
if (document.getElementById('btn-export-csv')) {
return;
}
const spaceEl = kintone.app.getHeaderMenuSpaceElement();
const CSVButtonEl = document.createElement('button');
CSVButtonEl.textContent = 'CSVファイル出力';
CSVButtonEl.id = 'btn-export-csv';
spaceEl.appendChild(CSVButtonEl);
CSVButtonEl.addEventListener('click', () => {
getMakeCsv(appId, records).then((resp) => {
downloadFile(resp);
});
});
});
// csvデータの作成
const getMakeCsv = (appId, customerRecords) => {
// 同じ会社名の関連レコードを取得
const fetchRelatedRecords = (opt_index, opt_data) => {
const index = opt_index || 0;
const data = opt_data || [];
const customerRecord = customerRecords[index];
const company = customerRecord.company.value;
const division = customerRecord.division.value;
const assignee = customerRecord.assignee.value;
const tel = customerRecord.TEL.value;
const mail = customerRecord.Mail.value;
const query = `company = "${company}"`; // 会社名をキーに該当関連レコードを取得
const params = {
app: appId,
query: query
};
return kintone.api(kintone.api.url('/k/v1/records', true), 'GET', params)
.then((resp) => {
const row = [company, division, assignee, tel, mail];
const relatedRecords = resp.records;
if (relatedRecords.length > 0) {
relatedRecords.forEach((relatedRecord) => {
row.push(relatedRecord.product.value);
row.push(relatedRecord.subtotal.value);
});
}
data.push(row.join(','));
if (customerRecords.length > index + 1) {
return fetchRelatedRecords(index + 1, data);
}
return data;
});
};
const header = ['会社名', '部署名', '担当者名', 'TEL', 'メールアドレス', '製品名', '小計'].join(',');
let csvData = [header];
return new kintone.Promise((resolve, reject) => {
fetchRelatedRecords().then((resp) => {
csvData = csvData.concat(resp);
resolve(csvData);
});
});
};
// ダウンロード関数
const downloadFile = (data) => {
const csv = data.join('\r\n');
// ファイル名
const filename = `client_case${getTimeStamp()}.csv`;
// Blob準備
const bom = new Uint8Array([0xef, 0xbb, 0xbf]);
const blob = new Blob([bom, csv], {type: 'text/csv'});
if (window.navigator.msSaveBlob) {
window.navigator.msSaveBlob(blob, filename);
} else {
const e = new MouseEvent('click', {view: window, bubbles: true, cancelable: true});
const url = window.URL || window.webkitURL;
const blobUrl = url.createObjectURL(blob);
const a = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
a.href = blobUrl;
a.download = filename;
a.dispatchEvent(e);
}
};
// ファイル名に付与する日付の取得
const getTimeStamp = () => {
const d = new Date();
const YYYY = d.getFullYear();
let MM = d.getMonth() + 1;
let DD = d.getDate();
let hh = d.getHours();
let mm = d.getMinutes();
if (MM < 10) {
MM = `0${MM}`;
}
if (DD < 10) {
DD = `0${DD}`;
}
if (hh < 10) {
hh = `0${hh}`;
} else if (mm < 10) {
mm = `0${mm}`;
}
return `${YYYY}${MM}${DD}${hh}${mm}`;
};
})();
|
今回はレコードの詳細情報を取得し、CSVファイルを手動で作成して、そのCSVファイルの中にデータを格納しています。
それでは簡単に説明します。
レコード情報と要素の取得
固定リンクがコピーされました
kintone.app.getRelatedRecordsTargetAppId('フィールドコード')
で関連レコードのアプリIDを取得します。
関連レコード一覧の参照先のアプリIDを取得する
13
|
const appId = kintone.app.getRelatedRecordsTargetAppId('reference');
|
そして、kintone.app.getHeaderMenuSpaceElement()
でボタン作成のためにレコード一覧のメニューの右側の要素を取得します。
レコード一覧のメニューの右側の要素を取得する
20
|
const spaceEl = kintone.app.getHeaderMenuSpaceElement();
|
customerRecords
は、顧客管理アプリを一覧表示したときのevent.records
です。
indexでひとつずつレコードを取り出し、各変数の中にフィールドの値を格納します。
39
|
const customerRecord = customerRecords[index];
|
query
では、検索条件でキーとなる会社名を変数に格納します。
複数のレコードを取得する
47
|
const query = `company = "${company}"`; // 会社名をキーに該当関連レコードを取得
|
document.getElementById('btn-export-csv')
をif文の条件とすることで、ボタンがない場合のみボタン要素を生成し、増殖バグを防ぎます。
増殖バグを防ぐ処理については、
レコード一覧画面にボタンを配置してみよう
を参照してください。
15
16
|
// ボタンの有無をチェック
if (document.getElementById('btn-export-csv')) {
|
以下でボタンを押した際に処理を行います。
26
|
CSVButtonEl.addEventListener('click', () => {
|
CSVファイルの作成
固定リンクがコピーされました
CSVファイルの各項目名(ヘッダー)は手動で作成する必要があります。
CSVはカンマ区切りなので、join(',')
で配列の要素を結合した文字列を生成します。
70
|
const header = ['会社名', '部署名', '担当者名', 'TEL', 'メールアドレス', '製品名', '小計'].join(',');
|
関連レコードはkintone.api
で取得します。
kintone.api
は非同期実行なので、顧客ごとの関連レコードを取得するためfetchRelatedRecords
を再帰的に呼び出します。
取得した関連レコードの内容をCSVの各行に追加します。
35
36
|
// 同じ会社名の関連レコードを取得
const fetchRelatedRecords = (opt_index, opt_data) => {
|
現在の日付をファイル名に
固定リンクがコピーされました
Dateオブジェクトで現在の日時を取得します。
106
|
const d = new Date();
|
getMonth()
は前の月を取得するため、注意して+1します。
108
|
let MM = d.getMonth() + 1;
|
月や日付の桁数が一桁場合、前に0を足して二桁にします。
112
113
114
115
116
117
118
119
120
121
122
|
if (MM < 10) {
MM = `0${MM}`;
}
if (DD < 10) {
DD = `0${DD}`;
}
if (hh < 10) {
hh = `0${hh}`;
} else if (mm < 10) {
mm = `0${mm}`;
}
|
最後にYYYY + MM + DD + hh + mm
の形式で返します。
123
|
return `${YYYY}${MM}${DD}${hh}${mm}`;
|
データのダウンロードについては
集計したデータをCSVでダウンロードするには
を参照してください。
いかがでしたでしょうか。
これで関連レコードもCSV出力できるようになりました。
また上記のテクニックを活用することで関連レコードに限らず、自由に他アプリからのデータをCSV出力できます。
ぜひお試しください。