google-spreadsheet 3.0.14 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +1 -0
- package/Changelog.md +10 -0
- package/README.md +9 -13
- package/TODO +73 -0
- package/lib/GoogleSpreadsheet.js +52 -3
- package/lib/GoogleSpreadsheetCell.js +0 -1
- package/lib/GoogleSpreadsheetWorksheet.js +69 -14
- package/package.json +6 -6
package/.eslintrc.js
CHANGED
package/Changelog.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
TODO: set this up to be automated and pulled from git commits... for now just going to leave some notes manually!
|
|
4
|
+
|
|
5
|
+
### 3.2.0 (2021-11-07)
|
|
6
|
+
|
|
7
|
+
- Added `insertDimension` functionality
|
|
8
|
+
- Added custom header row index for row-based API
|
|
9
|
+
- Bumped dependency versions
|
|
10
|
+
- Readme/docs cleanup
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
[](https://snyk.io/test/github/theoephraim/node-google-spreadsheet?targetFile=package.json)
|
|
7
7
|
[](https://www.npmtrends.com/google-spreadsheet)
|
|
8
8
|
|
|
9
|
-
- multiple auth options -
|
|
9
|
+
- multiple auth options - service account (w/ optional impersonation), OAuth 2.0, API key (read-only)
|
|
10
10
|
- cell-based API - read, write, bulk-updates, formatting
|
|
11
11
|
- row-based API - read, update, delete (based on the old v3 row-based calls)
|
|
12
12
|
- managing worksheets - add, remove, resize, change title, formatting
|
|
@@ -16,7 +16,7 @@ Full docs available at [https://theoephraim.github.io/node-google-spreadsheet](h
|
|
|
16
16
|
|
|
17
17
|
> **🚨 Google Deprecation Warning - affects older version (v2) of this module 🚨**
|
|
18
18
|
>
|
|
19
|
-
> Google is [phasing out their old v3 api](https://cloud.google.com/blog/products/g-suite/migrate-your-apps-use-latest-sheets-api), which the older version of this module used
|
|
19
|
+
> Google is [phasing out their old v3 api](https://cloud.google.com/blog/products/g-suite/migrate-your-apps-use-latest-sheets-api), which the older version of this module used. Originally they were going to shut it down on March 3rd 2020, but have pushed that date back to June 2021.
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
**Regardless, please upgrade to the latest version of this module (v3) which uses the newer sheets v4 API**
|
|
@@ -28,7 +28,7 @@ Full docs available at [https://theoephraim.github.io/node-google-spreadsheet](h
|
|
|
28
28
|
## Examples
|
|
29
29
|
_the following examples are meant to give you an idea of just some of the things you can do_
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
> **IMPORTANT NOTE** - To keep the examples concise, I'm calling await [at the top level](https://v8.dev/features/top-level-await) which is not allowed by default in most versions of node. If you need to call await in a script at the root level, you must instead wrap it in an async function like so:
|
|
32
32
|
|
|
33
33
|
```javascript
|
|
34
34
|
(async function() {
|
|
@@ -41,20 +41,16 @@ _the following examples are meant to give you an idea of just some of the things
|
|
|
41
41
|
```javascript
|
|
42
42
|
const { GoogleSpreadsheet } = require('google-spreadsheet');
|
|
43
43
|
|
|
44
|
-
//
|
|
44
|
+
// Initialize the sheet - doc ID is the long id in the sheets URL
|
|
45
45
|
const doc = new GoogleSpreadsheet('<the sheet ID from the url>');
|
|
46
46
|
|
|
47
|
-
//
|
|
47
|
+
// Initialize Auth - see https://theoephraim.github.io/node-google-spreadsheet/#/getting-started/authentication
|
|
48
48
|
await doc.useServiceAccountAuth({
|
|
49
|
+
// env var values are copied from service account credentials generated by google
|
|
50
|
+
// see "Authentication" section in docs for more info
|
|
49
51
|
client_email: process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL,
|
|
50
52
|
private_key: process.env.GOOGLE_PRIVATE_KEY,
|
|
51
53
|
});
|
|
52
|
-
// OR load directly from json file if not in secure environment
|
|
53
|
-
await doc.useServiceAccountAuth(require('./creds-from-google.json'));
|
|
54
|
-
// OR use service account to impersonate a user (see https://developers.google.com/identity/protocols/oauth2/service-account#delegatingauthority)
|
|
55
|
-
await doc.useServiceAccountAuth(require('./creds-from-google.json'), 'some-user@my-domain.com');
|
|
56
|
-
// OR use API key -- only for read-only access to public sheets
|
|
57
|
-
doc.useApiKey('YOUR-API-KEY');
|
|
58
54
|
|
|
59
55
|
await doc.loadInfo(); // loads document properties and worksheets
|
|
60
56
|
console.log(doc.title);
|
|
@@ -104,7 +100,7 @@ More info:
|
|
|
104
100
|
|
|
105
101
|
### Working with cells
|
|
106
102
|
```javascript
|
|
107
|
-
await sheet.loadCells('A1:E10'); // loads
|
|
103
|
+
await sheet.loadCells('A1:E10'); // loads range of cells into local cache - DOES NOT RETURN THE CELLS
|
|
108
104
|
console.log(sheet.cellStats); // total cells, loaded, how many non-empty
|
|
109
105
|
const a1 = sheet.getCell(0, 0); // access cells using a zero-based index
|
|
110
106
|
const c6 = sheet.getCellByA1('C6'); // or A1 style notation
|
|
@@ -150,7 +146,7 @@ None yet - get in touch!
|
|
|
150
146
|
|
|
151
147
|
Contributions are welcome, but please follow the existing conventions, use the linter, add relevant tests, add relevant documentation.
|
|
152
148
|
|
|
153
|
-
|
|
149
|
+
The docs site is generated using [docsify](https://docsify.js.org). To preview and run locally so you can make edits, run `npm run docs:preview` and head to http://localhost:3000
|
|
154
150
|
The content lives in markdown files in the docs folder.
|
|
155
151
|
|
|
156
152
|
## License
|
package/TODO
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
- support more cell functionality
|
|
2
|
+
- data validation rules - https://github.com/theoephraim/node-google-spreadsheet/issues/487
|
|
3
|
+
|
|
4
|
+
- dont explode if sheet contains charts - https://github.com/theoephraim/node-google-spreadsheet/issues/444
|
|
5
|
+
- add row.toJSON()
|
|
6
|
+
https://github.com/theoephraim/node-google-spreadsheet/issues/247
|
|
7
|
+
- google auth - Application Default Creds
|
|
8
|
+
https://github.com/theoephraim/node-google-spreadsheet/issues/215
|
|
9
|
+
https://github.com/theoephraim/node-google-spreadsheet/issues/345
|
|
10
|
+
|
|
11
|
+
- escape issues for strings starting with = `'=not a formula`
|
|
12
|
+
https://github.com/theoephraim/node-google-spreadsheet/issues/323
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
- browser/react native, older ES support
|
|
17
|
+
https://github.com/theoephraim/node-google-spreadsheet/issues/339
|
|
18
|
+
https://github.com/theoephraim/node-google-spreadsheet/issues/382
|
|
19
|
+
https://github.com/theoephraim/node-google-spreadsheet/issues/406
|
|
20
|
+
https://github.com/theoephraim/node-google-spreadsheet/issues/404
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
- nice tips here - https://github.com/mikro-orm/mikro-orm/issues/12
|
|
24
|
+
- start using semantic release? or similar https://semantic-release.gitbook.io/semantic-release/
|
|
25
|
+
- better commit messages to autogenerate changelog
|
|
26
|
+
- commitizen - https://github.com/commitizen/cz-cli
|
|
27
|
+
- https://gist.github.com/brianclements/841ea7bffdb01346392c
|
|
28
|
+
- commitlint checks - https://github.com/conventional-changelog/commitlint
|
|
29
|
+
- https://github.com/conventional-changelog/conventional-changelog
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
BUGS
|
|
36
|
+
- fetching single row via GRO has issues
|
|
37
|
+
https://github.com/theoephraim/node-google-spreadsheet/issues/347
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
MISSING FUNCTIONS
|
|
41
|
+
|
|
42
|
+
- support batchGet
|
|
43
|
+
https://github.com/theoephraim/node-google-spreadsheet/issues/326
|
|
44
|
+
|
|
45
|
+
- update filters
|
|
46
|
+
https://github.com/theoephraim/node-google-spreadsheet/issues/328
|
|
47
|
+
- insertDimension
|
|
48
|
+
https://github.com/theoephraim/node-google-spreadsheet/issues/366
|
|
49
|
+
- conditional formatting
|
|
50
|
+
https://github.com/theoephraim/node-google-spreadsheet/issues/410
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
OTHER
|
|
54
|
+
- row to cell interface
|
|
55
|
+
https://github.com/theoephraim/node-google-spreadsheet/issues/343
|
|
56
|
+
- reading from draftValue
|
|
57
|
+
https://github.com/theoephraim/node-google-spreadsheet/issues/350
|
|
58
|
+
https://github.com/theoephraim/node-google-spreadsheet/issues/402
|
|
59
|
+
- heroku config docs
|
|
60
|
+
https://github.com/theoephraim/node-google-spreadsheet/issues/354
|
|
61
|
+
- document metadata from drive api
|
|
62
|
+
https://github.com/theoephraim/node-google-spreadsheet/issues/364
|
|
63
|
+
- date formatting, escaping issues
|
|
64
|
+
https://github.com/theoephraim/node-google-spreadsheet/issues/367
|
|
65
|
+
https://github.com/theoephraim/node-google-spreadsheet/issues/363
|
|
66
|
+
- release notes
|
|
67
|
+
https://github.com/theoephraim/node-google-spreadsheet/issues/384
|
|
68
|
+
- delete rows from google forms
|
|
69
|
+
https://github.com/theoephraim/node-google-spreadsheet/issues/393
|
|
70
|
+
- better handling of merged cells
|
|
71
|
+
https://github.com/theoephraim/node-google-spreadsheet/issues/400
|
|
72
|
+
- specify header row
|
|
73
|
+
https://github.com/theoephraim/node-google-spreadsheet/issues/407
|
package/lib/GoogleSpreadsheet.js
CHANGED
|
@@ -20,6 +20,7 @@ const AUTH_MODES = {
|
|
|
20
20
|
JWT: 'JWT',
|
|
21
21
|
API_KEY: 'API_KEY',
|
|
22
22
|
RAW_ACCESS_TOKEN: 'RAW_ACCESS_TOKEN',
|
|
23
|
+
OAUTH: 'OAUTH',
|
|
23
24
|
};
|
|
24
25
|
|
|
25
26
|
class GoogleSpreadsheet {
|
|
@@ -28,6 +29,7 @@ class GoogleSpreadsheet {
|
|
|
28
29
|
this.authMode = null;
|
|
29
30
|
this._rawSheets = {};
|
|
30
31
|
this._rawProperties = null;
|
|
32
|
+
this._spreadsheetUrl = null;
|
|
31
33
|
|
|
32
34
|
// create an axios instance with sheet root URL and interceptors to handle auth
|
|
33
35
|
this.axios = Axios.create({
|
|
@@ -88,6 +90,11 @@ class GoogleSpreadsheet {
|
|
|
88
90
|
this.accessToken = token;
|
|
89
91
|
}
|
|
90
92
|
|
|
93
|
+
async useOAuth2Client(oAuth2Client) {
|
|
94
|
+
this.authMode = AUTH_MODES.OAUTH;
|
|
95
|
+
this.oAuth2Client = oAuth2Client;
|
|
96
|
+
}
|
|
97
|
+
|
|
91
98
|
// creds should be an object obtained by loading the json file google gives you
|
|
92
99
|
// impersonateAs is an email of any user in the G Suite domain
|
|
93
100
|
// (only works if service account has domain-wide delegation enabled)
|
|
@@ -133,6 +140,9 @@ class GoogleSpreadsheet {
|
|
|
133
140
|
if (!this.apiKey) throw new Error('Please set API key');
|
|
134
141
|
config.params = config.params || {};
|
|
135
142
|
config.params.key = this.apiKey;
|
|
143
|
+
} else if (this.authMode === AUTH_MODES.OAUTH) {
|
|
144
|
+
const credentials = await this.oAuth2Client.getAccessToken();
|
|
145
|
+
config.headers.Authorization = `Bearer ${credentials.token}`;
|
|
136
146
|
} else {
|
|
137
147
|
throw new Error('You must initialize some kind of auth before making any requests');
|
|
138
148
|
}
|
|
@@ -254,6 +264,7 @@ class GoogleSpreadsheet {
|
|
|
254
264
|
...includeCells && { includeGridData: true },
|
|
255
265
|
},
|
|
256
266
|
});
|
|
267
|
+
this._spreadsheetUrl = response.data.spreadsheetUrl;
|
|
257
268
|
this._rawProperties = response.data.properties;
|
|
258
269
|
_.each(response.data.sheets, (s) => this._updateOrCreateSheet(s));
|
|
259
270
|
}
|
|
@@ -290,15 +301,16 @@ class GoogleSpreadsheet {
|
|
|
290
301
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#AddSheetRequest
|
|
291
302
|
|
|
292
303
|
const response = await this._makeSingleUpdateRequest('addSheet', {
|
|
293
|
-
properties: _.omit(properties, 'headers', 'headerValues'),
|
|
304
|
+
properties: _.omit(properties, 'headers', 'headerValues', 'headerRowIndex'),
|
|
294
305
|
});
|
|
295
306
|
// _makeSingleUpdateRequest already adds the sheet
|
|
296
307
|
const newSheetId = response.properties.sheetId;
|
|
297
308
|
const newSheet = this.sheetsById[newSheetId];
|
|
298
309
|
|
|
299
310
|
// allow it to work with `.headers` but `.headerValues` is the real prop
|
|
300
|
-
|
|
301
|
-
|
|
311
|
+
const headers = properties.headerValues || properties.headers;
|
|
312
|
+
if (headers) {
|
|
313
|
+
await newSheet.setHeaderRow(headers, properties.headerRowIndex);
|
|
302
314
|
}
|
|
303
315
|
|
|
304
316
|
return newSheet;
|
|
@@ -372,6 +384,43 @@ class GoogleSpreadsheet {
|
|
|
372
384
|
const { sheets } = result.data;
|
|
373
385
|
_.each(sheets, (sheet) => { this._updateOrCreateSheet(sheet); });
|
|
374
386
|
}
|
|
387
|
+
|
|
388
|
+
// EXPORTING /////////////////////////////////////////////////////////////
|
|
389
|
+
async _downloadAs(fileType, worksheetId, returnStreamInsteadOfBuffer) {
|
|
390
|
+
// see https://stackoverflow.com/questions/11619805/using-the-google-drive-api-to-download-a-spreadsheet-in-csv-format/51235960#51235960
|
|
391
|
+
|
|
392
|
+
if (['html', 'xlsx', 'ods'].includes(fileType)) {
|
|
393
|
+
if (worksheetId) throw new Error(`Cannot specify worksheetId when exporting as ${fileType}`);
|
|
394
|
+
} else if (['csv', 'tsv', 'pdf'].includes(fileType)) {
|
|
395
|
+
if (worksheetId === undefined) throw new Error(`Must specify worksheetId when exporting as ${fileType}`);
|
|
396
|
+
} else {
|
|
397
|
+
throw new Error(`unsupported export fileType - ${fileType}`);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// google UI shows "html" but passes through "zip"
|
|
401
|
+
if (fileType === 'html') fileType = 'zip';
|
|
402
|
+
|
|
403
|
+
const exportUrl = this._spreadsheetUrl.replace('/edit', '/export');
|
|
404
|
+
const response = await this.axios.get(exportUrl, {
|
|
405
|
+
baseUrl: '', // unset baseUrl since we're not hitting the normal sheets API
|
|
406
|
+
params: {
|
|
407
|
+
id: this.spreadsheetId,
|
|
408
|
+
format: fileType,
|
|
409
|
+
...worksheetId && { gid: worksheetId },
|
|
410
|
+
},
|
|
411
|
+
responseType: returnStreamInsteadOfBuffer ? 'stream' : 'arraybuffer',
|
|
412
|
+
});
|
|
413
|
+
return response.data;
|
|
414
|
+
}
|
|
415
|
+
async downloadAsHTML(returnStreamInsteadOfBuffer = false) {
|
|
416
|
+
return this._downloadAs('html', null, returnStreamInsteadOfBuffer);
|
|
417
|
+
}
|
|
418
|
+
async downloadAsXLSX(returnStreamInsteadOfBuffer = false) {
|
|
419
|
+
return this._downloadAs('xlsx', null, returnStreamInsteadOfBuffer);
|
|
420
|
+
}
|
|
421
|
+
async downloadAsODS(returnStreamInsteadOfBuffer = false) {
|
|
422
|
+
return this._downloadAs('ods', null, returnStreamInsteadOfBuffer);
|
|
423
|
+
}
|
|
375
424
|
}
|
|
376
425
|
|
|
377
426
|
module.exports = GoogleSpreadsheet;
|
|
@@ -20,6 +20,8 @@ class GoogleSpreadsheetWorksheet {
|
|
|
20
20
|
constructor(parentSpreadsheet, { properties, data }) {
|
|
21
21
|
this._spreadsheet = parentSpreadsheet; // the parent GoogleSpreadsheet instance
|
|
22
22
|
|
|
23
|
+
this._headerRowIndex = 1; // assume "header row" (for row-based calls) is in first row
|
|
24
|
+
|
|
23
25
|
// basic properties
|
|
24
26
|
this._rawProperties = properties;
|
|
25
27
|
|
|
@@ -51,6 +53,7 @@ class GoogleSpreadsheetWorksheet {
|
|
|
51
53
|
resetLocalCache(dataOnly) {
|
|
52
54
|
if (!dataOnly) this._rawProperties = null;
|
|
53
55
|
this.headerValues = null;
|
|
56
|
+
this._headerRowIndex = 1;
|
|
54
57
|
this._cells = [];
|
|
55
58
|
}
|
|
56
59
|
|
|
@@ -174,7 +177,6 @@ class GoogleSpreadsheetWorksheet {
|
|
|
174
177
|
return this._cells[rowIndex][columnIndex];
|
|
175
178
|
}
|
|
176
179
|
|
|
177
|
-
|
|
178
180
|
async loadCells(sheetFilters) {
|
|
179
181
|
// load the whole sheet
|
|
180
182
|
if (!sheetFilters) return this._spreadsheet.loadCells(this.a1SheetName);
|
|
@@ -283,11 +285,11 @@ class GoogleSpreadsheetWorksheet {
|
|
|
283
285
|
// });
|
|
284
286
|
// }
|
|
285
287
|
|
|
286
|
-
|
|
287
288
|
// ROW BASED FUNCTIONS ///////////////////////////////////////////////////////////////////////////
|
|
288
289
|
|
|
289
|
-
async loadHeaderRow() {
|
|
290
|
-
|
|
290
|
+
async loadHeaderRow(headerRowIndex) {
|
|
291
|
+
if (headerRowIndex !== undefined) this._headerRowIndex = headerRowIndex;
|
|
292
|
+
const rows = await this.getCellsInRange(`A${this._headerRowIndex}:${this.lastColumnLetter}${this._headerRowIndex}`);
|
|
291
293
|
if (!rows) {
|
|
292
294
|
throw new Error('No values in the header row - fill the first row with header values before trying to interact with rows');
|
|
293
295
|
}
|
|
@@ -298,7 +300,7 @@ class GoogleSpreadsheetWorksheet {
|
|
|
298
300
|
checkForDuplicateHeaders(this.headerValues);
|
|
299
301
|
}
|
|
300
302
|
|
|
301
|
-
async setHeaderRow(headerValues) {
|
|
303
|
+
async setHeaderRow(headerValues, headerRowIndex) {
|
|
302
304
|
if (!headerValues) return;
|
|
303
305
|
if (headerValues.length > this.columnCount) {
|
|
304
306
|
throw new Error(`Sheet is not large enough to fit ${headerValues.length} columns. Resize the sheet first.`);
|
|
@@ -310,15 +312,17 @@ class GoogleSpreadsheetWorksheet {
|
|
|
310
312
|
throw new Error('All your header cells are blank -');
|
|
311
313
|
}
|
|
312
314
|
|
|
315
|
+
if (headerRowIndex) this._headerRowIndex = headerRowIndex;
|
|
316
|
+
|
|
313
317
|
const response = await this._spreadsheet.axios.request({
|
|
314
318
|
method: 'put',
|
|
315
|
-
url: `/values/${this.encodedA1SheetName}
|
|
319
|
+
url: `/values/${this.encodedA1SheetName}!${this._headerRowIndex}:${this._headerRowIndex}`,
|
|
316
320
|
params: {
|
|
317
321
|
valueInputOption: 'USER_ENTERED', // other option is RAW
|
|
318
322
|
includeValuesInResponse: true,
|
|
319
323
|
},
|
|
320
324
|
data: {
|
|
321
|
-
range: `${this.a1SheetName}
|
|
325
|
+
range: `${this.a1SheetName}!${this._headerRowIndex}:${this._headerRowIndex}`,
|
|
322
326
|
majorDimension: 'ROWS',
|
|
323
327
|
values: [[
|
|
324
328
|
...trimmedHeaderValues,
|
|
@@ -369,7 +373,7 @@ class GoogleSpreadsheetWorksheet {
|
|
|
369
373
|
|
|
370
374
|
const response = await this._spreadsheet.axios.request({
|
|
371
375
|
method: 'post',
|
|
372
|
-
url: `/values/${this.encodedA1SheetName}!
|
|
376
|
+
url: `/values/${this.encodedA1SheetName}!A${this._headerRowIndex}:append`,
|
|
373
377
|
params: {
|
|
374
378
|
valueInputOption: options.raw ? 'RAW' : 'USER_ENTERED',
|
|
375
379
|
insertDataOption: options.insert ? 'INSERT_ROWS' : 'OVERWRITE',
|
|
@@ -423,7 +427,7 @@ class GoogleSpreadsheetWorksheet {
|
|
|
423
427
|
|
|
424
428
|
if (!this.headerValues) await this.loadHeaderRow();
|
|
425
429
|
|
|
426
|
-
const firstRow =
|
|
430
|
+
const firstRow = 1 + this._headerRowIndex + options.offset;
|
|
427
431
|
const lastRow = firstRow + options.limit - 1; // inclusive so we subtract 1
|
|
428
432
|
const lastColumn = columnToLetter(this.headerValues.length);
|
|
429
433
|
const rawRows = await this.getCellsInRange(
|
|
@@ -440,6 +444,13 @@ class GoogleSpreadsheetWorksheet {
|
|
|
440
444
|
return rows;
|
|
441
445
|
}
|
|
442
446
|
|
|
447
|
+
async clearRows(options = {}) {
|
|
448
|
+
// default to first row after header
|
|
449
|
+
const startRowIndex = options.start || this._headerRowIndex + 1;
|
|
450
|
+
const endRowIndex = options.end || this.rowCount;
|
|
451
|
+
await this._spreadsheet.axios.post(`/values/${this.encodedA1SheetName}!${startRowIndex}:${endRowIndex}:clear`);
|
|
452
|
+
}
|
|
453
|
+
|
|
443
454
|
// BASIC PROPS ///////////////////////////////////////////////////////////////////////////////////
|
|
444
455
|
async updateProperties(properties) {
|
|
445
456
|
// Request type = `updateSheetProperties`
|
|
@@ -622,9 +633,17 @@ class GoogleSpreadsheetWorksheet {
|
|
|
622
633
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DuplicateFilterViewRequest
|
|
623
634
|
}
|
|
624
635
|
|
|
625
|
-
async
|
|
636
|
+
async duplicate(options = {}) {
|
|
626
637
|
// Request type = `duplicateSheet`
|
|
627
638
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DuplicateSheetRequest
|
|
639
|
+
const response = await this._makeSingleUpdateRequest('duplicateSheet', {
|
|
640
|
+
sourceSheetId: this.sheetId,
|
|
641
|
+
...options.index !== undefined && { insertSheetIndex: options.index },
|
|
642
|
+
...options.id && { newSheetId: options.id },
|
|
643
|
+
...options.title && { newSheetName: options.title },
|
|
644
|
+
});
|
|
645
|
+
const newSheetId = response.properties.sheetId;
|
|
646
|
+
return this._spreadsheet.sheetsById[newSheetId];
|
|
628
647
|
}
|
|
629
648
|
|
|
630
649
|
async findReplace() {
|
|
@@ -632,9 +651,35 @@ class GoogleSpreadsheetWorksheet {
|
|
|
632
651
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#FindReplaceRequest
|
|
633
652
|
}
|
|
634
653
|
|
|
635
|
-
async insertDimension() {
|
|
654
|
+
async insertDimension(columnsOrRows, range, inheritFromBefore = null) {
|
|
636
655
|
// Request type = `insertDimension`
|
|
637
656
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#InsertDimensionRequest
|
|
657
|
+
|
|
658
|
+
if (!columnsOrRows) throw new Error('You need to specify a dimension. i.e. COLUMNS|ROWS');
|
|
659
|
+
if (!_.isObject(range)) throw new Error('`range` must be an object containing `startIndex` and `endIndex`');
|
|
660
|
+
if (!_.isInteger(range.startIndex) || range.startIndex < 0) throw new Error('range.startIndex must be an integer >=0');
|
|
661
|
+
if (!_.isInteger(range.endIndex) || range.endIndex < 0) throw new Error('range.endIndex must be an integer >=0');
|
|
662
|
+
if (range.endIndex <= range.startIndex) throw new Error('range.endIndex must be greater than range.startIndex');
|
|
663
|
+
|
|
664
|
+
// default inheritFromBefore to true - unless inserting in the first row/column
|
|
665
|
+
if (inheritFromBefore === null) {
|
|
666
|
+
inheritFromBefore = range.startIndex > 0;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
// do not allow inheritFromBefore if inserting at first row/column
|
|
670
|
+
if (inheritFromBefore && range.startIndex === 0) {
|
|
671
|
+
throw new Error('Cannot set inheritFromBefore to true if inserting in first row/column');
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
return this._makeSingleUpdateRequest('insertDimension', {
|
|
675
|
+
range: {
|
|
676
|
+
sheetId: this.sheetId,
|
|
677
|
+
dimension: columnsOrRows,
|
|
678
|
+
startIndex: range.startIndex,
|
|
679
|
+
endIndex: range.endIndex,
|
|
680
|
+
},
|
|
681
|
+
inheritFromBefore,
|
|
682
|
+
});
|
|
638
683
|
}
|
|
639
684
|
|
|
640
685
|
async insertRange() {
|
|
@@ -820,12 +865,22 @@ class GoogleSpreadsheetWorksheet {
|
|
|
820
865
|
});
|
|
821
866
|
}
|
|
822
867
|
|
|
823
|
-
async clear() {
|
|
824
|
-
// clears
|
|
868
|
+
async clear(a1Range) {
|
|
869
|
+
// clears data in the sheet - defaults to entire sheet
|
|
870
|
+
const range = a1Range ? `!${a1Range}` : '';
|
|
825
871
|
// sheet name without ie 'sheet1' rather than 'sheet1'!A1:B5 is all cells
|
|
826
|
-
await this._spreadsheet.axios.post(`/values/${this.encodedA1SheetName}:clear`);
|
|
872
|
+
await this._spreadsheet.axios.post(`/values/${this.encodedA1SheetName}${range}:clear`);
|
|
827
873
|
this.resetLocalCache(true);
|
|
828
874
|
}
|
|
875
|
+
async downloadAsCSV(returnStreamInsteadOfBuffer = false) {
|
|
876
|
+
return this._spreadsheet._downloadAs('csv', this.sheetId, returnStreamInsteadOfBuffer);
|
|
877
|
+
}
|
|
878
|
+
async downloadAsTSV(returnStreamInsteadOfBuffer = false) {
|
|
879
|
+
return this._spreadsheet._downloadAs('tsv', this.sheetId, returnStreamInsteadOfBuffer);
|
|
880
|
+
}
|
|
881
|
+
async downloadAsPDF(returnStreamInsteadOfBuffer = false) {
|
|
882
|
+
return this._spreadsheet._downloadAs('pdf', this.sheetId, returnStreamInsteadOfBuffer);
|
|
883
|
+
}
|
|
829
884
|
}
|
|
830
885
|
|
|
831
886
|
module.exports = GoogleSpreadsheetWorksheet;
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"author": "Theo Ephraim <theozero@gmail.com> (https://theoephraim.com)",
|
|
3
3
|
"name": "google-spreadsheet",
|
|
4
4
|
"description": "Google Sheets API (v4) -- simple interface to read/write data and manage sheets",
|
|
5
|
-
"version": "3.0
|
|
5
|
+
"version": "3.3.0",
|
|
6
6
|
"license": "Unlicense",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"google spreadsheets",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"api",
|
|
17
17
|
"googleapis"
|
|
18
18
|
],
|
|
19
|
-
"homepage": "https://github.
|
|
19
|
+
"homepage": "https://theoephraim.github.io/node-google-spreadsheet",
|
|
20
20
|
"repository": {
|
|
21
21
|
"type": "git",
|
|
22
22
|
"url": "git://github.com/theoephraim/node-google-spreadsheet.git"
|
|
@@ -26,13 +26,13 @@
|
|
|
26
26
|
"node": ">=0.8.0"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"axios": "^0.
|
|
29
|
+
"axios": "^0.21.4",
|
|
30
30
|
"google-auth-library": "^6.1.3",
|
|
31
|
-
"lodash": "^4.17.
|
|
31
|
+
"lodash": "^4.17.21"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"delay": "^4.3.0",
|
|
35
|
-
"docsify-cli": "^4.4.
|
|
35
|
+
"docsify-cli": "^4.4.3",
|
|
36
36
|
"eslint": "^6.8.0",
|
|
37
37
|
"eslint-config-airbnb-base": "^14.0.0",
|
|
38
38
|
"eslint-plugin-async-await": "0.0.0",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"lint": "eslint ./",
|
|
48
48
|
"lint:fix": "eslint ./ --fix",
|
|
49
49
|
"docs:preview": "docsify serve docs",
|
|
50
|
-
"readme:copy": "echo \"<!-- DO NOT EDIT THIS FILE, EDIT MAIN README.md AND RUN \\`npm readme:copy\\` instead -->\n\n\" | cat - README.md > docs/README.md"
|
|
50
|
+
"readme:copy": "echo \"<!-- DO NOT EDIT THIS FILE, EDIT MAIN README.md AND RUN \\`npm readme:copy\\` instead -->\n\n_Welcome to the docs site for_\n\" | cat - README.md > docs/README.md"
|
|
51
51
|
},
|
|
52
52
|
"husky": {
|
|
53
53
|
"hooks": {
|