2
votes

Guide de démarrage rapide de Google Sheets Node.js: Comment renvoyer le tableau de lignes renvoyé par l'API dans une variable

J'utilise l'API de démarrage rapide de Google Sheets pour Nodejs. J'ai tout installé correctement et le code fonctionne correctement.

La fonction principale est à la fin du code, appelée listMajors (). Il produit un tableau bidimensionnel de lignes. Le code mappe simplement le tableau de lignes dans un console.log () comprenant quelques éléments de chaque ligne.

Je prévois d'utiliser cette API dans une application complexe que je crée. Je peux modifier l'ID et la plage de la feuille de calcul et obtenir les valeurs de ma feuille correctement.

Ce que je veux faire, c'est obtenir ce tableau de «lignes» en dehors de la fonction et dans une nouvelle variable. Je veux faire cela car une grande partie de mon code va être écrite en utilisant les valeurs des lignes et je ne veux pas avoir à écrire tout le code à l'intérieur de la fonction listMajors ().

Ma question est la suivante: y a-t-il un moyen de faire en sorte que cette fonction listMajors () renvoie le tableau à deux dimensions dans une variable que je peux utiliser dans la portée globale? Je n'ai pas été en mesure d'accomplir cela. J'ai essayé de simplement définir la fonction égale à une variable et d'ajouter une ligne de return rows; instruction à la fin de la fonction. J'ai eu l'erreur "ReferenceError: listMajors is not defined".

Voici le code original:

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);

C'était le changement que j'essayais de faire:

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.');
    }
  });
}

Je crois que je pourrais écrire toutes mes autres fonctions dans un fichier différent, les importer, puis les appeler simplement dans la fonction listMajors (). C'est une solution à mon problème, mais ce que je veux vraiment savoir, c'est s'il existe une manière différente d'accomplir cela.


1 commentaires

Est-ce que cela répond à votre question? Comment renvoyer la réponse d'un appel asynchrone?


3 Réponses :


2
votes
  • Vous souhaitez récupérer les valeurs récupérées à partir de sheets.spreadsheets.values.get() à une autre fonction.
  • Vous voulez y parvenir en utilisant googleapis avec Node.js.
  • Vous avez déjà pu obtenir et placer des valeurs pour Spreadsheet à l'aide de l'API Sheets.
  • Si ma compréhension est correcte, qu'en est-il de cette réponse? Veuillez considérer cela comme une des réponses possibles.

    Script modifié:

    Dans ce cas, comme cas de test, dans un premier temps, main() est appelée. Donc, dans un premier temps, veuillez modifier comme suit.

    De:

    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);
    }
    

    À:

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

    Et veuillez ajouter main() et modifier listMajors() comme suit.

    main() et listMajors()

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

    Par la modification ci-dessus, lorsque main() est exécuté, vous pouvez voir les valeurs récupérées avec sheets.spreadsheets.values.get() à data .

    Si j'ai mal compris votre question et que ce n'était pas la direction que vous vouliez, je m'en excuse.


0 commentaires

0
votes

y a-t-il un moyen de faire en sorte que cette fonction listMajors () renvoie le tableau à deux dimensions dans une variable que je peux utiliser dans la portée globale?

Oui et vous devez créer une variable en dehors de la déclaration de fonction , puis affecter la sortie de la fonction à la variable créée.

Voici un guide étape par étape pour créer un tableau

  1. créer un tableau majors[]
  2. ajouter des valeurs de tableau majors[] partir des colonnes Name et Majors
  3. lister les valeurs majors[] pour voir toutes les données
  4. lister les valeurs majors[1] pour voir le nom et la majeure (Anna, anglais)
Anna
Female
1. Freshman
NC
English
Basketball

Voici la sortie console.log() :

// 1
let data = {
  names : [],
  gender : [],
  classLevel : [],
  homeState : [],
  major : [],
  extracurricularActivity : []
}

// 4
function listData(row){
    console.log(data.names[row]);
    console.log(data.gender[row]);
    console.log(data.classLevel[row]);
    console.log(data.homeState[row]);
    console.log(data.major[row]);
    console.log(data.extracurricularActivity[row]);
}

function listMajors(auth) {

  const sheets = google.sheets({version: 'v4', auth});

  sheets.spreadsheets.values.get({
    spreadsheetId: '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms',
    range: 'Class Data!A2:F',
  }, (err, res) => {

    if (err) return console.log('The API returned an error: ' + err);

    const rows = res.data.values;

    if (rows.length) {
// 2
      rows.map((row) => {
        data.names.push(row[0]);
        data.gender.push(row[1]);
        data.classLevel.push(row[2]);
        data.homeState.push(row[3]);
        data.major.push(row[4]);
        data.extracurricularActivity.push(row[5]);
      });
    } else {
      console.log('No data found.');
    }
// 3
    console.log(data);
    console.log('--------------------')
// 5
    listData(2);
  });
}

A partir de maintenant, vous pouvez utiliser votre tableau majors[] comme vous le souhaitez.


Si vous souhaitez avoir plus de contrôle sur vos données, vous pouvez créer major{} objet major{}

Presque les mêmes étapes que ci-dessus:

  1. créer data{} objet data{}
  2. ajouter aux data{} objet toutes les valeurs
  3. list data{} valeurs pour voir toutes les données
  4. créer la fonction listData() pour une sortie de ligne plus facile
  5. lister Anna dans les data{} qui se trouve à la ligne 4 dans Google Sheets, mais nous évitons la première ligne, qui signifie -1, donc dans les data{} son index est 2.
[
  'Alexandra, English', 'Andrew, Math',
  'Anna, English',      'Becky, Art',
  'Benjamin, English',  'Carl, Art',
  'Carrie, English',    'Dorothy, Math',
  'Dylan, Math',        'Edward, English',
  'Ellen, Physics',     'Fiona, Art',
  'John, Physics',      'Jonathan, Math',
  'Joseph, English',    'Josephine, Math',
  'Karen, English',     'Kevin, Physics',
  'Lisa, Art',          'Mary, Physics',
  'Maureen, Physics',   'Nick, Art',
  'Olivia, Physics',    'Pamela, Math',
  'Patrick, Art',       'Robert, English',
  'Sean, Physics',      'Stacy, Math',
  'Thomas, Art',        'Will, Math'
]
--------------------
Anna, English

Ici vous pouvez voir une sortie pour listData(2) :

// 1
let majors = [];

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) {
// 2
      rows.map((row) => {
        majors.push(`${row[0]}, ${row[4]}`);
      });
    } else {
      console.log('No data found.');
    }
// 3
    console.log(majors);
    console.log('--------------------')
// 4
    console.log(majors[2])
  });
}

Il existe des moyens plus avancés de le faire, jetez un œil à la référence. J'espère que ces exemples vous aideront à démarrer votre API Google Sheets avec Node.js

Référence:


4 commentaires

Cela n'a pas fonctionné pour moi. Je suis presque sûr que listMajors est une fonction de promesse qui s'exécute de manière asynchrone. J'ai établi un tableau au préalable, poussé les valeurs dans le tableau et console.log l'arr. L'appel console.log atteint d'abord la pile des appels, enregistre un tableau vide, puis pousse toutes les valeurs dans le tableau.


@MatthewWolman Cela ne devrait vous donner aucune sorte d'erreurs. Avez-vous réussi à suivre les instructions étape par étape? Si tel est le cas, pouvez-vous mettre à jour votre message d'origine avec le fichier index.js complet? sans données sensibles


Je n'ai pas compris que vous enregistriez les éléments dans la fonction listMajor. Ce n’est malheureusement pas ce que j’ai demandé. Oui, votre code fonctionnerait si je l'exécutais tel quel. Je suis capable d'accomplir la même chose moi-même. De plus, en faisant ce que vous faites, il n'y a aucune raison de déclarer le tableau ou l'objet en dehors de la fonction de lastMajor si vous allez simplement à console.log le tableau / objet dans la portée de lastMajor. Je veux que ces données soient accessibles en dehors de la portée.


@MatthewWolman Si vous souhaitez créer des variables globales, créez simplement global.js et demandez-le dans index.js; Si vous obtenez une sortie vide, c'est parce que vous appelez des résultats trop tôt, je suppose que vous savez comment les promesses et async / attendent fonctionnent, au cas où vous ne le sauriez pas, voici uneintroduction aux promesses et à la vidéo youtube sur Async Await



0
votes

Vous pouvez regarder ma question (j'ai ajouté la solution réalisable à la fin de la question)

Je ne prétends pas que ce soit la solution parfaite car je travaille toujours sur la compréhension de l'async, du rappel, de la promesse en javascript, mais j'ai cherché sur Internet et l'utilisation de la variable de ligne en dehors de la fonction listmajor était quelque chose que je voulais réaliser et je l'ai fait avec mon code.

Intégration de Nodejs et de feuille de calcul Google (impossible de lire la propriété 'length' de undefined)


0 commentaires