Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

google-spreadsheet

theoephraim993kUnlicense4.1.4TypeScript support: included

Google Sheets API -- simple interface to read/write data and manage sheets

google spreadsheets, google sheets, google, spreadsheet, spreadsheets, sheets, gdata, api, googleapis, drive, google docs, google drive

readme

google-spreadsheet

The most popular Google Sheets API wrapper for javascript / typescript

NPM version CI status Known Vulnerabilities NPM

  • multiple auth options (via google-auth-library) - service account, OAuth, API key, ADC, etc
  • cell-based API - read, write, bulk-updates, formatting
  • row-based API - read, update, delete (based on the old v3 row-based calls)
  • managing worksheets - add, remove, resize, update properties (ex: title), duplicate to same or other document
  • managing docs - create new doc, delete doc, basic sharing/permissions
  • export - download sheet/docs in various formats

Docs site - Full docs available at https://theoephraim.github.io/node-google-spreadsheet


🌈 Installation - pnpm i google-spreadsheet
(or npm i google-spreadsheet --save or yarn add google-spreadsheet)

Examples

The following examples are meant to give you an idea of just some of the things you can do

IMPORTANT NOTE - To keep the examples concise, I'm calling await at the top level which is not allowed in some older versions of node. If you need to call await in a script at the root level and your environment does not support it, you must instead wrap it in an async function like so:

(async function () {
  await someAsyncFunction();
})();

The Basics

import { GoogleSpreadsheet } from 'google-spreadsheet';
import { JWT } from 'google-auth-library';

// Initialize auth - see https://theoephraim.github.io/node-google-spreadsheet/#/guides/authentication
const serviceAccountAuth = new JWT({
  // env var values here are copied from service account credentials generated by google
  // see "Authentication" section in docs for more info
  email: process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL,
  key: process.env.GOOGLE_PRIVATE_KEY,
  scopes: ['https://www.googleapis.com/auth/spreadsheets'],
});

const doc = new GoogleSpreadsheet('<the sheet ID from the url>', serviceAccountAuth);

await doc.loadInfo(); // loads document properties and worksheets
console.log(doc.title);
await doc.updateProperties({ title: 'renamed doc' });

const sheet = doc.sheetsByIndex[0]; // or use `doc.sheetsById[id]` or `doc.sheetsByTitle[title]`
console.log(sheet.title);
console.log(sheet.rowCount);

// adding / removing sheets
const newSheet = await doc.addSheet({ title: 'another sheet' });
await newSheet.delete();

More info:

Working with rows

// if creating a new sheet, you can set the header row
const sheet = await doc.addSheet({ headerValues: ['name', 'email'] });

// append rows
const larryRow = await sheet.addRow({ name: 'Larry Page', email: 'larry@google.com' });
const moreRows = await sheet.addRows([
  { name: 'Sergey Brin', email: 'sergey@google.com' },
  { name: 'Eric Schmidt', email: 'eric@google.com' },
]);

// read rows
const rows = await sheet.getRows(); // can pass in { limit, offset }

// read/write row values
console.log(rows[0].get('name')); // 'Larry Page'
rows[1].set('email', 'sergey@abc.xyz'); // update a value
rows[2].assign({ name: 'Sundar Pichai', email: 'sundar@google.com' }); // set multiple values
await rows[2].save(); // save updates on a row
await rows[2].delete(); // delete a row

Row methods support explicit TypeScript types for shape of the data

type UsersRowData = {
  name: string;
  email: string;
  type?: 'admin' | 'user';
};
const userRows = await sheet.getRows<UsersRowData>();

userRows[0].get('name'); // <- TS is happy, knows it will be a string
userRows[0].get('badColumn'); // <- will throw a type error

More info:

Working with cells

await sheet.loadCells('A1:E10'); // loads range of cells into local cache - DOES NOT RETURN THE CELLS
console.log(sheet.cellStats); // total cells, loaded, how many non-empty
const a1 = sheet.getCell(0, 0); // access cells using a zero-based index
const c6 = sheet.getCellByA1('C6'); // or A1 style notation
// access everything about the cell
console.log(a1.value);
console.log(a1.formula);
console.log(a1.formattedValue);
// update the cell contents and formatting
a1.value = 123.456;
c6.formula = '=A1';
a1.textFormat = { bold: true };
c6.note = 'This is a note!';
await sheet.saveUpdatedCells(); // save all updates in one call

More info:

Managing docs and sharing

const auth = new JWT({
  email: process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL,
  key: process.env.GOOGLE_PRIVATE_KEY,
  scopes: [
    'https://www.googleapis.com/auth/spreadsheets',
    // note that sharing-related calls require the google drive scope
    'https://www.googleapis.com/auth/drive.file',
  ],
});

// create a new doc
const newDoc = await GoogleSpreadsheet.createNewSpreadsheetDocument(auth, { title: 'new fancy doc' });

// share with specific users, domains, or make public
await newDoc.share('someone.else@example.com');
await newDoc.share('mycorp.com');
await newDoc.setPublicAccessLevel('reader');

// delete doc
await newDoc.delete();

Why?

This module provides an intuitive wrapper around Google's API to simplify common interactions

While Google's v4 sheets API is much easier to use than v3 was, the official googleapis npm module is a giant autogenerated meta-tool that handles every Google product. The module and the API itself are awkward and the docs are pretty terrible, at least to get started.

In what situation should you use Google's API directly?
This module makes trade-offs for simplicity of the interface. Google's API provides a mechanism to make many requests in parallel, so if speed and efficiency are extremely important to your use case, you may want to use their API directly. There are also many lesser-used features of their API that are not implemented here yet.

Support & Contributions

This module was written and is actively maintained by Theo Ephraim.

Are you actively using this module for a commercial project? Want to help support it?
Buy Theo a beer

Sponsors

None yet - get in touch!

Contributing

Contributions are welcome, but please follow the existing conventions, use the linter, add relevant tests, and add relevant documentation.

The docs site is generated using docsify. To preview and run locally so you can make edits, run npm run docs:preview and head to http://localhost:3000 The content lives in markdown files in the docs folder.

License

This is free and unencumbered public domain software. For more info, see https://unlicense.org.

changelog

Changelog

All notable changes to this project will be documented in this file. Dates are displayed in UTC.

Generated by auto-changelog.

4.1.3

  • Read headers in batch on getRows() #693
  • Fix type of sheetsById in docs #658
  • Update authentication.md #699
  • update axios, fix new google-auth-library issue, fixes #701 #700 #701
  • fix setDataValidation docs 2bca048
  • Update FUNDING.yml 5459a87
  • use correct type in docs 6d210a2
  • allow CI manual reruns e10cbb1

4.1.2

  • add setDataValidation #691
  • fix docs typos
  • move from CircleCI to GH Actions 53fe384

4.1.1

  • chore(deps): allow google-auth-library@^9.0.0 #657
  • docs: remove outdated reference to doc.useServiceAccountAuth() a60104b

4.1.0

  • fix: match color style field to that in google api fce1605

4.0.3

  • docs: get/set are sync methods #637
  • docs(readme.md): fix wrong import #633
  • docs: docs cleanup and improvements 882bd73
  • docs(small updates): fixed a few small grammar issues and copied readme to docs index 867bb63
  • fix: handle trimming null/undefined header values 3ef8fcf
  • build: call build in release task c306dc0

4.0.2

  • fix: lodash imports needs explicit .js extension 4cad156

v4.0.1

  • chore: switch back from lodash-es to lodash to avoid ESM issues c808eed

v4.0.0

  • Typescript rewrite! 903e923
    • no more lagging/outdated types from DefinitelyTyped (@types/google-spreadsheet)
    • refactor GoogleSpreadsheetRow to be more TS friendly
    • add new typed value getters/setters to GoogleSpreadsheetCell (stringValue, boolValue, numberValue)
    • cell.formulaError -> cell.errorValue
    • refactor authentication to rely directly on google-auth-library as a peer dependency
    • support Application Default Credentials (auto inject credentials in some environments)
    • refactor document creation into static method, similar auth setup
    • support basic sharing / permissions management (drive api)
    • support document delete
    • replaced GoogleSpreadsheetFormulaError with GoogleSpreadsheetCellErrorValue and now handles all possible cell error types
    • fully deprecated sheet.getInfo,
  • chore: set up release tooling (release-it, auto-changelog, commitizen) dc831e3

v3.3.0

13 May 2022

  • add sheet.duplicate, clean up dependencies, docus updates 4cec425
  • bump/audit dependencies 42d918b
  • add export methods 07b0783
  • clearRows and clear(range) 5bfa235
  • clarify docs around loading cells c1d2f23

v3.2.0

7 November 2021

  • Bump path-parse from 1.0.6 to 1.0.7 #492
  • Bump hosted-git-info from 2.8.5 to 2.8.9 #463
  • Bump handlebars from 4.6.0 to 4.7.7 #458
  • Bump normalize-url from 4.5.0 to 4.5.1 #479
  • Bump tmpl from 1.0.4 to 1.0.5 #511
  • Bump ws from 5.2.2 to 5.2.3 #519
  • Bump y18n from 4.0.0 to 4.0.3 #520
  • Bump docsify from 4.10.2 to 4.12.1 #521
  • insertDimension cleanup 71cf945
  • add insertDimension functionality 6a4a9b9
  • add tests for insertDimension 84d0a3a
  • custom header row index 198e9c3
  • small readme clarification 8c0932c
  • update axios 0058852
  • actually bump lodash... 402885b
  • fix docs typo 94cdf90

v3.1.15

6 November 2021

  • version 3.1.15 - oauth support b11da48
  • fix: package.json & package-lock.json to reduce vulnerabilities 197e351
  • Bump ini from 1.3.5 to 1.3.8 77f5372
  • Minor update to OAuth docs faad98c

v3.1.14

26 December 2020

v3.0.14

27 November 2020

  • Bump dot-prop from 4.2.0 to 4.2.1 #413
  • Bump node-fetch from 2.6.0 to 2.6.1 #391
  • Bump yargs-parser from 13.1.1 to 13.1.2 #389
  • Merge and unmerge cells #385
  • update readme to include add sheetsByTitle #388
  • fixing error message #398
  • create new doc functionality, readme updates 28d4f6e
  • Added merge and unmerge cells operations 9d30a61
  • upgrade google-auth-library 9efcade
  • merge/unmerge docs a7aabfe
  • bump npm version 2b4bc7e
  • fixing error message to conform to others 7bd4a82

v3.0.13

17 August 2020

  • swap location of readme file and symlink so its within the GH pages publishing source 30578c2
  • npm did not like the symlinked readme. Github doesnt like it either. Revert to copying the file, but added a script 250c702
  • fix small docs issue 15cbcb4
  • fix test 21f97a0

v3.0.12

17 August 2020

  • Fix Link to GoogleSpreadsheetCell in README.md #380
  • Feature/service account impersonation #358
  • Add sheetsByTitle getter #349
  • Bump acorn from 5.7.3 to 5.7.4 #319
  • doc: rm getRows side-effect #320
  • doc: scroll to page top on navigation #324
  • use symlink for docs readme, add impersonate docs d2fbc5c
  • bump dependency versions 4ae02d9
  • fix bug setting background color 626581b
  • add doc.sheetsByTitle getter 37084fd
  • fix addRows offset issue - force google API to start add rows at column A 5c24469
  • short doc for impersonateAs option of useServiceAccountAuth 1e30921
  • add impersonateAs option for useServiceAccountAuth c0e4b5f
  • package version bump - 3.0.12 301dfa9

v3.0.11

12 April 2020

  • fix loadCells when using an API key only 15a3619

v3.0.10

14 March 2020

  • add short delays when running tests in CI to avoid rate limits 188374f
  • fix bug loading multiple cell ranges abb8217

v3.0.9

28 February 2020

  • add options when inserting/saving rows for RAW and INSERT modes a6baa65
  • update docs - fix saveCells, update emojis 0102f1c
  • bunch of fixes dc38223
  • fix saveCells f6cfcc3
  • add doc.useRawAccessToken to allow oauth usage 0bdf5b2
  • fix readme badges e38181b
  • update readme with deprecation info d4853bc
  • fix github link on docs site 85c59bc

v3.0.8

13 February 2020

  • do not add dangling comma on functions #299

v3.0.7

12 February 2020

  • add sheet.addRows() to add multiple rows at once 6914fb6
  • fix bug when loading empty cell multiple times be80634
  • version bump 08976fe

v3.0.6

11 February 2020

  • Minor doc fix #288
  • Docs Sample Code - "loadCells" instead of "getCells" #291
  • V3.0 - rewrite using google sheets v4 api #269
  • fix broken cell.save() 69e98b3
  • throw original error if response body doesnot have more info c19dc22
  • version bump 786be59
  • Fix typo in docs f933c17

v3.0.5

6 February 2020

  • fix docs links, fix encoding on row save and sheet clear, better errors for empty headers 6c035a3

v3.0.4

4 February 2020

  • support special chars in sheet names that are used in URLs 561c6eb
  • fix sheetcount, make row props enumerable bd8eba6

v3.0.3

4 February 2020

  • better handling of empty headers and dupes 30ec42c

v3.0.2

3 February 2020

  • rename doc.getInfo to loadInfo 87812c3

v3.0.1

3 February 2020

v3.0.0

3 February 2020

  • V3.0 - rewrite using google sheets v4 api #269
  • work in progress d2d84ac

v2.0.9

3 February 2020

  • deprecation warning #272

v2.0.8

3 September 2019

v2.0.7

15 January 2019

  • Fix formatting 6f50866
  • Move value setter/getter to prototype d6d299e
  • Move from var to prototype functions 3870b98
  • Move updateValuesFromResponseData to prototype 2a30fde
  • Move save to prototype 6da73df
  • add getters for "edit" and "self" links, and don't set them if they match our pattern 09b0591
  • Move numericValue setter/getter to prototype da9ff6f
  • Move formula setter/getter to prototype 49473c5
  • xml_parser only needed there f4c929a
  • handle feed request functions that need 3rd callback parameter ( raw xml ) 689c56c
  • the same for "id" - if it matches our pattern, then construct it instead of saving long url strings in each cell bd813eb
  • Move getSelf to prototype ac70e40
  • Move getEdit to prototype 9458bd7
  • Move getId to prototype 9a93a74
  • Move clearValue to prototype 6df93a7
  • Move valueForSave getter to prototype 31cc75e
  • Move setValue to prototype 1d35038
  • [eslint] fixed smaller eslint issues 969b25e
  • Move del to prototype b34b969
  • more memory friendly way to cycle through entries - we get rid of old entries after they've been added 1795596
  • Expose SpreadsheetCell 6c5527a
  • [eslint] fixed spreadsheet not defined error f66ad9b
  • [eslint] removed shadowing of data and unused i d081f27
  • delete response body, since we have a parsed result already f01ee4b
  • version bump to 2.0.7 0e5f3f7
  • [eslint] removed shadowing of opts 049e1ae
  • request nowadays handles gzip compression automatically - worth a try if it's supported 04498e5

v2.0.6

3 October 2018

v2.0.5

25 June 2018

  • Fixes #205 #208
  • Merge pull request #208 from jpike88/patch-1 #205
  • version bump for google auth dependency 935d399
  • Security fix 0cd7b25

v2.0.4

26 May 2017

  • Made cell.save consistent with row.save in terms of requiring a callback (#105) #114
  • Show how to catch errors using async in README #113
  • make sure google_auth is not empty #149
  • fix link to structured query #147
  • Added missing step on creating API Key #130
  • Fix vars leaking into global scope #121
  • Fix sample code in README.md #134
  • Writing requires authentication #139
  • 128 LF and CR in SpreadsheetCell.save #129

  • fix GoogleSpreadsheet.removeWorksheet with tests and docs 868ad3f
  • return the row object when adding a new row, with tests and docs 0b241d6
  • reorder new cell linefeed test cf67752
  • 128 fix LF and CR in SpreadsheetCell.save 12b7acc

  • Made cell.save consistent with row.save in terms of requiring a callback. (#105) d1a2dc5
  • Show how to catch errors using async b86ea1f
  • Scope links vars to prevent global leakage 6af5c86
  • version bump! f233257
  • fix failing author test, not sure why case changed! 5a52afa

v2.0.3

10 May 2016

  • fix typo on GooogleSpreadsheet 23f25f9

v2.0.2

4 May 2016

  • Update readme to show syntax highlighting #96
  • fix readme 31a6fb5
  • improve cells test file 8460b18
  • version bump for fixed readme (to republish) 79d1435
  • fix readme note about heroku 5affe0c

v2.0.1

27 March 2016

  • bugfix for undefined inputValue 60ba19e

v2.0.0

16 March 2016

  • Making title work (likely due to a Google change) #65
  • V2.0! FULL TEST SUITE! FIXES + IMPROVEMENTS! fbe9d82
  • fix gdata version 3 bug with save on getRows result a7f8dc4
  • rename getRows options and fix docs f65c746
  • use if-match header on PUT + bump version 4dad296
  • remove extra xml tag 9868a85
  • bump version for title fix 7d15a76

v1.1.0

25 October 2015

v1.0.1

6 July 2015

v1.0.0

5 July 2015

  • Update README.md #36
  • v1.0.0 - rebuild auth stuff to support service accounts and add docs b295ddb
  • improve docs 4775eec

v0.3.1

27 April 2015

  • Adding numericValue property to cell #13
  • add better error message for private sheets cbedb87
  • Added numericValue to cell. f6beb06

v0.3.0

27 April 2015

  • making sure query isn't null on getRows #18
  • Show what actually went wrong when saving a row #20
  • Added options visibility & projection #25
  • Error when request does not receive expected response #26
  • README.md: Fixed typographical error ('alot' -> 'a lot'). #28
  • Missing parentheses in the example #19
  • Check if worksheet_id is a number and greater than 0 #10
  • Update index.js #11
  • Updated google client login dependency #9
  • fix bugs, add docs, v0.3.0! 160824c
  • Check if worksheet_id is a number and greater than 0, since 0 is a valid worksheet id 2b53c69
  • silence logging b0946ee
  • making sure query isn't null 06ffe10
  • added return empty c6bc1ea
  • Turns out it had two missing parentheses cb4fad1
  • The example had a missing parentheses so it threw a run-time error 12b3c03

v0.2.7

12 March 2014

v0.2.6

9 December 2013

  • Better Column Name Handling #4
  • Swapped out hardcoded version number in readme for gemfury badge #3
  • Fixed README indentation and added explicit syntax highlighting #1
  • Fixes #1 by modifying regex to cope with new lines in the text (http://stackoverflow.com/questions/1068280/javascript-regex-multiline-flag-doesnt-work) #1
  • update dependencies to fix some inconsistent encoding issues 08cfaf1
  • Upgraded xml2js to fix problem with reading newlines, also added tests! 6093d41
  • initial code to handle cell-based feeds 6a0bb39
  • Cleanup - remove unused tests, update readme d0fd8c8
  • Cope with updating entries that contain new lines, slight improvement in loading data with new lines (I think) 53c375f
  • Added very low level support for querying list-based feeds a75f976
  • Fix for inserting new rows with 0 values 2bf2eba
  • Fixed readme example 37866c8
  • Fix for column names with uppercase and whitespace characters. 5fe1a57
  • Removed console output b693536
  • Version bump e700edd
  • Updated package.json with better keywords and description 926e404

v0.2.0

4 March 2013

  • v0.2.0 rewrite - now built-in auth, edit/add/deleting rows, major code cleanup 5a15dc3
  • (Un)licensed the project. 58583b5

0.1.0

9 February 2013

  • minor patches #8
  • The repo your repo could be like! #6
  • Support some API options and fixed handling "gsx" response. #4
  • Support some API request options 337e52b
  • Wrote a couple of tests. They hit actual goog api tho - so kinda slow. 56bde4a
  • .gitignore. pedantic semicolon. basic example code. edde04e
  • README updates. 331a15d
  • .npmignore 9205e22
  • Removed TODO from README. 3d6ef69
  • show require in googleclientlogin example. 71c70f5
  • :gem: Added travis.yml file :gem: a08d77d
  • bumped to 0.1.0 bfa6a2c
  • derp - wrong require path for test code. b94479d
  • fixed indent. 830ceae
  • xml parser fix per issue #7. 2853816
  • :gem: Travis CI image/link in readme :gem: 9ebe382

v0.0.3

9 November 2011

  • Fix package.json oopsies. #2
  • Fixed package.json d57c9b0
  • Bumped to v0.0.3 f1da9eb

v0.0.2

9 November 2011

v0.0.1

1 August 2011