今回は、kintoneアプリの見積書から、Googleスプレッドシートとデータを連携して見積書を出力できるようにしてみたいと思います。
Googleスプレッドシートと連携すると、帳票のテンプレートを使用して簡単にカスタマイズできる上、Emailに添付することも可能となります。
連携の流れは以下となっています。
- kintoneからGoogleのクライアントIDをもとにOAuth認証
- kintoneからGoogleのアクセストークン取得
- アクセストークンを利用してGoogle Sheets APIを実行
- kintoneアプリのレコードからGoogleスプレッドシートにデータを登録
kintoneアプリの作成
固定リンクがコピーされました
今回は、kintoneアプリの「商品見積書パック」を元にアプリを設定・変更します。
kintoneアプリストアより、左サイドメニュー上部のアプリストア検索欄に「見積書」と入力し、検索します。
「商品見積書パック」が表示されますので、「このアプリを追加」をクリックします。
「見積書」アプリを開いて、右上のギアアイコンをクリックして、アプリの設定画面に移行します。
下記テーブルを参考に、フォームに対してフィールドを追加します。
フィールドの種類 |
フィールド名 |
フィールドコード |
備考 |
日付 |
見積日 |
見積日 |
- |
文字列(1行) |
見積番号 |
見積番号 |
- |
文字列(1行) |
顧客番号 |
顧客番号 |
追加フィールド |
日付 |
有効期限 |
有効期限 |
追加フィールド |
文字列(1行) |
宛名 |
宛名 |
- |
文字列(1行) |
会社名 |
会社名 |
追加フィールド |
文字列(1行) |
郵便番号 |
郵便番号 |
追加フィールド |
文字列(1行) |
都道府県 |
都道府県 |
追加フィールド |
文字列(1行) |
住所 |
住所 |
追加フィールド |
文字列(1行) |
電話番号 |
電話番号 |
追加フィールド |
テーブル |
見積明細 |
見積明細 |
- |
文字列(1行) |
商品名 |
商品名 |
テーブル内フィールド |
数値 |
単価 |
単価 |
テーブル内フィールド |
数値 |
数量 |
数量 |
テーブル内フィールド |
計算 |
小計 |
小計 |
計算式:単価*数量 テーブル内フィールド |
計算 |
合計金額 |
合計金額 |
計算式:SUM(小計) |
文字列(複数行) |
備考 |
備考 |
- |
スペース |
- |
print_button_space |
ボタン用スペース 追加フィールド |
追加フィールドは以下のように配置します。
フィールドの設定、変更後、「フォームを保存」し、最後に「アプリを更新」します。
これで、kintoneアプリの設定は終了です。
Googleスプレッドシートの設定
固定リンクがコピーされました
1. スプレッドシートの作成
固定リンクがコピーされました
Google.com
より、ログインし、右上Googleアプリメニューより、スプレッドシートを選択します。
「+」サインをクリックして、新しいスプレッドシートを作成します。
2. アドオンの設定
固定リンクがコピーされました
今回はスプレッドシートのテンプレートアドオンを利用して、帳票を作成します。
「アドオン」メニューより、「アドオンを取得」を選択します。
検索文字列に「Template Gallery」と入力し、表示された「Template Gallery for Sheets」アドオンをクリックします。
インストール画面が表示されるので、インストールをクリックします。
インストール完了後、画面にしたがってGoogleアカウントへのアクセスを許可してください。
「アドオン」メニューより「Template Gallery for Sheets」−「Browse Template」を選択し、「Category」から、「Business」−「Invoices」をクリックします。
表示されたInvoiceテンプレートより、今回は「Billing Invoice」を選択します。
画面に従い、Google Driveにテンプレートをコピーし、「Open File」ボタンをクリックします。
「Invoice」タブのシートを選択し、ファイル名を変更し、必要に応じ、帳票タイトルや見出しを日本語に変更します。
また、このGoogleスプレッドシートのURLから、スプレッドシートIDを取得します。
以上でGoogleスプレッドシートの設定は終了です。
Google APIの認証情報の設定
固定リンクがコピーされました
1. プロジェクトの作成
固定リンクがコピーされました
次にGoogle APIを利用するためにGoogle APIの認証情報を設定します。
まず、
Google Cloudのデベロッパーコンソール
にログインします。
画面が表示されたら、「プロジェクトの選択」をクリックします。
右上の「新しいプロジェクト」をクリックして、新規プロジェクトを作成します。
プロジェクト名を入力し、「作成」ボタンをクリックすると、新規プロジェクトが作成されます。
ここではプロジェクト名を「kintone-google-spreadsheet」にします。
2. Gmail APIの有効化
固定リンクがコピーされました
再び、プロジェクト選択の画面を開き、新規作成したプロジェクトを開きます。
次に左サイドメニューより「ライブラリ」を選択し、表示された画面の左サイドメニューからGoogle Workspaceカテゴリーを選択し、「Google Sheets API」を選択します。
「有効にする」をクリックして、Google Sheets APIを有効にします。
3. 認証情報の作成
固定リンクがコピーされました
OAuth同意画面を設定します。
左サイドメニュより「OAuth同意画面」を選択し、右画面より「User Type」を指定し、「作成」ボタンをクリックします。
今回は検証用として「外部」を選択します。利用状況に応じて適切に選択してください。
アプリケーション名を入力します。
ここでは「kintone-google-spreadsheet」にします。
ユーザーサポートメールをドロップダウンメニューから選択し、デベロッパーの連絡先情報にメールアドレスを入力(ユーザーサポートメールのメールアドレスと同じでOKです)し、「保存して次へ」ボタンをクリックします。
4. クライアントIDの作成
固定リンクがコピーされました
次は、OAuthクライアントIDを作成します。
左サイドメニューより「認証情報」を選択し、右側の「+認証情報を作成」をクリックし、「OAuthクライアントID」を選択します。
アプリケーションの種類に「Webアプリケーション」を選択し、名前を自由に入力し、「承認済みのJavaScript生成元」にご自身のkintone環境のURLを入力し、「作成」ボタンをクリックします。
クライアントIDが作成されますので、メモしておきます。(後のプログラミングで使用します)
5. APIキーの作成
固定リンクがコピーされました
再び、「認証情報を作成」メニューから、今度は、「APIキー」を選択します。
APIキーが作成されますので、メモしておきます。
左サイドメニューの「認証情報」をクリックすると生成した認証情報が確認できます。
以上でGoogle APIの認証情報の設定は終了です。
今回使用するプログラム
固定リンクがコピーされました
URL指定で追加
- https://apis.google.com/js/api.js
- https://accounts.google.com/gsi/client
アップロードして追加
次の内容を「sample-google-sheets.js」として保存します。
Google APIの認証情報の設定を記述している為、
プログラムの修正
を参照して環境に合わせて修正してください。
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
|
/*
* kintone見積書アプリからGoogleスプレッドシートで帳票出力してみよう
* Copyright (c) 2022 Cybozu
*
* Licensed under the MIT License
* https://opensource.org/license/mit/
*/
/* global gapi */
/* global google */
(() => {
'use strict';
// APIキー
const API_KEY = 'GOOGLE_API_KEY';
// クライアントID
const CLIENT_ID = 'GOOGLE_CLIENT_ID';
// スプレッドシートID
const SHEET_ID = 'GOOGLE_SHEET_ID';
// ログイン状態監視用
let tokenClient = false,
gapiInited = false,
gisInited = false;
// ログイン準備ができたらログインボタン表示
const checkBeforeStart = () => {
if (gapiInited && gisInited) {
document.getElementById('login_button').style.visibility = 'visible';
}
};
const loadGapi = () => {
gapi.load('client', intializeGapiClient);
};
const intializeGapiClient = async () => {
await gapi.client.init({
apiKey: API_KEY,
discoveryDocs: ['https://www.googleapis.com/discovery/v1/apis/sheets/v4/rest'],
});
gapiInited = true;
checkBeforeStart();
};
const loadGsi = () => {
tokenClient = google.accounts.oauth2.initTokenClient({
client_id: CLIENT_ID,
scope: 'https://www.googleapis.com/auth/spreadsheets',
callback: '', // defined later
});
gisInited = true;
checkBeforeStart();
};
// Googleログイン準備
const initClient = () => {
loadGapi();
loadGsi();
};
// Googleログインボタンクリック
const handleLoginClick = () => {
tokenClient.callback = async (resp) => {
if (resp.error !== undefined) {
throw resp;
}
document.getElementById('logout_button').style.visibility = 'visible';
document.getElementById('print_button').style.visibility = 'visible';
document.getElementById('login_button').textContent = 'Refresh';
};
if (gapi.client.getToken() === null) {
tokenClient.requestAccessToken({prompt: 'consent'});
} else {
tokenClient.requestAccessToken({prompt: ''});
}
};
// ログアウト
const handleLogoutClick = () => {
const token = gapi.client.getToken();
if (token !== null) {
google.accounts.oauth2.revoke(token.access_token);
gapi.client.setToken('');
document.getElementById('login_button').textContent = 'Googleログイン';
document.getElementById('logout_button').style.visibility = 'hidden';
document.getElementById('print_button').style.visibility = 'hidden';
}
};
// 見積書印刷
const printInvoice = (event) => {
// レコードのデータの取得
const record = kintone.app.record.get().record;
if (!record) {
return;
}
// APIリクエスト
// リクエストパラメータの設定
const params = {
// スプレッドシートID
spreadsheetId: SHEET_ID
};
// 商品リストをSpreadSheet用の配列に変更
const productArray = record.見積明細.value.map((item) => [
item.value.商品名.value,
null,
null,
null,
null,
item.value.数量.value,
item.value.単価.value,
]);
// スプレッドシートに出力するデータの設定
const batchUpdateSpreadsheetRequestBody = {
valueInputOption: 'RAW',
data: [
{
range: '\'Invoice\'!A1:A6',
majorDimension: 'COLUMNS',
values: [
[
record.宛名.value + '様',
record.会社名.value,
record.郵便番号.value,
record.都道府県.value,
record.住所.value,
record.電話番号.value
]
]
},
{
range: '\'Invoice\'!F5:H7',
majorDimension: 'ROWS',
values: [
[
record.見積番号.value,
null,
record.見積日.value
],
[],
[
record.顧客番号.value,
null,
record.有効期限.value
]
]
},
{
range: '\'Invoice\'!A12:A17',
majorDimension: 'COLUMNS',
values: [
[
record.宛名.value + '様',
record.会社名.value,
record.郵便番号.value,
record.都道府県.value,
record.住所.value,
record.電話番号.value
]
]
},
{
range: '\'Invoice\'!F12:F17',
majorDimension: 'COLUMNS',
values: [
[
record.宛名.value + '様',
record.会社名.value,
record.郵便番号.value,
record.都道府県.value,
record.住所.value,
record.電話番号.value
]
]
},
{
range: '\'Invoice\'!A39:A39',
majorDimension: 'COLUMNS',
values: [
[record.備考.value]
]
},
{
range: '\'Invoice\'!A21:G38',
majorDimension: 'ROWS',
values: productArray
}
]
};
// スプレッドシートへの出力実行
const request = gapi.client.sheets.spreadsheets.values.batchUpdate(params, batchUpdateSpreadsheetRequestBody);
request.then((response) => {
alert('帳票出力に成功しました。');
}, (reason) => {
alert('エラー: ' + reason.result.error.message);
});
};
// レコード詳細画面の表示後イベント
kintone.events.on('app.record.detail.show', (event) => {
// ボタン増殖回避
if (document.getElementById('print_button') !== null) {
return event;
}
// Googleログインボタン作成
const loginButton = document.createElement('button');
loginButton.id = 'login_button';
loginButton.textContent = 'Googleログイン';
loginButton.style.visibility = 'hidden';
// Googleログアウトボタン作成
const logoutButton = document.createElement('button');
logoutButton.id = 'logout_button';
logoutButton.textContent = 'Googleログアウト';
logoutButton.style.visibility = 'hidden';
// 帳票出力ボタン作成
const printButton = document.createElement('button');
printButton.id = 'print_button';
printButton.textContent = '帳票出力';
printButton.style.visibility = 'hidden';
// 各ボタンに機能を持たせる
logoutButton.addEventListener('click', handleLogoutClick);
loginButton.addEventListener('click', handleLoginClick);
printButton.addEventListener('click', () => {
printInvoice(event);
});
// スペースフィールドに各ボタンを設置
kintone.app.record.getSpaceElement('print_button_space').appendChild(loginButton);
kintone.app.record.getSpaceElement('print_button_space').appendChild(logoutButton);
kintone.app.record.getSpaceElement('print_button_space').appendChild(printButton);
// Googleログイン準備
initClient();
return event;
});
})();
|
Googleスプレッドシートの設定
と
Google APIの認証情報の設定
で取得した各設定値をセットします。
API_KEY
:Google APIキー
CLIENT_ID
:クライアントID
SHEET_ID
:スプレッドシートIDの値
6
7
8
9
10
11
|
// APIキー
const API_KEY = 'GOOGLE_API_KEY';
// クライアントID
const CLIENT_ID = 'GOOGLE_CLIENT_ID';
// スプレッドシートID
const SHEET_ID = 'GOOGLE_SHEET_ID';
|
スコープとディスカバリードックの情報の詳細は
Google Sheets APIのガイド
を参照してください。
Google API認証
Google APIのJavaScriptクライアントとGoogle Identity Servicesライブラリをロードし、ログイン時の処理を記述します。
JavaScriptクライアントとGoogle Identity Servicesライブラリの詳細に関しましては、
Google Identity Services JavaScript SDK
を参照してください。
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
|
// ログイン状態監視用
let tokenClient = false,
gapiInited = false,
gisInited = false;
// ログイン準備ができたらログインボタン表示
const checkBeforeStart = () => {
if (gapiInited && gisInited) {
document.getElementById('login_button').style.visibility = 'visible';
}
};
const loadGapi = () => {
gapi.load('client', intializeGapiClient);
};
const intializeGapiClient = async () => {
await gapi.client.init({
apiKey: API_KEY,
discoveryDocs: ['https://www.googleapis.com/discovery/v1/apis/sheets/v4/rest'],
});
gapiInited = true;
checkBeforeStart();
};
const loadGsi = () => {
tokenClient = google.accounts.oauth2.initTokenClient({
client_id: CLIENT_ID,
scope: 'https://www.googleapis.com/auth/spreadsheets',
callback: '', // defined later
});
gisInited = true;
checkBeforeStart();
};
// Googleログイン準備
const initClient = () => {
loadGapi();
loadGsi();
};
// Googleログインボタンクリック
const handleLoginClick = () => {
tokenClient.callback = async (resp) => {
if (resp.error !== undefined) {
throw resp;
}
document.getElementById('logout_button').style.visibility = 'visible';
document.getElementById('print_button').style.visibility = 'visible';
document.getElementById('login_button').textContent = 'Refresh';
};
if (gapi.client.getToken() === null) {
tokenClient.requestAccessToken({prompt: 'consent'});
} else {
tokenClient.requestAccessToken({prompt: ''});
}
};
// ログアウト
const handleLogoutClick = () => {
const token = gapi.client.getToken();
if (token !== null) {
google.accounts.oauth2.revoke(token.access_token);
gapi.client.setToken('');
document.getElementById('login_button').textContent = 'Googleログイン';
document.getElementById('logout_button').style.visibility = 'hidden';
document.getElementById('print_button').style.visibility = 'hidden';
}
};
|
レコード詳細画面の表示後イベント
レコード詳細画面の表示後イベントは以下の関数内に記述します。
197
198
|
// レコード詳細画面の表示後イベント
kintone.events.on('app.record.detail.show', (event) => {});
|
Googleログインボタン、Googleログアウトボタン、見積書データを出力する帳票出力ボタンをスペースフィールドに設置します。
イベントリスナーにはボタンのクリックした際に呼び出される関数を設定しています。
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
|
// Googleログアウトボタン作成
const logoutButton = document.createElement('button');
logoutButton.id = 'logout_button';
logoutButton.textContent = 'Googleログアウト';
logoutButton.style.visibility = 'hidden';
// 帳票出力ボタン作成
const printButton = document.createElement('button');
printButton.id = 'print_button';
printButton.textContent = '帳票出力';
printButton.style.visibility = 'hidden';
// 各ボタンに機能を持たせる
logoutButton.addEventListener('click', handleLogoutClick);
loginButton.addEventListener('click', handleLoginClick);
printButton.addEventListener('click', () => {
printInvoice(event);
});
// スペースフィールドに各ボタンを設置
kintone.app.record.getSpaceElement('print_button_space').appendChild(loginButton);
kintone.app.record.getSpaceElement('print_button_space').appendChild(logoutButton);
kintone.app.record.getSpaceElement('print_button_space').appendChild(printButton);
|
Googleスプレッドシートへ出力
まずは、見積書アプリで設定したレコードのデータを取得します。
86
87
|
// レコードのデータの取得
const record = kintone.app.record.get().record;
|
スプレッドシートIDを変数に設定します。
91
92
93
94
95
96
|
// APIリクエスト
// リクエストパラメータの設定
const params = {
// スプレッドシートID
spreadsheetId: SHEET_ID
};
|
見積書のサブテーブルの商品リストをArrayとして設定します。
98
99
100
101
102
103
104
105
106
107
|
// 商品リストをSpreadSheet用の配列に変更
const productArray = record.見積明細.value.map((item) => [
item.value.商品名.value,
null,
null,
null,
null,
item.value.数量.value,
item.value.単価.value,
]);
|
次にGoogleスプレッドシートに出力するデータのパラメーターをJSON形式で設定します。
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
|
// スプレッドシートに出力するデータの設定
const batchUpdateSpreadsheetRequestBody = {
valueInputOption: 'RAW',
data: [
{
range: '\'Invoice\'!A1:A6',
majorDimension: 'COLUMNS',
values: [
[
record.宛名.value + '様',
record.会社名.value,
record.郵便番号.value,
record.都道府県.value,
record.住所.value,
record.電話番号.value
]
]
},
{
range: '\'Invoice\'!F5:H7',
majorDimension: 'ROWS',
values: [
[
record.見積番号.value,
null,
record.見積日.value
],
[],
[
record.顧客番号.value,
null,
record.有効期限.value
]
]
},
{
range: '\'Invoice\'!A12:A17',
majorDimension: 'COLUMNS',
values: [
[
record.宛名.value + '様',
record.会社名.value,
record.郵便番号.value,
record.都道府県.value,
record.住所.value,
record.電話番号.value
]
]
},
{
range: '\'Invoice\'!F12:F17',
majorDimension: 'COLUMNS',
values: [
[
record.宛名.value + '様',
record.会社名.value,
record.郵便番号.value,
record.都道府県.value,
record.住所.value,
record.電話番号.value
]
]
},
{
range: '\'Invoice\'!A39:A39',
majorDimension: 'COLUMNS',
values: [
[record.備考.value]
]
},
{
range: '\'Invoice\'!A21:G38',
majorDimension: 'ROWS',
values: productArray
}
]
};
|
上記で設定したリクエストを実行します。
今回は、batchUpdate関数を使って、スプレッドシートに出力しています。
187
188
189
190
191
192
193
|
// スプレッドシートへの出力実行
const request = gapi.client.sheets.spreadsheets.values.batchUpdate(params, batchUpdateSpreadsheetRequestBody);
request.then((response) => {
alert('帳票出力に成功しました。');
}, (reason) => {
alert('エラー: ' + reason.result.error.message);
});
|
スプレッドシート出力データのパラメーター設定およびAPIに関する詳細は、
Google Sheets API Referenceのspreadsheets.valuesの項目
を参照してください。
これらのプログラムを「アプリの設定 > JavaScript/CSSでカスタマイズ」下に配置します。
見積書で商品を選択するため、kintoneの商品リストアプリを開いて、いくつか商品を追加します。
見積書アプリに新規レコードを追加します。
保存後、「Googleログインボタン」が表示されます。
「Googleログインボタン」をクリックするとGoogleアカウントへの認証画面が表示されるので、メールアドレス、パスワードを入力してGoogleアカウントにログインします。
Googleスプレッドシートを作成したアカウントを選択してください。
また、認証画面を表示するには、お使いのブラウザーのポップアップ設定を有効にしてください。
以下のような警告が表示された場合は「cybozu.com(安全ではないページ)に移動」を選択してください。
「帳票出力」ボタンが画面右上に表示されるのでクリックして見積書をGoogleスプレッドシートに出力します。
見積書Googleスプレッドシートを開くとkintone見積書アプリで作成したデータが出力されています。
「ファイル」メニューから印刷したり、PDFに保存してEmailで顧客へ送信したりできます。
今回は、kintoneのアプリストアから商品見積書パックを使って、見積書をGoogleスプレッドシートに帳票出力してみました。
他にもいろいろなテンプレートを利用してGoogleスプレッドシートを帳票作成ツールとしてkintoneの機能を補う形で活用できると思いますのでぜひ、試してみてください。