質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.10%

Googleスプレッドシートにnode.js(google API)を使って文字を書き込みたい

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 1,243

lassieena

score 18

実現したいこと

Googleスプレッドシートにnode.jsで文字を書き込みたいです。Googleスプレッドシートから読み込むことはできるのですが書き込む処理がわかりません。apiはappendを使っています。エラーメッセージが長くなっています。少し削りました。

エラーメッセージ

$ node app.js
{ Error: Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.
    at createError (/home/vagrant/node_modules/axios/lib/core/createError.js:16:15)
    at settle (/home/vagrant/node_modules/axios/lib/core/settle.js:18:12)
    at IncomingMessage.handleStreamEnd (/home/vagrant/node_modules/axios/lib/adapters/http.js:201:11)
    at emitNone (events.js:91:20)
    at IncomingMessage.emit (events.js:185:7)
    at endReadableNT (_stream_readable.js:974:12)
    at _combinedTickCallback (internal/process/next_tick.js:80:11)
    at process._tickCallback (internal/process/next_tick.js:104:9)
  config: 
   { adapter: [Function: httpAdapter],
     transformRequest: { '0': [Function: transformRequest] },
     transformResponse: { '0': [Function: transformResponse] },
     timeout: 0,
     xsrfCookieName: 'XSRF-TOKEN',
     xsrfHeaderName: 'X-XSRF-TOKEN',
     maxContentLength: 2147483648,
     validateStatus: [Function],
     headers: 
      { Accept: 'application/json, text/plain, */*',
        'Content-Type': 'application/x-www-form-urlencoded',
        'User-Agent': 'google-api-nodejs-client/1.6.1',
        'Content-Length': 11 },
     method: 'post',
     url: 'https://sheets.googleapis.com/v4/spreadsheets/19Z3nQt9lY1SMw3drTR0ly-rRsLRkTjEUJjV9_vl9d18/values/sheet1!A4:append',
     paramsSerializer: [Function],
     data: 'hello world',
     params: { valueInputOption: 'RAW', key: 'auth' } },
  request: 

<-- エラー削った部分 -->

   _header: 'POST /v4/spreadsheets/スプレッドシートID/values/sheet1!A4:append?valueInputOption=RAW&key=auth HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nContent-Type: application/x-www-form-urlencoded\r\nUser-Agent: google-api-nodejs-client/1.6.1\r\nContent-Length: 11\r\nHost: sheets.googleapis.com\r\nConnection: close\r\n\r\n',
     _headers: 
      { accept: 'application/json, text/plain, */*',
        'content-type': 'application/x-www-form-urlencoded',
        'user-agent': 'google-api-nodejs-client/1.6.1',
        'content-length': 11,
        host: 'sheets.googleapis.com' },
     _headerNames: 
      { accept: 'Accept',
        'content-type': 'Content-Type',
        'user-agent': 'User-Agent',
        'content-length': 'Content-Length',
        host: 'Host' },

<-- エラー削った部分 -->

        method: 'post',
        url: 'https://sheets.googleapis.com/v4/spreadsheets/スプレッドシートID/values/sheet1!A4:append',
        paramsSerializer: [Function],
        data: 'hello world',
        params: [Object] },
     request: 
      ClientRequest {
        domain: null,
        _events: [Object],
        _eventsCount: 6,
        _maxListeners: undefined,
        output: [],
        outputEncodings: [],
        outputCallbacks: [],
        outputSize: 0,
        writable: true,
        _last: true,
        upgrading: false,
        chunkedEncoding: false,
        shouldKeepAlive: false,
        useChunkedEncodingByDefault: true,
        sendDate: false,
        _removedHeader: [Object],
        _contentLength: null,
        _hasBody: true,
        _trailer: '',
        finished: true,
        _headerSent: true,
        socket: [Object],
        connection: [Object],
        _header: 'POST /v4/spreadsheets/スプレッドシートID/values/sheet1!A4:append?valueInputOption=RAW&key=auth HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nContent-Type: application/x-www-form-urlencoded\r\nUser-Agent: google-api-nodejs-client/1.6.1\r\nContent-Length: 11\r\nHost: sheets.googleapis.com\r\nConnection: close\r\n\r\n',
        _headers: [Object],
        _headerNames: [Object],
        _onPendingData: null,
        agent: [Object],
        socketPath: undefined,
        timeout: undefined,
        method: 'POST',
        path: '/v4/spreadsheets/スプレッドシートID/values/sheet1!A4:append?valueInputOption=RAW&key=auth',
        _ended: true,
        _redirectable: [Object],
        parser: null,
        res: [Object] },
     data: { error: [Object] } },
  code: 401,
  errors: 
   [ { message: 'Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.',
       domain: 'global',
       reason: 'unauthorized' } ] }

ソースコード

const fs = require('fs');
const readline = require('readline');
const {google} = require('googleapis');


const SCOPES = ['https://www.googleapis.com/auth/spreadsheets'];


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(JSON.parse(content), Listwrite);
});

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


  fs.readFile(TOKEN_PATH, (err, token) => {
    if (err) return getNewToken(oAuth2Client, callback);
    oAuth2Client.setCredentials(JSON.parse(token));
    callback(oAuth2Client);
  });
}

function getNewToken(oAuth2Client, callback) {
  const authUrl = oAuth2Client.generateAuthUrl({
    access_type: 'offline',
    approval_prompt: 'force',
    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) console.error(err);
        console.log('Token stored to', TOKEN_PATH);
      });
      callback(oAuth2Client);
    });
  });
}

/**
 * Prints the names and majors of students in a sample spreadsheet:
 * @see スプレッドシートID
 * @param {google.auth.OAuth2} auth The authenticated Google OAuth client.
 */

function Listwrite(spreadsheetId, range, valueInputOption, _values) {
    let values = [
      [
        1
      ],
       // Additional rows ...
    ];
    values = _values;
    let resource = {
      values,
    };   
    const sheets = google.sheets('v4');

    sheets.spreadsheets.values.append({
      auth: 'auth',
      spreadsheetId: 'スプレッドシートID',
      range: 'sheet1!A4',
      valueInputOption: 'RAW',
      resource: "hello world",
    }, (err, result) => {
      if (err) return console.log(err);
      console.log(`${result.updates.updatedCells} cells appended.` + 'OK');
      resolve(result);
    });
}

試したこと

補足情報

node.js v6.11.1
googleAPI v4

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • miyabi-sun

    2019/02/12 15:18 編集

    1行目に「Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project」とあり、
    認証で拒否されているようですが、認証用のトークンファイルはどの程度まで準備をすすめましたか?
    この辺が解決すればスルッと全部動くと思うので、credentials.jsonやtoken.jsonファイルの中身を確認しながら進めてください。

    キャンセル

  • lassieena

    2019/02/12 16:46

    https://developers.google.com/sheets/api/quickstart/nodejs?authuser=1のクイックスタートをみながらcredentials.jsonとtoken.json入れました。token.jsonは実行したらできるファイルなのでコードか、credentials.jsonが間違っていないと間違っていないと思います。

    credentials.json
    {
    "installed":{
    "client_id":"クライアントID",
    "project_id":"プロジェクトID",
    "auth_uri":"https://accounts.google.com/o/oauth2~",
    "token_uri":"https://oauth2.googleapis.com~",
    "auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1~",
    "client_secret":"クライアント シークレット",
    "redirect_uris":["urn:~","http://localhost"]
    }
    }

    キャンセル

回答 1

check解決した方法

0

できました。
https://developers.google.com/sheets/api/quickstart/nodejs?authuser=1の公式の大部分をコピペしていて、公式とは違うようにListwrite関数を書いてしまったので認証できなかったのだと思います。
今回はPromise構文を使って、公式コードを変えました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.10%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる