Skip to content

Commit

Permalink
add options when inserting/saving rows for RAW and INSERT modes
Browse files Browse the repository at this point in the history
  • Loading branch information
theoephraim committed Feb 27, 2020
1 parent 0bdf5b2 commit a6baa65
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 19 deletions.
9 changes: 7 additions & 2 deletions docs/classes/google-spreadsheet-row.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,14 @@ await row.save(); // cell will now contain the value "ASDF", not the formula

## Methods

#### `save()` (async) :id=fn-save
#### `save(options)` (async) :id=fn-save
> Save any updates made to row values
Param|Type|Required|Description
---|---|---|---
`options`|Object|-|Options object
`options.raw`|Boolean|-|Store raw values instead of converting as if typed into the sheets UI<br>_see [ValueInputOption](https://developers.google.com/sheets/api/reference/rest/v4/ValueInputOption)_

-**Side effects** - updates are saved and everything re-fetched from google


Expand All @@ -87,5 +92,5 @@ await row.save(); // cell will now contain the value "ASDF", not the formula
-**Side effects** - Row is removed from the sheet

_also available as `_row.del()`_
_also available as `row.del()`_

10 changes: 7 additions & 3 deletions docs/classes/google-spreadsheet-worksheet.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,26 +77,30 @@ Param|Type|Required|Description

-**Side effects** - first row of the sheet is filled, `sheet.headerValues` is populated

#### `addRow(rowValues)` (async) :id=fn-addRow
#### `addRow(rowValues, options)` (async) :id=fn-addRow
> Append a new row to the sheet
Param|Type|Required|Description
---|---|---|---
`rowValues`<br>_option 1_|Object|✅|Object of cell values, keys are based on the header row<br>_ex: `{ col1: 'val1', col2: 'val2', ... }`_
`rowValues`<br>_option 2_|Array|✅|Array of cell values in order from first column onwards<br>_ex: `['val1', 'val2', ...]`_

`options`|Object|-|Options object
`options.raw`|Boolean|-|Store raw values instead of converting as if typed into the sheets UI<br>_see [ValueInputOption](https://developers.google.com/sheets/api/reference/rest/v4/ValueInputOption)_
`options.insert`|Boolean|-|Insert new rows instead of overwriting empty rows and only adding if necessary<br>_see [InsertDataOption](https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/append#InsertDataOption)_


- ↩️ **Returns** - [GoogleSpreadsheetRow](classes/google-spreadsheet-row) (in a promise)
-**Side effects** - row is added to the sheet


#### `addRows(arrayOfRowValues)` (async) :id=fn-addRows
#### `addRows(arrayOfRowValues, options)` (async) :id=fn-addRows
> Append multiple new rows to the sheet at once
Param|Type|Required|Description
---|---|---|---
`arrayOfRowValues`|Array|✅|Array of rows values to append to the sheet<br>_see [`sheet.addRow()`](#fn-addRow) above for more info_
`options`|Object|-|Inserting options<br>_see [`sheet.addRow()`](#fn-addRow) above for more info_


- ↩️ **Returns** - [[GoogleSpreadsheetRow](classes/google-spreadsheet-row)] (in a promise)
-**Side effects** - rows are added to the sheet
Expand Down
4 changes: 2 additions & 2 deletions lib/GoogleSpreadsheetRow.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ class GoogleSpreadsheetRow {
].join('');
}

async save() {
async save(options = {}) {
if (this._deleted) throw new Error('This row has been deleted - call getRows again before making updates.');

const response = await this._sheet._spreadsheet.axios.request({
method: 'put',
url: `/values/${encodeURIComponent(this.a1Range)}`,
params: {
valueInputOption: 'USER_ENTERED', // other option is RAW
valueInputOption: options.raw ? 'RAW' : 'USER_ENTERED',
includeValuesInResponse: true,
},
data: {
Expand Down
17 changes: 12 additions & 5 deletions lib/GoogleSpreadsheetWorksheet.js
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ class GoogleSpreadsheetWorksheet {
this.headerValues = response.data.updatedData.values[0];
}

async addRows(rows) {
async addRows(rows, options = {}) {
// adds multiple rows in one API interaction using the append endpoint

// each row can be an array or object
Expand Down Expand Up @@ -364,8 +364,8 @@ class GoogleSpreadsheetWorksheet {
method: 'post',
url: `/values/${encodeURIComponent(this.a1SheetName)}:append`,
params: {
valueInputOption: 'USER_ENTERED', // RAW
insertDataOption: 'OVERWRITE', // INSERT_ROWS
valueInputOption: options.raw ? 'RAW' : 'USER_ENTERED',
insertDataOption: options.insert ? 'INSERT_ROWS' : 'OVERWRITE',
includeValuesInResponse: true,
},
data: {
Expand All @@ -379,14 +379,21 @@ class GoogleSpreadsheetWorksheet {
let rowNumber = updatedRange.match(/![A-Z]+([0-9]+):?/)[1];
rowNumber = parseInt(rowNumber);

// if new rows were added, we need update sheet.rowRount
if (options.insert) {
this._rawProperties.gridProperties.rowCount += rows.length;
} else if (rowNumber + rows.length > this.rowCount) {
this._rawProperties.gridProperties.rowCount = rowNumber + rows.length;
}

return _.map(response.data.updates.updatedData.values, (rowValues) => {
const row = new GoogleSpreadsheetRow(this, rowNumber++, rowValues);
return row;
});
}

async addRow(rowValues) {
const rows = await this.addRows([rowValues]);
async addRow(rowValues, options) {
const rows = await this.addRows([rowValues], options);
return rows[0];
}

Expand Down
42 changes: 35 additions & 7 deletions test/rows.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ let rows;
let row;

const HEADERS = ['numbers', 'letters', 'col1', 'col2', 'col3'];
const INITIAL_ROW_COUNT = 15;
const INITIAL_DATA = [
['0', 'A'],
['1', 'B'],
Expand All @@ -24,10 +25,9 @@ describe('Row-based operations', () => {
sheet = await doc.addSheet({
headers: HEADERS,
title: `Spécial CнArs - ${+new Date()}`, // some urls have sheet title in them
gridProperties: { rowCount: INITIAL_ROW_COUNT },
});
for (let i = 0; i < INITIAL_DATA.length; i++) {
await sheet.addRow(INITIAL_DATA[i]);
}
await sheet.addRows(INITIAL_DATA);
});
afterAll(async () => {
await sheet.delete();
Expand All @@ -37,7 +37,7 @@ describe('Row-based operations', () => {
it('can fetch multiple rows', async () => {
rows = await sheet.getRows();
row = rows[0];
expect(rows.length).toEqual(5);
expect(rows.length).toEqual(INITIAL_DATA.length);
});

it('a row has properties with keys from the headers', () => {
Expand Down Expand Up @@ -95,12 +95,40 @@ describe('Row-based operations', () => {
it('can add multiple rows', async () => {
const newRows = await sheet.addRows([
{ numbers: '7', letters: 'H' },
{ numbers: '8', letters: 'I' },
['9', 'J'],
['8', 'I'],
]);
expect(newRows[0].numbers).toEqual('7');
expect(newRows[1].numbers).toEqual('8');
expect(newRows[2].numbers).toEqual('9');
});

it('can add rows with options.insert', async () => {
// we should still have some empty rows left for this test to be valid
rows = await sheet.getRows();
expect(rows.length).toBeLessThan(INITIAL_ROW_COUNT);
const oldRowCount = sheet.rowCount;
await sheet.addRows([
{ numbers: '101', letters: 'XX' },
], { insert: true });
expect(sheet.rowCount).toEqual(oldRowCount + 1);
});

it('will update sheet.rowCount if new rows are added (while not in insert mode)', async () => {
const oldRowCount = sheet.rowCount;
const dataForMoreRowsThanFit = _.times(INITIAL_ROW_COUNT, () => ({
numbers: '999', letters: 'ZZZ',
}));
const newRows = await sheet.addRows(dataForMoreRowsThanFit);
expect(sheet.rowCount).toBeGreaterThan(oldRowCount);
expect(newRows[newRows.length - 1].rowIndex).toEqual(sheet.rowCount - 1);
});

it('can add rows with options.raw', async () => {
const rawValue = 'true';
const regularRow = await sheet.addRow({ col1: rawValue });
const rawRow = await sheet.addRow({ col1: rawValue }, { raw: true });

expect(regularRow.col1).toEqual('TRUE'); // internally its treating as a boolean
expect(rawRow.col1).toEqual(rawValue);
});
});

Expand Down

0 comments on commit a6baa65

Please sign in to comment.