使用 Google Sheets API 获取表格最后一行(使用 Node.js)
結論:得出結論
因为没有类似于GAS的getLastRow方法,所以您可以使用spreadsheets.values.append来添加空行,并从返回值中获取最后一行。
安装
1. 在GCP上启用Sheets API。
2. 在凭据页面上创建OAuth Client ID(选择应用程序类型为桌面应用),并将client_secret文件保存为credentials.json。
3. 安装Google API包。
npm install googleapis@39 --save
代码 (Mandarin Chinese: mǎ)
请复制粘贴以下文件并保存在 credentials.json 的相同位置运行。
※请将 SPREADSHEET_ID 和 SHEET_NAME 更改为您自己的值)
※身份验证部分的代码与 Google 官方的quickstart 完全相同。
const fs = require('fs');
const readline = require('readline');
const { google } = require('googleapis');
//最終行を取得したいシートの名前とスプレッドシートIDを指定=====
const SPREADSHEET_ID = '*************************';
const SHEET_NAME = 'シート1';
//====================================================
const SCOPES = ['https://www.googleapis.com/auth/spreadsheets'];
const CLIENT_SECRET_PATH = 'credentials.json';
const TOKEN_PATH = 'token.json'; // トークンファイル名(トークンファイルは初めてこのファイルを実行する際に自動生成される)
fs.readFile(CLIENT_SECRET_PATH, (err, content) => {
if (err) return console.log('Error loading client secret file:', err);
authorize(JSON.parse(content), getLastRow);
});
/**
認証関数 既に認証されていればcallbackのみ実行
*/
function authorize(credentials, callback) {
const { client_secret, client_id, redirect_uris } = credentials.installed;
const oAuth2Client = new google.auth.OAuth2(
client_id, client_secret, redirect_uris[0]);
// Check if we have previously stored a token.
fs.readFile(TOKEN_PATH, (err, token) => {
if (err) return getNewToken(oAuth2Client, callback);
oAuth2Client.setCredentials(JSON.parse(token));
callback(oAuth2Client);
});
}
/**
トークン生成関数 既にtokenファイルがあればcallbackのみ実行
*/
function getNewToken(oAuth2Client, callback) {
const authUrl = oAuth2Client.generateAuthUrl({
access_type: 'offline',
scope: SCOPES,
});
console.log('Authorize this app by visiting this url:', authUrl);
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question('Enter the code from that page here: ', (code) => {
rl.close();
oAuth2Client.getToken(code, (err, token) => {
if (err) return console.error('Error while trying to retrieve access token', err);
oAuth2Client.setCredentials(token);
// Store the token to disk for later program executions
fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => {
if (err) return console.error(err);
console.log('Token stored to', TOKEN_PATH);
});
callback(oAuth2Client);
});
});
}
/**
最終行を取得する関数
*/
async function getLastRow(auth) {
const sheets = google.sheets({ version: 'v4', auth });
const lastRow = await new Promise((resolve, reject) => {
sheets.spreadsheets.values.append({
spreadsheetId: SPREADSHEET_ID,
range: `${SHEET_NAME}!A1`,
valueInputOption: 'USER_ENTERED',
insertDataOption: 'INSERT_ROWS',
resource: {
values: [
[],
],
}
}, (err, result) => {
if (err) {
// Handle error.
console.log(err);
} else {
//result.data.tableRangeが無い = シートのどのセルにも値が入力されていないので、0を返す
if(!result.data.tableRange) return resolve(0);
const match = result.data.tableRange.match(/^.*![A-Z]+\d+:[A-Z]+(?<lastRow>\d+)$/);
if(match){
resolve(match.groups.lastRow);
} else {
//1つのセルのみ入力されているシートの場合は上記の正規表現ではエラーになる
const match_only1cell = result.data.tableRange.match(/^.*![A-Z]+(?<lastRow>\d+)$/);
resolve(match_only1cell.groups.lastRow);
}
}
})
});
//最終行を出力
console.log(`lastRow: ${lastRow}`);
}
说明
這個類別具備”GetValues”和”SetValues”功能。
const fs = require('fs');
const readline = require('readline');
const { google } = require('googleapis');
class GoogleSheetsClass {
constructor() {
this.SCOPES = ['https://www.googleapis.com/auth/spreadsheets'];
this.sheets = null;
//認証しsheetsオブジェクトを取得しておく
fs.readFile(CLIENT_SECRET_PATH, (err, content) => {
if (err) return console.log('Error loading client secret file:', err);
this.authorize(JSON.parse(content), auth => {
this.sheets = google.sheets({ version: 'v4', auth });
});
});
}
/**
認証関数 既に認証されていればcallbackのみ実行
*/
authorize(credentials, callback) {
const { client_secret, client_id, redirect_uris } = credentials.installed;
const oAuth2Client = new google.auth.OAuth2(
client_id, client_secret, redirect_uris[0]);
// Check if we have previously stored a token.
fs.readFile(TOKEN_PATH, (err, token) => {
if (err) return this.getNewToken(oAuth2Client, callback);
oAuth2Client.setCredentials(JSON.parse(token));
callback(oAuth2Client);
});
}
/**
トークン生成関数 既にtokenファイルがあればcallbackのみ実行
*/
getNewToken(oAuth2Client, callback) {
const authUrl = oAuth2Client.generateAuthUrl({
access_type: 'offline',
scope: this.SCOPES,
});
console.log('Authorize this app by visiting this url:', authUrl);
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question('Enter the code from that page here: ', (code) => {
rl.close();
oAuth2Client.getToken(code, (err, token) => {
if (err) return console.error('Error while trying to retrieve access token', err);
oAuth2Client.setCredentials(token);
// Store the token to disk for later program executions
fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => {
if (err) return console.error(err);
console.log('Token stored to', TOKEN_PATH);
});
callback(oAuth2Client);
});
});
}
//getLastRow
async getLastRow(spreadsheet_id, sheet_name) {
return new Promise((resolve, reject) => {
this.sheets.spreadsheets.values.append({
spreadsheetId: spreadsheet_id,
range: `'${sheet_name}'!A1`,
valueInputOption: 'USER_ENTERED',
insertDataOption: 'INSERT_ROWS',
resource: {
values: [
[],
],
}
}, (err, result) => {
if (err) {
// Handle error.
throw err;
} else {
//result.data.tableRangeが無い = シートのどのセルにも値が入力されていないので、0を返す
if(!result.data.tableRange) return resolve(0);
const match = result.data.tableRange.match(/^.*![A-Z]+\d+:[A-Z]+(?<lastRow>\d+)$/);
if(match){
resolve(match.groups.lastRow);
} else {
//1つのセルのみ入力されているシートの場合は上記の正規表現ではエラーになる
const match_only1cell = result.data.tableRange.match(/^.*![A-Z]+(?<lastRow>\d+)$/);
resolve(match_only1cell.groups.lastRow);
}
}
})
});
}
/*
** getValues
** rangeは"A1:B2"形式で指定
*/
async getValues(spreadsheet_id, sheet_name, range){
return new Promise((resolve, reject) => {
this.sheets.spreadsheets.values.get({
spreadsheetId: spreadsheet_id,
range: `'${sheet_name}'!${range}`,
}, (err, result) => {
if (err) { throw err; } else {
resolve(result.data.values);
}
});
});
}
/*
** setValues
** rangeは"A1:B2"形式、 valuesは二次元配列を指定
*/
async setValues(spreadsheet_id, sheet_name, range, values){
return new Promise((resolve, reject) => {
this.sheets.spreadsheets.values.update({
spreadsheetId: spreadsheet_id,
range: `'${sheet_name}'!${range}`,
valueInputOption: "USER_ENTERED",
resource : {
values : values //[[]]
}
}, (err, result) => {
if (err) { throw err; } else {
resolve(result.data);
}
});
});
}
}