diff --git a/lib/GoogleSpreadsheetWorksheet.js b/lib/GoogleSpreadsheetWorksheet.js index 9e277d69..9d83f696 100644 --- a/lib/GoogleSpreadsheetWorksheet.js +++ b/lib/GoogleSpreadsheetWorksheet.js @@ -673,9 +673,35 @@ class GoogleSpreadsheetWorksheet { // 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 + // sortSpec is of the format + // [[rowIndex, order], [rowIndex, order]...] where order is 'desc' or 'asc' + // https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#SortRangeRequest + async sortRange(sortSpecs, range) { + if (!sortSpecs.length) return null; + if (!_.isArray(sortSpecs[0])) { sortSpecs = [sortSpecs]; } + + if (!this.headerValues) await this.loadHeaderRow(); + + // Allow a few values for order + const dirmap = { + desc: 'DESCENDING', + asc: 'ASCENDING', + DESCENDING: 'DESCENDING', + ASCENDING: 'ASCENDING', + }; + + sortSpecs = sortSpecs.map(([idx, dir]) => ({ + sortOrder: dirmap[dir], + dimensionIndex: typeof idx === 'number' ? idx : this.headerValues.indexOf(idx), + })); + + if (!range) { range = {}; } + range.sheetId = this.sheetId; + + return this._makeSingleUpdateRequest('sortRange', { + range, + sortSpecs, + }); } async setDataValidation() { diff --git a/test/cells.test.js b/test/cells.test.js index 7793c257..6c4394f2 100644 --- a/test/cells.test.js +++ b/test/cells.test.js @@ -236,5 +236,35 @@ describe('Cell-based operations', () => { }); }); }); + + describe('sorting a sheet', () => { + beforeEach(async () => { + await sheet.loadCells('A1:C4'); + const sheetData = [ + ['a', 'b', 'c'], + [1, 1, 2], + [2, 3, 1], + [3, 2, 3], + ]; + for (let row = 0; row < sheetData.length; row++) { + for (let col = 0; col < sheetData[row].length; col++) { + sheet.getCell(row, col).value = sheetData[row][col]; + } + } + await sheet.saveUpdatedCells(); + }); + + it('sorts by index', async () => { + await sheet.sortRange([[0, 'desc']]); + await sheet.loadCells('A1:C4'); + expect(sheet.getCell(1, 0).value).toBe(3); + }); + + it('sorts by header name', async () => { + await sheet.sortRange([['b', 'DESCENDING']]); + await sheet.loadCells('A1:C4'); + expect(sheet.getCell(1, 0).value).toBe(2); + }); + }); }); });