mirror of
https://github.com/n8n-io/n8n.git
synced 2025-02-21 02:56:40 -08:00
✨ Add delete operation to GoogleSheets-Node
This commit is contained in:
parent
8bf90e6496
commit
2a802256ca
|
@ -1,5 +1,5 @@
|
||||||
import { IDataObject } from 'n8n-workflow';
|
import { IDataObject } from 'n8n-workflow';
|
||||||
import { google } from 'googleapis';
|
import { google, sheets_v4 } from 'googleapis';
|
||||||
import { JWT } from 'google-auth-library';
|
import { JWT } from 'google-auth-library';
|
||||||
import { getAuthenticationClient } from './GoogleApi';
|
import { getAuthenticationClient } from './GoogleApi';
|
||||||
|
|
||||||
|
@ -24,6 +24,18 @@ export interface ILookupValues {
|
||||||
lookupValue: string;
|
lookupValue: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IToDeleteRange {
|
||||||
|
amount: number;
|
||||||
|
startIndex: number;
|
||||||
|
sheetId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IToDelete {
|
||||||
|
[key: string]: IToDeleteRange[] | undefined;
|
||||||
|
columns?: IToDeleteRange[];
|
||||||
|
rows?: IToDeleteRange[];
|
||||||
|
}
|
||||||
|
|
||||||
export type ValueInputOption = 'RAW' | 'USER_ENTERED';
|
export type ValueInputOption = 'RAW' | 'USER_ENTERED';
|
||||||
|
|
||||||
export type ValueRenderOption = 'FORMATTED_VALUE' | 'FORMULA' | 'UNFORMATTED_VALUE';
|
export type ValueRenderOption = 'FORMATTED_VALUE' | 'FORMULA' | 'UNFORMATTED_VALUE';
|
||||||
|
@ -85,6 +97,44 @@ export class GoogleSheet {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the sheets in a Spreadsheet
|
||||||
|
*/
|
||||||
|
async spreadsheetGetSheets() {
|
||||||
|
const client = await this.getAuthenticationClient();
|
||||||
|
|
||||||
|
const response = await Sheets.spreadsheets.get(
|
||||||
|
{
|
||||||
|
auth: client,
|
||||||
|
spreadsheetId: this.id,
|
||||||
|
fields: 'sheets.properties'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets values in one or more ranges of a spreadsheet.
|
||||||
|
*/
|
||||||
|
async spreadsheetBatchUpdate(requests: sheets_v4.Schema$Request[]) { // tslint:disable-line:no-any
|
||||||
|
const client = await this.getAuthenticationClient();
|
||||||
|
|
||||||
|
const response = await Sheets.spreadsheets.batchUpdate(
|
||||||
|
{
|
||||||
|
auth: client,
|
||||||
|
spreadsheetId: this.id,
|
||||||
|
requestBody: {
|
||||||
|
requests,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the cell values
|
* Sets the cell values
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
|
import { sheets_v4 } from 'googleapis';
|
||||||
|
|
||||||
import { IExecuteFunctions } from 'n8n-core';
|
import { IExecuteFunctions } from 'n8n-core';
|
||||||
import {
|
import {
|
||||||
IDataObject,
|
IDataObject,
|
||||||
|
ILoadOptionsFunctions,
|
||||||
INodeExecutionData,
|
INodeExecutionData,
|
||||||
|
INodePropertyOptions,
|
||||||
INodeType,
|
INodeType,
|
||||||
INodeTypeDescription,
|
INodeTypeDescription,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
@ -11,6 +15,7 @@ import {
|
||||||
IGoogleAuthCredentials,
|
IGoogleAuthCredentials,
|
||||||
ILookupValues,
|
ILookupValues,
|
||||||
ISheetUpdateData,
|
ISheetUpdateData,
|
||||||
|
IToDelete,
|
||||||
ValueInputOption,
|
ValueInputOption,
|
||||||
ValueRenderOption,
|
ValueRenderOption,
|
||||||
} from './GoogleSheet';
|
} from './GoogleSheet';
|
||||||
|
@ -52,6 +57,11 @@ export class GoogleSheets implements INodeType {
|
||||||
value: 'clear',
|
value: 'clear',
|
||||||
description: 'Clears data from a Sheet',
|
description: 'Clears data from a Sheet',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'Delete',
|
||||||
|
value: 'delete',
|
||||||
|
description: 'Delete columns and rows from a Sheet',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'Lookup',
|
name: 'Lookup',
|
||||||
value: 'lookup',
|
value: 'lookup',
|
||||||
|
@ -87,11 +97,120 @@ export class GoogleSheets implements INodeType {
|
||||||
displayName: 'Range',
|
displayName: 'Range',
|
||||||
name: 'range',
|
name: 'range',
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
displayOptions: {
|
||||||
|
hide: {
|
||||||
|
operation: [
|
||||||
|
'delete'
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
default: 'A:F',
|
default: 'A:F',
|
||||||
required: true,
|
required: true,
|
||||||
description: 'The table range to read from or to append data to. See the Google <a href="https://developers.google.com/sheets/api/guides/values#writing">documentation</a> for the details.<br />If it contains multiple sheets it can also be<br />added like this: "MySheet!A:F"',
|
description: 'The table range to read from or to append data to. See the Google <a href="https://developers.google.com/sheets/api/guides/values#writing">documentation</a> for the details.<br />If it contains multiple sheets it can also be<br />added like this: "MySheet!A:F"',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------
|
||||||
|
// Delete
|
||||||
|
// ----------------------------------
|
||||||
|
{
|
||||||
|
displayName: 'To Delete',
|
||||||
|
name: 'toDelete',
|
||||||
|
placeholder: 'Add Columns/Rows to delete',
|
||||||
|
description: 'Deletes colums and rows from a sheet.',
|
||||||
|
type: 'fixedCollection',
|
||||||
|
typeOptions: {
|
||||||
|
multipleValues: true,
|
||||||
|
},
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
operation: [
|
||||||
|
'delete'
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default: {},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
displayName: 'Columns',
|
||||||
|
name: 'columns',
|
||||||
|
values: [
|
||||||
|
{
|
||||||
|
displayName: 'Sheet',
|
||||||
|
name: 'sheetId',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getSheets',
|
||||||
|
},
|
||||||
|
options: [],
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
description: 'The sheet to delete columns from',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Start Index',
|
||||||
|
name: 'startIndex',
|
||||||
|
type: 'number',
|
||||||
|
typeOptions: {
|
||||||
|
minValue: 0,
|
||||||
|
},
|
||||||
|
default: 0,
|
||||||
|
description: 'The start index (0 based and inclusive) of column to delete.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Amount',
|
||||||
|
name: 'amount',
|
||||||
|
type: 'number',
|
||||||
|
typeOptions: {
|
||||||
|
minValue: 1,
|
||||||
|
},
|
||||||
|
default: 1,
|
||||||
|
description: 'Number of columns to delete.',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Rows',
|
||||||
|
name: 'rows',
|
||||||
|
values: [
|
||||||
|
{
|
||||||
|
displayName: 'Sheet',
|
||||||
|
name: 'sheetId',
|
||||||
|
type: 'options',
|
||||||
|
typeOptions: {
|
||||||
|
loadOptionsMethod: 'getSheets',
|
||||||
|
},
|
||||||
|
options: [],
|
||||||
|
default: '',
|
||||||
|
required: true,
|
||||||
|
description: 'The sheet to delete columns from',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Start Index',
|
||||||
|
name: 'startIndex',
|
||||||
|
type: 'number',
|
||||||
|
typeOptions: {
|
||||||
|
minValue: 0,
|
||||||
|
},
|
||||||
|
default: 0,
|
||||||
|
description: 'The start index (0 based and inclusive) of row to delete.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Amount',
|
||||||
|
name: 'amount',
|
||||||
|
type: 'number',
|
||||||
|
typeOptions: {
|
||||||
|
minValue: 1,
|
||||||
|
},
|
||||||
|
default: 1,
|
||||||
|
description: 'Number of rows to delete.',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------
|
// ----------------------------------
|
||||||
// Read
|
// Read
|
||||||
// ----------------------------------
|
// ----------------------------------
|
||||||
|
@ -178,6 +297,7 @@ export class GoogleSheets implements INodeType {
|
||||||
operation: [
|
operation: [
|
||||||
'append',
|
'append',
|
||||||
'clear',
|
'clear',
|
||||||
|
'delete',
|
||||||
],
|
],
|
||||||
rawData: [
|
rawData: [
|
||||||
true
|
true
|
||||||
|
@ -201,6 +321,7 @@ export class GoogleSheets implements INodeType {
|
||||||
hide: {
|
hide: {
|
||||||
operation: [
|
operation: [
|
||||||
'clear',
|
'clear',
|
||||||
|
'delete',
|
||||||
],
|
],
|
||||||
rawData: [
|
rawData: [
|
||||||
true
|
true
|
||||||
|
@ -401,6 +522,48 @@ export class GoogleSheets implements INodeType {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
methods = {
|
||||||
|
loadOptions: {
|
||||||
|
// Get all the sheets in a Spreadsheet
|
||||||
|
async getSheets(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||||
|
const spreadsheetId = this.getCurrentNodeParameter('sheetId') as string;
|
||||||
|
|
||||||
|
const credentials = this.getCredentials('googleApi');
|
||||||
|
|
||||||
|
if (credentials === undefined) {
|
||||||
|
throw new Error('No credentials got returned!');
|
||||||
|
}
|
||||||
|
|
||||||
|
const googleCredentials = {
|
||||||
|
email: credentials.email,
|
||||||
|
privateKey: credentials.privateKey,
|
||||||
|
} as IGoogleAuthCredentials;
|
||||||
|
|
||||||
|
const sheet = new GoogleSheet(spreadsheetId, googleCredentials);
|
||||||
|
const responseData = await sheet.spreadsheetGetSheets();
|
||||||
|
|
||||||
|
if (responseData === undefined) {
|
||||||
|
throw new Error('No data got returned');
|
||||||
|
}
|
||||||
|
|
||||||
|
const returnData: INodePropertyOptions[] = [];
|
||||||
|
for (const sheet of responseData.sheets!) {
|
||||||
|
if (sheet.properties!.sheetType !== 'GRID') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
returnData.push({
|
||||||
|
name: sheet.properties!.title as string,
|
||||||
|
value: sheet.properties!.sheetId as unknown as string,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnData;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||||
const spreadsheetId = this.getNodeParameter('sheetId', 0) as string;
|
const spreadsheetId = this.getNodeParameter('sheetId', 0) as string;
|
||||||
const credentials = this.getCredentials('googleApi');
|
const credentials = this.getCredentials('googleApi');
|
||||||
|
@ -416,10 +579,13 @@ export class GoogleSheets implements INodeType {
|
||||||
|
|
||||||
const sheet = new GoogleSheet(spreadsheetId, googleCredentials);
|
const sheet = new GoogleSheet(spreadsheetId, googleCredentials);
|
||||||
|
|
||||||
const range = this.getNodeParameter('range', 0) as string;
|
|
||||||
|
|
||||||
const operation = this.getNodeParameter('operation', 0) as string;
|
const operation = this.getNodeParameter('operation', 0) as string;
|
||||||
|
|
||||||
|
let range = '';
|
||||||
|
if (operation !== 'delete') {
|
||||||
|
range = this.getNodeParameter('range', 0) as string;
|
||||||
|
}
|
||||||
|
|
||||||
const options = this.getNodeParameter('options', 0, {}) as IDataObject;
|
const options = this.getNodeParameter('options', 0, {}) as IDataObject;
|
||||||
|
|
||||||
const valueInputMode = (options.valueInputMode || 'RAW') as ValueInputOption;
|
const valueInputMode = (options.valueInputMode || 'RAW') as ValueInputOption;
|
||||||
|
@ -452,6 +618,41 @@ export class GoogleSheets implements INodeType {
|
||||||
|
|
||||||
await sheet.clearData(range);
|
await sheet.clearData(range);
|
||||||
|
|
||||||
|
const items = this.getInputData();
|
||||||
|
return this.prepareOutputData(items);
|
||||||
|
} else if (operation === 'delete') {
|
||||||
|
// ----------------------------------
|
||||||
|
// delete
|
||||||
|
// ----------------------------------
|
||||||
|
|
||||||
|
const requests: sheets_v4.Schema$Request[] = [];
|
||||||
|
|
||||||
|
const toDelete = this.getNodeParameter('toDelete', 0) as IToDelete;
|
||||||
|
|
||||||
|
const deletePropertyToDimensions: IDataObject = {
|
||||||
|
'columns': 'COLUMNS',
|
||||||
|
'rows': 'ROWS',
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const propertyName of Object.keys(deletePropertyToDimensions)) {
|
||||||
|
if (toDelete[propertyName] !== undefined) {
|
||||||
|
toDelete[propertyName]!.forEach(range => {
|
||||||
|
requests.push({
|
||||||
|
deleteDimension: {
|
||||||
|
range: {
|
||||||
|
sheetId: range.sheetId,
|
||||||
|
dimension: deletePropertyToDimensions[propertyName] as string,
|
||||||
|
startIndex: range.startIndex,
|
||||||
|
endIndex: range.startIndex + range.amount,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await sheet.spreadsheetBatchUpdate(requests);
|
||||||
|
|
||||||
const items = this.getInputData();
|
const items = this.getInputData();
|
||||||
return this.prepareOutputData(items);
|
return this.prepareOutputData(items);
|
||||||
} else if (operation === 'lookup') {
|
} else if (operation === 'lookup') {
|
||||||
|
|
Loading…
Reference in a new issue