diff --git a/packages/nodes-base/nodes/Google/Sheet/GenericFunctions.ts b/packages/nodes-base/nodes/Google/Sheet/GenericFunctions.ts index 21831fc9b774b..80526a9ce1e62 100644 --- a/packages/nodes-base/nodes/Google/Sheet/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Google/Sheet/GenericFunctions.ts @@ -127,3 +127,19 @@ function getAccessToken(this: IExecuteFunctions | IExecuteSingleFunctions | ILoa //@ts-ignore return this.helpers.request(options); } + +// Hex to RGB +export function hexToRgb(hex: string) { + // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") + const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; + hex = hex.replace(shorthandRegex, (m, r, g, b) => { + return r + r + g + g + b + b; + }); + + const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return result ? { + red: parseInt(result[1], 16), + green: parseInt(result[2], 16), + blue: parseInt(result[3], 16), + } : null; +} \ No newline at end of file diff --git a/packages/nodes-base/nodes/Google/Sheet/GoogleSheets.node.ts b/packages/nodes-base/nodes/Google/Sheet/GoogleSheets.node.ts index ac3750e9fa9e4..58782e1e15fcf 100644 --- a/packages/nodes-base/nodes/Google/Sheet/GoogleSheets.node.ts +++ b/packages/nodes-base/nodes/Google/Sheet/GoogleSheets.node.ts @@ -23,6 +23,7 @@ import { import { googleApiRequest, + hexToRgb, } from './GenericFunctions'; export class GoogleSheets implements INodeType { @@ -121,6 +122,11 @@ export class GoogleSheets implements INodeType { value: 'clear', description: 'Clear data from a sheet', }, + { + name: 'Create', + value: 'create', + description: 'Create a new sheet', + }, { name: 'Delete', value: 'delete', @@ -136,6 +142,11 @@ export class GoogleSheets implements INodeType { value: 'read', description: 'Read data from a sheet', }, + { + name: 'Remove', + value: 'remove', + description: 'Remove a sheet', + }, { name: 'Update', value: 'update', @@ -150,7 +161,7 @@ export class GoogleSheets implements INodeType { // All // ---------------------------------- { - displayName: 'Sheet ID', + displayName: 'Spreadsheet ID', name: 'sheetId', type: 'string', displayOptions: { @@ -162,7 +173,7 @@ export class GoogleSheets implements INodeType { }, default: '', required: true, - description: 'The ID of the Google Sheet.
Found as part of the sheet URL https://docs.google.com/spreadsheets/d/{ID}/', + description: 'The ID of the Google Spreadsheet.
Found as part of the sheet URL https://docs.google.com/spreadsheets/d/{ID}/', }, { displayName: 'Range', @@ -176,7 +187,9 @@ export class GoogleSheets implements INodeType { }, hide: { operation: [ + 'create', 'delete', + 'remove', ], }, }, @@ -185,7 +198,6 @@ export class GoogleSheets implements INodeType { description: 'The table range to read from or to append data to. See the Google documentation for the details.
If it contains multiple sheets it can also be
added like this: "MySheet!A:F"', }, - // ---------------------------------- // Delete // ---------------------------------- @@ -392,8 +404,10 @@ export class GoogleSheets implements INodeType { hide: { operation: [ 'append', + 'create', 'clear', 'delete', + 'remove', ], rawData: [ true, @@ -422,7 +436,9 @@ export class GoogleSheets implements INodeType { hide: { operation: [ 'clear', + 'create', 'delete', + 'remove', ], rawData: [ true, @@ -596,7 +612,7 @@ export class GoogleSheets implements INodeType { { name: 'Formula', value: 'FORMULA', - description: ' Values will not be calculated. The reply will include the formulas. For example, if A1 is 1.23 and A2 is =A1 and formatted as currency, then A2 would return "=A1".', + description: 'Values will not be calculated. The reply will include the formulas. For example, if A1 is 1.23 and A2 is =A1 and formatted as currency, then A2 would return "=A1".', }, { name: 'Unformatted Value', @@ -793,6 +809,170 @@ export class GoogleSheets implements INodeType { }, ], }, + + // ---------------------------------- + // sheet:create + // ---------------------------------- + { + displayName: 'Simple', + name: 'simple', + type: 'boolean', + default: true, + displayOptions: { + show: { + resource: [ + 'sheet', + ], + operation: [ + 'create', + ], + }, + }, + description: 'When set to true a simplify version of the response will be used else the raw data.', + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Option', + default: {}, + displayOptions: { + show: { + resource: [ + 'sheet', + ], + operation: [ + 'create', + ], + }, + }, + options: [ + { + displayName: 'Grid Properties', + name: 'gridProperties', + type: 'collection', + placeholder: 'Add Property', + default: '', + options: [ + { + displayName: 'Column Count', + name: 'columnCount', + type: 'number', + default: 0, + description: 'The number of columns in the grid.', + }, + { + displayName: 'Column Group Control After', + name: 'columnGroupControlAfter', + type: 'boolean', + default: false, + description: 'True if the column grouping control toggle is shown after the group.', + }, + { + displayName: 'Frozen Column Count', + name: 'frozenColumnCount', + type: 'number', + default: 0, + description: 'The number of columns that are frozen in the grid.', + }, + { + displayName: 'Frozen Row Count', + name: 'frozenRowCount', + type: 'number', + default: 0, + description: 'The number of rows that are frozen in the grid.', + }, + { + displayName: 'Hide Gridlines', + name: 'hideGridlines', + type: 'boolean', + default: false, + description: 'True if the grid isn\'t showing gridlines in the UI.', + }, + { + displayName: 'Row Count', + name: 'rowCount', + type: 'number', + default: 0, + description: 'The number of rows in the grid.', + }, + { + displayName: 'Row Group Control After', + name: 'rowGroupControlAfter', + type: 'boolean', + default: false, + description: 'True if the row grouping control toggle is shown after the group.', + }, + + ], + description: 'The type of the sheet.', + }, + { + displayName: 'Hidden', + name: 'hidden', + type: 'boolean', + default: false, + description: 'True if the sheet is hidden in the UI, false if it\'s visible.', + }, + { + displayName: 'Right To Left', + name: 'rightToLeft', + type: 'boolean', + default: false, + description: 'True if the sheet is an RTL sheet instead of an LTR sheet.', + }, + { + displayName: 'Sheet ID', + name: 'sheetId', + type: 'number', + default: 0, + description: 'The ID of the sheet. Must be non-negative. This field cannot be changed once set.', + }, + { + displayName: 'Sheet Index', + name: 'index', + type: 'number', + default: 0, + description: 'The index of the sheet within the spreadsheet.', + }, + { + displayName: 'Tab Color', + name: 'tabColor', + type: 'color', + default: '0aa55c', + description: 'The color of the tab in the UI.', + }, + { + displayName: 'Title', + name: 'title', + type: 'string', + default: '', + description: 'The Sheet name.', + }, + ], + }, + + // ---------------------------------- + // sheet:remove + // ---------------------------------- + { + displayName: 'Sheet ID', + name: 'id', + type: 'string', + default: '', + required: true, + displayOptions: { + show: { + resource: [ + 'sheet', + ], + operation: [ + 'remove', + ], + }, + }, + description: 'The ID of the sheet to delete.', + }, ], }; @@ -840,7 +1020,7 @@ export class GoogleSheets implements INodeType { const sheet = new GoogleSheet(spreadsheetId, this); let range = ''; - if (operation !== 'delete') { + if (!['create', 'delete', 'remove'].includes(operation)) { range = this.getNodeParameter('range', 0) as string; } @@ -878,6 +1058,39 @@ export class GoogleSheets implements INodeType { const items = this.getInputData(); return this.prepareOutputData(items); + + } else if (operation === 'create') { + const returnData: IDataObject[] = []; + + let responseData; + for (let i = 0; i < this.getInputData().length; i++) { + const spreadsheetId = this.getNodeParameter('sheetId', i) as string; + const options = this.getNodeParameter('options', i, {}) as IDataObject; + const simple = this.getNodeParameter('simple', 0) as boolean; + const properties = { ...options }; + + if (options.tabColor) { + const { red, green, blue } = hexToRgb(options.tabColor as string)!; + properties.tabColor = { red: red / 255, green: green / 255, blue: blue / 255 }; + } + + const requests = [{ + addSheet: { + properties, + }, + }]; + + responseData = await googleApiRequest.call(this, 'POST', `/v4/spreadsheets/${spreadsheetId}:batchUpdate`, { requests }); + + if (simple === true) { + Object.assign(responseData, responseData.replies[0].addSheet.properties); + delete responseData.replies; + } + returnData.push(responseData); + } + + return [this.helpers.returnJsonArray(returnData)]; + } else if (operation === 'delete') { // ---------------------------------- // delete @@ -976,6 +1189,27 @@ export class GoogleSheets implements INodeType { returnData = [{}]; } + return [this.helpers.returnJsonArray(returnData)]; + + } else if (operation === 'remove') { + const returnData: IDataObject[] = []; + + let responseData; + for (let i = 0; i < this.getInputData().length; i++) { + const sheetId = this.getNodeParameter('id', i) as string; + const spreadsheetId = this.getNodeParameter('sheetId', i) as string; + + const requests = [{ + deleteSheet: { + sheetId, + }, + }]; + + responseData = await googleApiRequest.call(this, 'POST', `/v4/spreadsheets/${spreadsheetId}:batchUpdate`, { requests }); + delete responseData.replies; + returnData.push(responseData); + } + return [this.helpers.returnJsonArray(returnData)]; } else if (operation === 'update') { // ----------------------------------