首页 > 解决方案 > Google Sheets Node.js 快速入门指南:如何将从 API 返回的行数组返回到变量中

问题描述

我正在为 Nodejs 使用 Google 的 Sheets Quickstart API。我已经正确安装了所有东西,并且代码运行良好。

main 函数位于代码的末尾,称为 listMajors()。它产生一个二维的行数组。该代码只是将 rows 数组映射到 console.log() 中,其中包括每行中的几个项目。

我打算在我正在创建的复杂应用程序中使用这个 API。我可以更改电子表格 ID 和范围,并从我的工作表中获取值。

我想要做的是将这个“行”数组放在函数之外并放入一个新变量中。我想这样做是因为我的大部分代码将使用行值编写,我不想在 listMajors() 函数中编写所有代码。

我的问题是,有没有办法让这个 listMajors() 函数将二维数组返回到我可以在全局范围内使用的变量中?我无法做到这一点。我试图将函数设置为等于变量并return rows;在函数末尾添加一条语句。我收到错误“ReferenceError:未定义 listMajors”。

这是原始代码:

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) => {
  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',
    range: 'Class Data!A2:E',
  }, (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.');
    }
  });
}

这是我试图做出的改变:

var data = function listMajors(auth) {
  const sheets = google.sheets({version: 'v4', auth});
  sheets.spreadsheets.values.get({
    spreadsheetId: '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms',
    range: 'Class Data!A2:E',
  }, (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]}`);
      //});
      return rows;
    } else {
      console.log('No data found.');
    }
  });
}

console.log(data);

我相信我可以在不同的文件中编写所有其他函数,导入它们,然后在 listMajors() 函数中调用它们。这是我的问题的解决方案,但我真正想知道的是是否有不同的方法来实现这一点。

标签: javascriptnode.jsgoogle-sheets-api

解决方案


  • 您想检索从sheets.spreadsheets.values.get()其他函数检索到的值。
  • 您想使用 googleapis 和 Node.js 来实现这一点。
  • 您已经能够使用 Sheets API 获取和放置电子表格的值。

如果我的理解是正确的,这个答案怎么样?请认为这只是几个可能的答案之一。

修改后的脚本:

在这种情况下,首先main()调用一个测试用例。所以首先,请修改如下。

从:

authorize(JSON.parse(content), listMajors);

至:

authorize(JSON.parse(content), main);

并请添加main()和修改listMajors()如下。

main()listMajors()

async function listMajors(auth) {
  const sheets = google.sheets({ version: "v4", auth });
  const res = await sheets.spreadsheets.values.get({
    spreadsheetId: '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms',
    range: 'Class Data!A2:E',
  });
  return res.data.values;
}

async function main(auth) {
  const data = await listMajors(auth);
  console.log(data);
}

通过以上修改,当main()运行时,可以看到用sheets.spreadsheets.values.get()at检索到的值data

如果我误解了您的问题并且这不是您想要的方向,我深表歉意。


推荐阅读