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') {
// ----------------------------------