Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Google Sheets Node): Add "By Name" option to selector for Sheets #8241

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions packages/nodes-base/nodes/Google/Sheet/GoogleSheetsTrigger.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { apiRequest } from './v2/transport';
import { sheetsSearch, spreadSheetsSearch } from './v2/methods/listSearch';
import { GoogleSheet } from './v2/helpers/GoogleSheet';
import { getSheetHeaderRowAndSkipEmpty } from './v2/methods/loadOptions';
import type { ValueRenderOption } from './v2/helpers/GoogleSheets.types';
import type { ResourceLocator, ValueRenderOption } from './v2/helpers/GoogleSheets.types';

import {
arrayOfArraysToJson,
Expand Down Expand Up @@ -399,11 +399,21 @@ export class GoogleSheetsTrigger implements INodeType {
extractValue: true,
}) as string;

let sheetId = this.getNodeParameter('sheetName', undefined, {
const sheetWithinDocument = this.getNodeParameter('sheetName', undefined, {
extractValue: true,
}) as string;
const { mode: sheetMode } = this.getNodeParameter('sheetName', 0) as {
mode: ResourceLocator;
};

sheetId = sheetId === 'gid=0' ? '0' : sheetId;
const googleSheet = new GoogleSheet(documentId, this);
const { sheetId, title: sheetName } = await googleSheet.spreadsheetGetSheet(
this.getNode(),
sheetMode,
sheetWithinDocument,
);

const options = this.getNodeParameter('options') as IDataObject;

// If the documentId or sheetId changed, reset the workflow static data
if (
Expand All @@ -417,13 +427,6 @@ export class GoogleSheetsTrigger implements INodeType {
workflowStaticData.lastIndexChecked = undefined;
}

const googleSheet = new GoogleSheet(documentId, this);
const sheetName: string = await googleSheet.spreadsheetGetSheetNameById(
this.getNode(),
sheetId,
);
const options = this.getNodeParameter('options') as IDataObject;

const previousRevision = workflowStaticData.lastRevision as number;
const previousRevisionLink = workflowStaticData.lastRevisionLink as string;

Expand Down
20 changes: 13 additions & 7 deletions packages/nodes-base/nodes/Google/Sheet/v2/actions/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,25 @@ export async function router(this: IExecuteFunctions): Promise<INodeExecutionDat
const googleSheet = new GoogleSheet(spreadsheetId, this);

let sheetId = '';
let sheetName = '';

if (operation !== 'create') {
sheetId = this.getNodeParameter('sheetName', 0, undefined, {
const sheetWithinDocument = this.getNodeParameter('sheetName', 0, undefined, {
extractValue: true,
}) as string;
}
const { mode: sheetMode } = this.getNodeParameter('sheetName', 0) as {
mode: ResourceLocator;
};

if (sheetId === 'gid=0') {
sheetId = '0';
const result = await googleSheet.spreadsheetGetSheet(
this.getNode(),
sheetMode,
sheetWithinDocument,
);
sheetId = result.sheetId.toString();
sheetName = result.title;
}

let sheetName = '';
switch (operation) {
case 'create':
sheetName = spreadsheetId;
Expand All @@ -50,8 +58,6 @@ export async function router(this: IExecuteFunctions): Promise<INodeExecutionDat
case 'remove':
sheetName = `${spreadsheetId}||${sheetId}`;
break;
default:
sheetName = await googleSheet.spreadsheetGetSheetNameById(this.getNode(), sheetId);
}

results = await sheet[googleSheets.operation].execute.call(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,12 @@ export const descriptions: INodeProperties[] = [
},
],
},
{
displayName: 'By Name',
name: 'name',
type: 'string',
placeholder: 'Sheet1',
},
],
displayOptions: {
show: {
Expand Down
35 changes: 20 additions & 15 deletions packages/nodes-base/nodes/Google/Sheet/v2/helpers/GoogleSheet.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
import get from 'lodash/get';
import type {
IDataObject,
IExecuteFunctions,
ILoadOptionsFunctions,
IDataObject,
IPollFunctions,
INode,
IPollFunctions,
} from 'n8n-workflow';
import { ApplicationError, NodeOperationError } from 'n8n-workflow';
import { utils as xlsxUtils } from 'xlsx';
import get from 'lodash/get';
import { apiRequest } from '../transport';
import type {
ILookupValues,
ISheetUpdateData,
ResourceLocator,
SheetCellDecoded,
SheetRangeData,
SheetRangeDecoded,
SpreadSheetResponse,
ValueInputOption,
ValueRenderOption,
} from './GoogleSheets.types';
import { removeEmptyColumns } from './GoogleSheets.utils';
import { getSheetId, removeEmptyColumns } from './GoogleSheets.utils';

export class GoogleSheet {
id: string;
Expand Down Expand Up @@ -116,32 +118,35 @@ export class GoogleSheet {
}

/**
* Returns the name of a sheet from a sheet id
* Returns the sheet within a spreadsheet based on name or ID
*/
async spreadsheetGetSheetNameById(node: INode, sheetId: string) {
async spreadsheetGetSheet(node: INode, mode: ResourceLocator, value: string) {
const query = {
fields: 'sheets.properties',
};

const response = await apiRequest.call(
const response = (await apiRequest.call(
this.executeFunctions,
'GET',
`/v4/spreadsheets/${this.id}`,
{},
query,
);
)) as SpreadSheetResponse;

const foundItem = response.sheets.find(
(item: { properties: { sheetId: number } }) => item.properties.sheetId === +sheetId,
);
const foundItem = response.sheets.find((item) => {
if (mode === 'name') return item.properties.title === value;
return item.properties.sheetId === getSheetId(value);
});

if (!foundItem?.properties?.title) {
throw new NodeOperationError(node, `Sheet with ID ${sheetId} not found`, {
level: 'warning',
});
throw new NodeOperationError(
node,
`Sheet with ${mode === 'name' ? 'name' : 'ID'} ${value} not found`,
{ level: 'warning' },
);
}

return foundItem.properties.title;
return foundItem.properties;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,24 @@ export type GoogleSheetsSheet = Entity<GoogleSheetsMap, 'sheet'>;
export type SpreadSheetProperties = PropertiesOf<GoogleSheetsSpreadSheet>;
export type SheetProperties = PropertiesOf<GoogleSheetsSheet>;

export type ResourceLocator = 'id' | 'url' | 'list';
export type ResourceLocator = 'id' | 'url' | 'list' | 'name';

export const ResourceLocatorUiNames = {
id: 'By ID',
url: 'By URL',
list: 'From List',
name: 'By Name',
};

type SpreadSheetResponseSheet = {
properties: {
title: string;
sheetId: number;
};
};

export type SpreadSheetResponse = {
sheets: SpreadSheetResponseSheet[];
};

export type SheetCellDecoded = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ export function getSpreadsheetId(
return value;
}

export function getSheetId(value: string): number {
if (value === 'gid=0') return 0;
return parseInt(value);
}

// Convert number to Sheets / Excel column name
export function getColumnName(colNumber: number): string {
const baseChar = 'A'.charCodeAt(0);
Expand Down
17 changes: 10 additions & 7 deletions packages/nodes-base/nodes/Google/Sheet/v2/methods/loadOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,18 @@ export async function getSheetHeaderRow(
const spreadsheetId = getSpreadsheetId(this.getNode(), mode as ResourceLocator, value as string);

const sheet = new GoogleSheet(spreadsheetId, this);
let sheetWithinDocument = this.getNodeParameter('sheetName', undefined, {
const sheetWithinDocument = this.getNodeParameter('sheetName', undefined, {
extractValue: true,
}) as string;

if (sheetWithinDocument === 'gid=0') {
sheetWithinDocument = '0';
}

const sheetName = await sheet.spreadsheetGetSheetNameById(this.getNode(), sheetWithinDocument);
const { mode: sheetMode } = this.getNodeParameter('sheetName', 0) as {
mode: ResourceLocator;
};

const { title: sheetName } = await sheet.spreadsheetGetSheet(
this.getNode(),
sheetMode,
sheetWithinDocument,
);
const sheetData = await sheet.getData(`${sheetName}!1:1`, 'FORMATTED_VALUE');

if (sheetData === undefined) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,16 @@ export async function getMappingColumns(
const spreadsheetId = getSpreadsheetId(this.getNode(), mode as ResourceLocator, value as string);

const sheet = new GoogleSheet(spreadsheetId, this);
let sheetWithinDocument = this.getNodeParameter('sheetName', undefined, {
const sheetWithinDocument = this.getNodeParameter('sheetName', undefined, {
extractValue: true,
}) as string;
const { mode: sheetMode } = this.getNodeParameter('sheetName', 0) as { mode: ResourceLocator };

if (sheetWithinDocument === 'gid=0') {
sheetWithinDocument = '0';
}

const sheetName = await sheet.spreadsheetGetSheetNameById(this.getNode(), sheetWithinDocument);
const { title: sheetName } = await sheet.spreadsheetGetSheet(
this.getNode(),
sheetMode,
sheetWithinDocument,
);
const sheetData = await sheet.getData(`${sheetName}!1:1`, 'FORMATTED_VALUE');

const columns = sheet.testFilter(sheetData || [], 0, 0).filter((col) => col !== '');
Expand Down
Loading