Node.jsでGoogle SpreadSheetsを操作してみよう。【GAS不使用】
こんにちは、代表ののびすけです。
この記事はNode.jsアドベントカレンダー2017の記事になります。
GASじゃなくてNode.jsから直接スプレッドシートにアクセスしたい!
そう思って調べるとNode.js Quickstart | Sheets API | Google Developersが出て来ますが、JS記述も古いし英語なので少しとっつきにくいです。
ということでちょっと試して記録残そうと思います。
Google Sheets API
Google Sheets APIはスプレッドシートにアクセスできるようになるAPIです。
Google Sheets API を使用すると、スプレッドシートの要素を読み取って変更できます。 スプレッドシートは多くの設定を備えており、美しく機能的なシートを作成することができます。
普段慣れている言語でスプレッドシートにアクセス出来まるので、簡単な操作であれば、GASを使う必要もないです。
今回のサンプルはこちらに置いておきます。
環境
- Node.js v9.2.0
- macOS High Sierra
参考までに今回の僕の環境です。
では実際に作っていきます。
1. Google Sheets APIを使えるようにする
ちなみに2017年12月時点でのウィザードです。こういうのはアップデートによって画面遷移変わるので適宜読み替えてください。
Use this wizard to create or select a project in the Google Developers Console and automatically turn on the API. Click Continue, then Go to credentials.
こちらのリンクからディベロッパーコンソールにいき、
新機能のお知らせ、パフォーマンスに関するアドバイス、フィードバック調査、特典に関する最新情報をメールで受け取ります。
の質問はいいえでもたぶん大丈夫です。
認証情報に進む
を選択
この画面が出ますが、キャンセル
を選択します。
OAuth同意画面
のタブを選択し、メールアドレスを確認し、ユーザーに表示するサービス名
を入力します。
保存
を選択しましょう。
次に、認証情報
のタブを選択し、 認証情報を作成
-> OAuthクライアントID
を選択します。
その他
を選択し、任意の名前をつけて作成
。
OK
で進みます。
client_secret_xxxxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com.json
のようなファイルがダウンロードされます。
これをclient_secret.json
にリネームしましょう。
2. Node.jsプロジェクトの準備
任意のディレクトリを作成して移動します。
sheetstest
としました。
mkdir sheetstest
cd sheetstest
npm init -y
でpackage.json
を作成します。
npm init -y
このディレクトリに先ほどのclient_secret.json
を移動させます。
ls
package.json client_secret.json
こんな感じです。
利用するモジュールを追加します。
npm i googleapis google-auth-library --save
3. トークンの作成&保存 (最初だけ)
本家とは少し違うやり方です。
本家のコードだとトークンの作成&保存
作業と実際のAPI呼び出しが一緒になったコードですがトークンの作成&保存
は最初のみ行えば良いので手順を分けて紹介します。
getAndStoreToken.js
を作成します。
//getAndStoreToken.js
'use strict';
const fs = require('fs');
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const {promisify} = require('util');
const google = require('googleapis');
const googleAuth = require('google-auth-library');
//promisifyでプロミス化
const readFileAsync = promisify(fs.readFile);
const writeFileAsync = promisify(fs.writeFile);
const rlQuestionAsync = promisify(rl.question);
const SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly'];
const TOKEN_DIR = __dirname;
const TOKEN_PATH = TOKEN_DIR+'/sheets.googleapis.com-nodejs-quickstart.json';
const main = async () => {
const content = await readFileAsync(__dirname+'/client_secret.json');
const credentials = JSON.parse(content); //クレデンシャル
//認証
const clientSecret = credentials.installed.client_secret;
const clientId = credentials.installed.client_id;
const redirectUrl = credentials.installed.redirect_uris[0];
const auth = new googleAuth();
const oauth2Client = new auth.OAuth2(clientId, clientSecret, redirectUrl);
//get new token
const authUrl = oauth2Client.generateAuthUrl({
access_type: 'offline',
scope: SCOPES
});
console.log('Authorize this app by visiting this url: ', authUrl);
rl.question('Enter the code from that page here: ', (code) => {
rl.close();
oauth2Client.getToken(code, async (err, token) => {
if (err) {
console.log('Error while trying to retrieve access token', err);
return;
}
oauth2Client.credentials = token;
try {
fs.mkdirSync(TOKEN_DIR);
} catch (err) {
if (err.code != 'EEXIST') throw err;
}
await writeFileAsync(TOKEN_PATH, JSON.stringify(token));
console.log('Token stored to ' + TOKEN_PATH);
});
});
};
main();
このプログラムを実行します。
node getAndStoreToken.js
https://accounts.google.com/~
で始まるURLが表示されるのでこれをコピーしてブラウザで開きます。
アカウント選択画面になります。 複数Googleアカウントを持っている人は、今回アクセスしようとしているアカウントを選択します。
許可
で進みます。
認証用のコードが発行されます。
これをコピーしてターミナルに貼り付けてエンターキーで進みます。
Token stored to /Users/n0bisuke/dotstudio/playground/sheetstest/sheets.googleapis.com-nodejs-quickstart.json
などと表示されてjsonファイルが保存されます。
sheets.googleapis.com-nodejs-quickstart.json
がフォルダ内に確認できればOKです。
4. いよいよシートにアクセス
さて最後の手順です。
getSheetsData.js
を作成しましょう。
//getSheetsData.js
'use strict';
const fs = require('fs');
const {promisify} = require('util');
const google = require('googleapis');
const googleAuth = require('google-auth-library');
const sheets = google.sheets('v4');
//promisifyでプロミス化
const readFileAsync = promisify(fs.readFile);
const ssValuesGetAsync = promisify(sheets.spreadsheets.values.get);
const TOKEN_DIR = __dirname;
const TOKEN_PATH = TOKEN_DIR + '/sheets.googleapis.com-nodejs-quickstart.json';
const main = async () => {
//クレデンシャル情報の取得
const content = await readFileAsync(__dirname+'/client_secret.json');
const credentials = JSON.parse(content); //クレデンシャル
//認証
const clientSecret = credentials.installed.client_secret;
const clientId = credentials.installed.client_id;
const redirectUrl = credentials.installed.redirect_uris[0];
const auth = new googleAuth();
const oauth2Client = new auth.OAuth2(clientId, clientSecret, redirectUrl);
const token = await readFileAsync(TOKEN_PATH);
oauth2Client.credentials = JSON.parse(token);
//API経由でシートにアクセス
const apiOptions = {
auth: oauth2Client,
spreadsheetId: '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms',
range: 'Class Data!A2:E',
};
const response = await ssValuesGetAsync(apiOptions);
//結果を表示
console.log(response);
};
main();
これを実行します。
$ node getSheetsData.js
{ range: '\'Class Data\'!A2:E101',
majorDimension: 'ROWS',
values:
[ [ 'Alexandra', 'Female', '4. Senior', 'CA', 'English' ],
[ 'Andrew', 'Male', '1. Freshman', 'SD', 'Math' ],
[ 'Anna', 'Female', '1. Freshman', 'NC', 'English' ],
[ 'Becky', 'Female', '2. Sophomore', 'SD', 'Art' ],
[ 'Benjamin', 'Male', '4. Senior', 'WI', 'English' ],
[ 'Carl', 'Male', '3. Junior', 'MD', 'Art' ],
[ 'Carrie', 'Female', '3. Junior', 'NE', 'English' ],
[ 'Dorothy', 'Female', '4. Senior', 'MD', 'Math' ],
[ 'Dylan', 'Male', '1. Freshman', 'MA', 'Math' ],
[ 'Edward', 'Male', '3. Junior', 'FL', 'English' ],
[ 'Ellen', 'Female', '1. Freshman', 'WI', 'Physics' ],
[ 'Fiona', 'Female', '1. Freshman', 'MA', 'Art' ],
[ 'John', 'Male', '3. Junior', 'CA', 'Physics' ],
[ 'Jonathan', 'Male', '2. Sophomore', 'SC', 'Math' ],
[ 'Joseph', 'Male', '1. Freshman', 'AK', 'English' ],
[ 'Josephine', 'Female', '1. Freshman', 'NY', 'Math' ],
[ 'Karen', 'Female', '2. Sophomore', 'NH', 'English' ],
[ 'Kevin', 'Male', '2. Sophomore', 'NE', 'Physics' ],
[ 'Lisa', 'Female', '3. Junior', 'SC', 'Art' ],
[ 'Mary', 'Female', '2. Sophomore', 'AK', 'Physics' ],
[ 'Maureen', 'Female', '1. Freshman', 'CA', 'Physics' ],
[ 'Nick', 'Male', '4. Senior', 'NY', 'Art' ],
[ 'Olivia', 'Female', '4. Senior', 'NC', 'Physics' ],
[ 'Pamela', 'Female', '3. Junior', 'RI', 'Math' ],
[ 'Patrick', 'Male', '1. Freshman', 'NY', 'Art' ],
[ 'Robert', 'Male', '1. Freshman', 'CA', 'English' ],
[ 'Sean', 'Male', '1. Freshman', 'NH', 'Physics' ],
[ 'Stacy', 'Female', '1. Freshman', 'NY', 'Math' ],
[ 'Thomas', 'Male', '2. Sophomore', 'RI', 'Art' ],
[ 'Will', 'Male', '4. Senior', 'FL', 'Math' ] ] }
このサンプルではこちらのワークブックへアクセスして情報を取得しています。
ちなみに用語的には
- ワークブック=Googleスプレッドシートの1ファイル
- シート=ワークブック内のタブ、シート
というニュアンスです。
//省略
const apiOptions = {
auth: oauth2Client,
spreadsheetId: '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms',
range: 'Class Data!A2:E',
};
//省略
ほかのワークブックにアクセスする場合はhttps://docs.google.com/spreadsheets/d/
の後に続くIDをspreadsheetId
に指定して実行しましょう。range
はシート名:取得する範囲
という形式で指定して、指定したシートの指定した範囲からセルの情報を取得します。
おわりに
これで次回以降は4番目の手順だけでスプレッドシートにアクセスできます。
client_secret.json
やsheets.googleapis.com-nodejs-quickstart.json
をコピーしてサーバー設置しておけば自動更新する仕組みなども作れます。
スプレッドシートは色々な場面で利用されているツールなので是非システム連携などに活用してみて下さい。
応用としてはこちらの内容で使っています。
それでは!