GoogleSheets的操作

使用NodeJS操作GoogleSheets

行程前準備

在GCP上建立一個Google Sheets API專案

啟動Sheets API服務

建立OAuth用戶端憑證並下載json檔到專案路徑

複製官方範例的程式碼(https://developers.google.com/sheets/api/quickstart/nodejs)

安裝googleapis(yarn add googleapis)

官方範例內容

const fs = require('fs');
const readline = require('readline');
const {google} = require('googleapis');
// If modifying these scopes, delete token.json.
const SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly'];
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
const TOKEN_PATH = 'token.json';
// Load client secrets from a local file.
fs.readFile('credentials.json', (err, content) => {//credentials.json修改成自己的憑證路徑
 if (err) return console.log('Error loading client secret file:', err);
 // Authorize a client with credentials, then call the Google Sheets API.
 authorize(JSON.parse(content), listMajors);
});
/**
* Create an OAuth2 client with the given credentials, and then execute the
* given callback function.
* @param {Object} credentials The authorization client credentials.
* @param {function} callback The callback to call with the authorized client.
*/
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);
 });
}
/**
* Get and store new token after prompting for user authorization, and then
* execute the given callback with the authorized OAuth2 client.
* @param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for.
* @param {getEventsCallback} callback The callback for the authorized client.
*/
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);
   });
 });
}
/**
* Prints the names and majors of students in a sample spreadsheet:
* @see https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit
* @param {google.auth.OAuth2} auth The authenticated Google OAuth client.
*/
function listMajors(auth) {
 const sheets = google.sheets({version: 'v4', auth});
 sheets.spreadsheets.values.get({
   spreadsheetId: '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms',//google sheets id
   range: 'Class Data!A2:E',//指定讀取的範圍,Class Data則是分頁簿名稱
 }, (err, res) => {
   if (err) return console.log('The API returned an error: ' + err);
   const rows = res.data.values;
   if (rows.length) {
     console.log('Name, Major:');
     // Print columns A and E, which correspond to indices 0 and 4.
     rows.map((row) => {
       console.log(`${row[0]}, ${row[4]}`);
     });
   } else {
     console.log('No data found.');
   }
 });
}

憑證路徑修改完後可執行專案的主程式檔,將會進行授權app的認證,網頁上會出現授權碼,將授權碼貼到終端機上

建立Auth驗證函數

官方範例上要操作sheets的API是透過authorize函式驗證,為了方便性所以我們重構成以下程式碼

function getAuth(fn){//fn參數用來接收要執行的函式
 fs.readFile('憑證.json',(err,content)=>{
   if(err) return console.error(err);
   authorize(JSON.parse(content),fn);
 })
}

取得sheets上的工作表

async function getSheets(auth) {
 const sheets = google.sheets({ version: 'v4', auth });
 const request = {
   spreadsheetId: '你的ID',
   includeGridData: false
 }
 try {
   const response = (await sheets.spreadsheets.get(request)).data;//有執行順序需求所以使用async...await
   const sheets_info = response.sheets;
   sheets_info.forEach(element => {//最終得到的結果會是以陣列型態回傳,可以使用instanceof驗證
     console.log(element);
   });
 } catch (e) {
   console.log(e);
 }
}
getAuth(getSheets);//呼叫Auth驗證函數,將要執行的函數傳遞過去

建立新的工作表

async function addSheets(auth){
 const sheets=google.sheets({ version: 'v4', auth });
 const request={
   spreadsheetId: yourId,
   resource:{
     requests:[{
       addSheet:{
         properties:{
           title:'測試工作表標題',
         }
       }
     }]
   }
 };
 try{
   const response=(await sheets.spreadsheets.batchUpdate(request)).data;
 }catch(e){
   console.error(e);
 }
}
getAuth(addSheets);

/*
執行時候可能出現權限不足問題(GaxiosError: Insufficient Permission)
解決方式:
1.先刪除一開始產生的token.json
2.修改SCOPES變數為:const SCOPES = ['https://www.googleapis.com/auth/spreadsheets'];
3.重新驗證後會產生一個具有讀寫權限的token.json
*/

新增資料到工作表

async function addValues(auth){
 const sheets=google.sheets({ version: 'v4', auth });
 const title='測試工作表標題';
 const request={
   spreadsheetId:yourId,
   range:`${title}!A1:A3`,//寫入的範圍從A1寫到A3,title為sheets名稱
   valueInputOption: "USER_ENTERED",//寫入的選項
   resource:{
     values:[['test'],['dev'],['col']]//寫入的值,以二維陣列表示
   }
 };
 try{
   await sheets.spreadsheets.values.update(request);
   console.log('資料寫入成功!');
 }catch(e){
   console.error(e);
 }
}

取得工作表內的資料

async function getSheetsValues(auth) {
 const sheets = google.sheets({ version: 'v4', auth });
 const request = {
   spreadsheetId: yourId,
   range:'測試工作表標題'//要取得的範圍,目前是取得整張工作表
 }
 try {
   const response = (await sheets.spreadsheets.values.get(request)).data;
   console.log(JSON.stringify(response,null,2));
 } catch (e) {
   console.log(e);
 }
}

GoogleSheetsAPI裡的功能還很多,詳細資料內容:https://developers.google.com/sheets/api/quickstart/quickstarts-overview