You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

861 lines
31 KiB

const _ = require('lodash');
const GoogleSpreadsheetRow = require('./GoogleSpreadsheetRow');
const GoogleSpreadsheetCell = require('./GoogleSpreadsheetCell');
const { getFieldMask, columnToLetter, letterToColumn } = require('./utils');
function checkForDuplicateHeaders(headers) {
// check for duplicate headers
const checkForDupes = _.groupBy(headers); // { c1: ['c1'], c2: ['c2', 'c2' ]}
_.each(checkForDupes, (grouped, header) => {
if (!header) return; // empty columns are skipped, so multiple is ok
if (grouped.length > 1) {
throw new Error(`Duplicate header detected: "${header}". Please make sure all non-empty headers are unique`);
}
});
}
class GoogleSpreadsheetWorksheet {
constructor(parentSpreadsheet, { properties, data }) {
this._spreadsheet = parentSpreadsheet; // the parent GoogleSpreadsheet instance
this._headerRowIndex = 1; // assume "header row" (for row-based calls) is in first row
// basic properties
this._rawProperties = properties;
this._cells = []; // we will use a 2d sparse array to store cells;
this._rowMetadata = []; // 1d sparse array
this._columnMetadata = [];
if (data) this._fillCellData(data);
return this;
}
// INTERNAL UTILITY FUNCTIONS ////////////////////////////////////////////////////////////////////
async _makeSingleUpdateRequest(requestType, requestParams) {
// pass the call up to the parent
return this._spreadsheet._makeSingleUpdateRequest(requestType, {
// sheetId: this.sheetId,
...requestParams,
});
}
_ensureInfoLoaded() {
if (!this._rawProperties) {
throw new Error('You must call `doc.loadInfo()` again before accessing this property');
}
}
resetLocalCache(dataOnly) {
if (!dataOnly) this._rawProperties = null;
this.headerValues = null;
this._headerRowIndex = 1;
this._cells = [];
}
_fillCellData(dataRanges) {
_.each(dataRanges, (range) => {
const startRow = range.startRow || 0;
const startColumn = range.startColumn || 0;
const numRows = range.rowMetadata.length;
const numColumns = range.columnMetadata.length;
// update cell data for entire range
for (let i = 0; i < numRows; i++) {
const actualRow = startRow + i;
for (let j = 0; j < numColumns; j++) {
const actualColumn = startColumn + j;
// if the row has not been initialized yet, do it
if (!this._cells[actualRow]) this._cells[actualRow] = [];
// see if the response includes some info for the cell
const cellData = _.get(range, `rowData[${i}].values[${j}]`);
// update the cell object or create it
if (this._cells[actualRow][actualColumn]) {
this._cells[actualRow][actualColumn]._updateRawData(cellData);
} else {
this._cells[actualRow][actualColumn] = new GoogleSpreadsheetCell(
this,
actualRow,
actualColumn,
cellData
);
}
}
}
// update row metadata
for (let i = 0; i < range.rowMetadata.length; i++) {
this._rowMetadata[startRow + i] = range.rowMetadata[i];
}
// update column metadata
for (let i = 0; i < range.columnMetadata.length; i++) {
this._columnMetadata[startColumn + i] = range.columnMetadata[i];
}
});
}
// PROPERTY GETTERS //////////////////////////////////////////////////////////////////////////////
_getProp(param) {
this._ensureInfoLoaded();
return this._rawProperties[param];
}
_setProp(param, newVal) { // eslint-disable-line no-unused-vars
throw new Error('Do not update directly - use `updateProperties()`');
}
get sheetId() { return this._getProp('sheetId'); }
get title() { return this._getProp('title'); }
get index() { return this._getProp('index'); }
get sheetType() { return this._getProp('sheetType'); }
get gridProperties() { return this._getProp('gridProperties'); }
get hidden() { return this._getProp('hidden'); }
get tabColor() { return this._getProp('tabColor'); }
get rightToLeft() { return this._getProp('rightToLeft'); }
set sheetId(newVal) { return this._setProp('sheetId', newVal); }
set title(newVal) { return this._setProp('title', newVal); }
set index(newVal) { return this._setProp('index', newVal); }
set sheetType(newVal) { return this._setProp('sheetType', newVal); }
set gridProperties(newVal) { return this._setProp('gridProperties', newVal); }
set hidden(newVal) { return this._setProp('hidden', newVal); }
set tabColor(newVal) { return this._setProp('tabColor', newVal); }
set rightToLeft(newVal) { return this._setProp('rightToLeft', newVal); }
get rowCount() {
this._ensureInfoLoaded();
return this.gridProperties.rowCount;
}
get columnCount() {
this._ensureInfoLoaded();
return this.gridProperties.columnCount;
}
get colCount() { throw new Error('`colCount` is deprecated - please use `columnCount` instead.'); }
set rowCount(newVal) { throw new Error('Do not update directly. Use resize()'); }
set columnCount(newVal) { throw new Error('Do not update directly. Use resize()'); }
get a1SheetName() { return `'${this.title.replace(/'/g, "''")}'`; }
get encodedA1SheetName() { return encodeURIComponent(this.a1SheetName); }
get lastColumnLetter() { return columnToLetter(this.columnCount); }
// CELLS-BASED INTERACTIONS //////////////////////////////////////////////////////////////////////
get cellStats() {
let allCells = _.flatten(this._cells);
allCells = _.compact(allCells);
return {
nonEmpty: _.filter(allCells, (c) => c.value).length,
loaded: allCells.length,
total: this.rowCount * this.columnCount,
};
}
getCellByA1(a1Address) {
const split = a1Address.match(/([A-Z]+)([0-9]+)/);
const columnIndex = letterToColumn(split[1]);
const rowIndex = parseInt(split[2]);
return this.getCell(rowIndex - 1, columnIndex - 1);
}
getCell(rowIndex, columnIndex) {
if (rowIndex < 0 || columnIndex < 0) throw new Error('Min coordinate is 0, 0');
if (rowIndex >= this.rowCount || columnIndex >= this.columnCount) {
throw new Error(`Out of bounds, sheet is ${this.rowCount} by ${this.columnCount}`);
}
if (!_.get(this._cells, `[${rowIndex}][${columnIndex}]`)) {
throw new Error('This cell has not been loaded yet');
}
return this._cells[rowIndex][columnIndex];
}
async loadCells(sheetFilters) {
// load the whole sheet
if (!sheetFilters) return this._spreadsheet.loadCells(this.a1SheetName);
let filtersArray = _.isArray(sheetFilters) ? sheetFilters : [sheetFilters];
filtersArray = _.map(filtersArray, (filter) => {
// add sheet name to A1 ranges
if (_.isString(filter)) {
if (filter.startsWith(this.a1SheetName)) return filter;
return `${this.a1SheetName}!${filter}`;
}
if (_.isObject(filter)) {
// TODO: detect and support DeveloperMetadata filters
if (!filter.sheetId) {
return { sheetId: this.sheetId, ...filter };
}
if (filter.sheetId !== this.sheetId) {
throw new Error('Leave sheet ID blank or set to matching ID of this sheet');
} else {
return filter;
}
} else {
throw new Error('Each filter must be a A1 range string or gridrange object');
}
});
return this._spreadsheet.loadCells(filtersArray);
}
async saveUpdatedCells() {
const cellsToSave = _.filter(_.flatten(this._cells), { _isDirty: true });
if (cellsToSave.length) {
await this.saveCells(cellsToSave);
}
// TODO: do we want to return stats? or the cells that got updated?
}
async saveCells(cellsToUpdate) {
// we send an individual "updateCells" request for each cell
// because the fields that are udpated for each group are the same
// and we dont want to accidentally overwrite something
const requests = _.map(cellsToUpdate, (cell) => cell._getUpdateRequest());
const responseRanges = _.map(cellsToUpdate, (c) => `${this.a1SheetName}!${c.a1Address}`);
// if nothing is being updated the request returned is just `null`
// so we make sure at least 1 request is valid - otherwise google throws a 400
if (!_.compact(requests).length) {
throw new Error('At least one cell must have something to update');
}
await this._spreadsheet._makeBatchUpdateRequest(requests, responseRanges);
}
// SAVING THIS FOR FUTURE USE
// puts the cells that need updating into batches
// async updateCellsByBatches() {
// // saving this code, but it's problematic because each group must have the same update fields
// const cellsByRow = _.groupBy(cellsToUpdate, 'rowIndex');
// const groupsToSave = [];
// _.each(cellsByRow, (cells, rowIndex) => {
// let cellGroup = [];
// _.each(cells, (c) => {
// if (!cellGroup.length) {
// cellGroup.push(c);
// } else if (
// cellGroup[cellGroup.length - 1].columnIndex ===
// c.columnIndex - 1
// ) {
// cellGroup.push(c);
// } else {
// groupsToSave.push(cellGroup);
// cellGroup = [];
// }
// });
// groupsToSave.push(cellGroup);
// });
// const requests = _.map(groupsToSave, (cellGroup) => ({
// updateCells: {
// rows: [
// {
// values: _.map(cellGroup, (cell) => ({
// ...cell._draftData.value && {
// userEnteredValue: { [cell._draftData.valueType]: cell._draftData.value },
// },
// ...cell._draftData.note !== undefined && {
// note: cell._draftData.note ,
// },
// ...cell._draftData.userEnteredFormat && {
// userEnteredValue: cell._draftData.userEnteredFormat,
// },
// })),
// },
// ],
// fields: 'userEnteredValue,note,userEnteredFormat',
// start: {
// sheetId: this.sheetId,
// rowIndex: cellGroup[0].rowIndex,
// columnIndex: cellGroup[0].columnIndex,
// },
// },
// }));
// const responseRanges = _.map(groupsToSave, (cellGroup) => {
// let a1Range = cellGroup[0].a1Address;
// if (cellGroup.length > 1)
// a1Range += `:${cellGroup[cellGroup.length - 1].a1Address}`;
// return `${cellGroup[0]._sheet.a1SheetName}!${a1Range}`;
// });
// }
// ROW BASED FUNCTIONS ///////////////////////////////////////////////////////////////////////////
async loadHeaderRow(headerRowIndex) {
if (headerRowIndex !== undefined) this._headerRowIndex = headerRowIndex;
const rows = await this.getCellsInRange(`A${this._headerRowIndex}:${this.lastColumnLetter}${this._headerRowIndex}`);
if (!rows) {
throw new Error('No values in the header row - fill the first row with header values before trying to interact with rows');
}
this.headerValues = _.map(rows[0], (header) => header.trim());
if (!_.compact(this.headerValues).length) {
throw new Error('All your header cells are blank - fill the first row with header values before trying to interact with rows');
}
checkForDuplicateHeaders(this.headerValues);
}
async setHeaderRow(headerValues, headerRowIndex) {
if (!headerValues) return;
if (headerValues.length > this.columnCount) {
throw new Error(`Sheet is not large enough to fit ${headerValues.length} columns. Resize the sheet first.`);
}
const trimmedHeaderValues = _.map(headerValues, (h) => h.trim());
checkForDuplicateHeaders(trimmedHeaderValues);
if (!_.compact(trimmedHeaderValues).length) {
throw new Error('All your header cells are blank -');
}
if (headerRowIndex) this._headerRowIndex = headerRowIndex;
const response = await this._spreadsheet.axios.request({
method: 'put',
url: `/values/${this.encodedA1SheetName}!${this._headerRowIndex}:${this._headerRowIndex}`,
params: {
valueInputOption: 'USER_ENTERED', // other option is RAW
includeValuesInResponse: true,
},
data: {
range: `${this.a1SheetName}!${this._headerRowIndex}:${this._headerRowIndex}`,
majorDimension: 'ROWS',
values: [[
...trimmedHeaderValues,
// pad the rest of the row with empty values to clear them all out
..._.times(this.columnCount - trimmedHeaderValues.length, () => ''),
]],
},
});
this.headerValues = response.data.updatedData.values[0];
}
async addRows(rows, options = {}) {
// adds multiple rows in one API interaction using the append endpoint
// each row can be an array or object
// an array is just cells
// ex: ['column 1', 'column 2', 'column 3']
// an object must use the header row values as keys
// ex: { col1: 'column 1', col2: 'column 2', col3: 'column 3' }
// google bug that does not handle colons in names
// see https://issuetracker.google.com/issues/150373119
if (this.title.includes(':')) {
throw new Error('Please remove the ":" from your sheet title. There is a bug with the google API which breaks appending rows if any colons are in the sheet title.');
}
if (!_.isArray(rows)) throw new Error('You must pass in an array of row values to append');
if (!this.headerValues) await this.loadHeaderRow();
// convert each row into an array of cell values rather than the key/value object
const rowsAsArrays = [];
_.each(rows, (row) => {
let rowAsArray;
if (_.isArray(row)) {
rowAsArray = row;
} else if (_.isObject(row)) {
rowAsArray = [];
for (let i = 0; i < this.headerValues.length; i++) {
const propName = this.headerValues[i];
rowAsArray[i] = row[propName];
}
} else {
throw new Error('Each row must be an object or an array');
}
rowsAsArrays.push(rowAsArray);
});
const response = await this._spreadsheet.axios.request({
method: 'post',
url: `/values/${this.encodedA1SheetName}!A${this._headerRowIndex}:append`,
params: {
valueInputOption: options.raw ? 'RAW' : 'USER_ENTERED',
insertDataOption: options.insert ? 'INSERT_ROWS' : 'OVERWRITE',
includeValuesInResponse: true,
},
data: {
values: rowsAsArrays,
},
});
// extract the new row number from the A1-notation data range in the response
// ex: in "'Sheet8!A2:C2" -- we want the `2`
const { updatedRange } = response.data.updates;
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) {
// have to subtract 1 since one row was inserted at rowNumber
this._rawProperties.gridProperties.rowCount = rowNumber + rows.length - 1;
}
return _.map(response.data.updates.updatedData.values, (rowValues) => {
const row = new GoogleSpreadsheetRow(this, rowNumber++, rowValues);
return row;
});
}
async addRow(rowValues, options) {
const rows = await this.addRows([rowValues], options);
return rows[0];
}
async getRows(options = {}) {
// https://developers.google.com/sheets/api/guides/migration
// v4 API does not have equivalents for the row-order query parameters provided
// Reverse-order is trivial; simply process the returned values array in reverse order.
// Order by column is not supported for reads, but it is possible to sort the data then read
// v4 API does not currently have a direct equivalent for the Sheets API v3 structured queries
// However, you can retrieve the relevant data and sort through it as needed in your application
// options
// - offset
// - limit
options.offset = options.offset || 0;
options.limit = options.limit || this.rowCount - 1;
if (!this.headerValues) await this.loadHeaderRow();
const firstRow = 1 + this._headerRowIndex + options.offset;
const lastRow = firstRow + options.limit - 1; // inclusive so we subtract 1
const lastColumn = columnToLetter(this.headerValues.length);
const rawRows = await this.getCellsInRange(
`A${firstRow}:${lastColumn}${lastRow}`
);
if (!rawRows) return [];
const rows = [];
let rowNum = firstRow;
for (let i = 0; i < rawRows.length; i++) {
rows.push(new GoogleSpreadsheetRow(this, rowNum++, rawRows[i]));
}
return rows;
}
// BASIC PROPS ///////////////////////////////////////////////////////////////////////////////////
async updateProperties(properties) {
// Request type = `updateSheetProperties`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#UpdateSheetPropertiesRequest
// properties
// - title (string)
// - index (number)
// - gridProperties ({ object (GridProperties) } - https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/sheets#gridproperties
// - hidden (boolean)
// - tabColor ({ object (Color) } - https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/other#Color
// - rightToLeft (boolean)
return this._makeSingleUpdateRequest('updateSheetProperties', {
properties: {
sheetId: this.sheetId,
...properties,
},
fields: getFieldMask(properties),
});
}
async updateGridProperties(gridProperties) {
// just passes the call through to update gridProperties
// see https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/sheets#GridProperties
// gridProperties
// - rowCount
// - columnCount
// - frozenRowCount
// - frozenColumnCount
// - hideGridLines
return this.updateProperties({ gridProperties });
}
// just a shortcut because resize makes more sense to change rowCount / columnCount
async resize(gridProperties) {
return this.updateGridProperties(gridProperties);
}
async updateDimensionProperties(columnsOrRows, properties, bounds) {
// Request type = `updateDimensionProperties`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#updatedimensionpropertiesrequest
// columnsOrRows = COLUMNS|ROWS
// properties
// - pixelSize
// - hiddenByUser
// - developerMetadata
// bounds
// - startIndex
// - endIndex
return this._makeSingleUpdateRequest('updateDimensionProperties', {
range: {
sheetId: this.sheetId,
dimension: columnsOrRows,
...bounds && {
startIndex: bounds.startIndex,
endIndex: bounds.endIndex,
},
},
properties,
fields: getFieldMask(properties),
});
}
// OTHER /////////////////////////////////////////////////////////////////////////////////////////
// this uses the "values" getter and does not give all the info about the cell contents
// it is used internally when loading header cells
async getCellsInRange(a1Range, options) {
const response = await this._spreadsheet.axios.get(`/values/${this.encodedA1SheetName}!${a1Range}`, {
params: options,
});
return response.data.values;
}
async updateNamedRange() {
// Request type = `updateNamedRange`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#UpdateNamedRangeRequest
}
async addNamedRange() {
// Request type = `addNamedRange`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#AddNamedRangeRequest
}
async deleteNamedRange() {
// Request type = `deleteNamedRange`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DeleteNamedRangeRequest
}
async repeatCell() {
// Request type = `repeatCell`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#RepeatCellRequest
}
async autoFill() {
// Request type = `autoFill`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#AutoFillRequest
}
async cutPaste() {
// Request type = `cutPaste`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#CutPasteRequest
}
async copyPaste() {
// Request type = `copyPaste`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#CopyPasteRequest
}
async mergeCells(range, mergeType = 'MERGE_ALL') {
// Request type = `mergeCells`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#MergeCellsRequest
if (range.sheetId && range.sheetId !== this.sheetId) {
throw new Error('Leave sheet ID blank or set to matching ID of this sheet');
}
await this._makeSingleUpdateRequest('mergeCells', {
mergeType,
range: {
...range,
sheetId: this.sheetId,
},
});
}
async unmergeCells(range) {
// Request type = `unmergeCells`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#UnmergeCellsRequest
if (range.sheetId && range.sheetId !== this.sheetId) {
throw new Error('Leave sheet ID blank or set to matching ID of this sheet');
}
await this._makeSingleUpdateRequest('unmergeCells', {
range: {
...range,
sheetId: this.sheetId,
},
});
}
async updateBorders() {
// Request type = `updateBorders`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#UpdateBordersRequest
}
async addFilterView() {
// Request type = `addFilterView`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#AddFilterViewRequest
}
async appendCells() {
// Request type = `appendCells`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#AppendCellsRequest
}
async clearBasicFilter() {
// Request type = `clearBasicFilter`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#ClearBasicFilterRequest
}
async deleteDimension() {
// Request type = `deleteDimension`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DeleteDimensionRequest
}
async deleteEmbeddedObject() {
// Request type = `deleteEmbeddedObject`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DeleteEmbeddedObjectRequest
}
async deleteFilterView() {
// Request type = `deleteFilterView`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DeleteFilterViewRequest
}
async duplicateFilterView() {
// Request type = `duplicateFilterView`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DuplicateFilterViewRequest
}
async duplicateSheet() {
// Request type = `duplicateSheet`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DuplicateSheetRequest
}
async findReplace() {
// Request type = `findReplace`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#FindReplaceRequest
}
async insertDimension(columnsOrRows, range, inheritFromBefore = null) {
// Request type = `insertDimension`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#InsertDimensionRequest
if (!columnsOrRows) throw new Error('You need to specify a dimension. i.e. COLUMNS|ROWS');
if (!_.isObject(range)) throw new Error('`range` must be an object containing `startIndex` and `endIndex`');
if (!_.isInteger(range.startIndex) || range.startIndex < 0) throw new Error('range.startIndex must be an integer >=0');
if (!_.isInteger(range.endIndex) || range.endIndex < 0) throw new Error('range.endIndex must be an integer >=0');
if (range.endIndex <= range.startIndex) throw new Error('range.endIndex must be greater than range.startIndex');
// default inheritFromBefore to true - unless inserting in the first row/column
if (inheritFromBefore === null) {
inheritFromBefore = range.startIndex > 0;
}
// do not allow inheritFromBefore if inserting at first row/column
if (inheritFromBefore && range.startIndex === 0) {
throw new Error('Cannot set inheritFromBefore to true if inserting in first row/column');
}
return this._makeSingleUpdateRequest('insertDimension', {
range: {
sheetId: this.sheetId,
dimension: columnsOrRows,
startIndex: range.startIndex,
endIndex: range.endIndex,
},
inheritFromBefore,
});
}
async insertRange() {
// Request type = `insertRange`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#InsertRangeRequest
}
async moveDimension() {
// Request type = `moveDimension`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#MoveDimensionRequest
}
async updateEmbeddedObjectPosition() {
// Request type = `updateEmbeddedObjectPosition`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#UpdateEmbeddedObjectPositionRequest
}
async pasteData() {
// Request type = `pasteData`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#PasteDataRequest
}
async textToColumns() {
// Request type = `textToColumns`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#TextToColumnsRequest
}
async updateFilterView() {
// Request type = `updateFilterView`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#UpdateFilterViewRequest
}
async deleteRange() {
// Request type = `deleteRange`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DeleteRangeRequest
}
async appendDimension() {
// Request type = `appendDimension`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#AppendDimensionRequest
}
async addConditionalFormatRule() {
// Request type = `addConditionalFormatRule`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#AddConditionalFormatRuleRequest
}
async updateConditionalFormatRule() {
// Request type = `updateConditionalFormatRule`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#UpdateConditionalFormatRuleRequest
}
async deleteConditionalFormatRule() {
// Request type = `deleteConditionalFormatRule`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DeleteConditionalFormatRuleRequest
}
async sortRange() {
// Request type = `sortRange`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#SortRangeRequest
}
async setDataValidation() {
// Request type = `setDataValidation`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#SetDataValidationRequest
}
async setBasicFilter() {
// Request type = `setBasicFilter`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#SetBasicFilterRequest
}
async addProtectedRange() {
// Request type = `addProtectedRange`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#AddProtectedRangeRequest
}
async updateProtectedRange() {
// Request type = `updateProtectedRange`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#UpdateProtectedRangeRequest
}
async deleteProtectedRange() {
// Request type = `deleteProtectedRange`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DeleteProtectedRangeRequest
}
async autoResizeDimensions() {
// Request type = `autoResizeDimensions`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#AutoResizeDimensionsRequest
}
async addChart() {
// Request type = `addChart`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#AddChartRequest
}
async updateChartSpec() {
// Request type = `updateChartSpec`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#UpdateChartSpecRequest
}
async updateBanding() {
// Request type = `updateBanding`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#UpdateBandingRequest
}
async addBanding() {
// Request type = `addBanding`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#AddBandingRequest
}
async deleteBanding() {
// Request type = `deleteBanding`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DeleteBandingRequest
}
async createDeveloperMetadata() {
// Request type = `createDeveloperMetadata`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#CreateDeveloperMetadataRequest
}
async updateDeveloperMetadata() {
// Request type = `updateDeveloperMetadata`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#UpdateDeveloperMetadataRequest
}
async deleteDeveloperMetadata() {
// Request type = `deleteDeveloperMetadata`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DeleteDeveloperMetadataRequest
}
async randomizeRange() {
// Request type = `randomizeRange`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#RandomizeRangeRequest
}
async addDimensionGroup() {
// Request type = `addDimensionGroup`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#AddDimensionGroupRequest
}
async deleteDimensionGroup() {
// Request type = `deleteDimensionGroup`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DeleteDimensionGroupRequest
}
async updateDimensionGroup() {
// Request type = `updateDimensionGroup`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#UpdateDimensionGroupRequest
}
async trimWhitespace() {
// Request type = `trimWhitespace`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#TrimWhitespaceRequest
}
async deleteDuplicates() {
// Request type = `deleteDuplicates`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#DeleteDuplicatesRequest
}
async addSlicer() {
// Request type = `addSlicer`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#AddSlicerRequest
}
async updateSlicerSpec() {
// Request type = `updateSlicerSpec`
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#UpdateSlicerSpecRequest
}
// delete this worksheet
async delete() {
return this._spreadsheet.deleteSheet(this.sheetId);
}
async del() { return this.delete(); } // alias to mimic old interface
// copies this worksheet into another document/spreadsheet
async copyToSpreadsheet(destinationSpreadsheetId) {
return this._spreadsheet.axios.post(`/sheets/${this.sheetId}:copyTo`, {
destinationSpreadsheetId,
});
}
async clear() {
// clears all the data in the sheet
// sheet name without ie 'sheet1' rather than 'sheet1'!A1:B5 is all cells
await this._spreadsheet.axios.post(`/values/${this.encodedA1SheetName}:clear`);
this.resetLocalCache(true);
}
}
module.exports = GoogleSpreadsheetWorksheet;