mirror of
https://github.com/n8n-io/n8n.git
synced 2025-01-12 05:17:28 -08:00
✨ Add lookup operation to GoogleSheets-Node
This commit is contained in:
parent
27e52254b1
commit
d9c7a8ee04
|
@ -18,6 +18,10 @@ export interface ISheetUpdateData {
|
|||
values: string[][];
|
||||
}
|
||||
|
||||
export interface ILookupValues {
|
||||
lookupColumn: string;
|
||||
lookupValue: string;
|
||||
}
|
||||
|
||||
export class GoogleSheet {
|
||||
id: string;
|
||||
|
@ -146,7 +150,7 @@ export class GoogleSheet {
|
|||
/**
|
||||
* Returns the given sheet data in a strucutred way
|
||||
*/
|
||||
structureData(inputData: string[][], startRow: number, keys: string[]): IDataObject[] {
|
||||
structureData(inputData: string[][], startRow: number, keys: string[], addEmpty?: boolean): IDataObject[] {
|
||||
const returnData = [];
|
||||
|
||||
let tempEntry: IDataObject, rowIndex: number, columnIndex: number, key: string;
|
||||
|
@ -160,7 +164,7 @@ export class GoogleSheet {
|
|||
tempEntry[key] = inputData[rowIndex][columnIndex];
|
||||
}
|
||||
}
|
||||
if (Object.keys(tempEntry).length) {
|
||||
if (Object.keys(tempEntry).length || addEmpty === true) {
|
||||
// Only add the entry if data got found to not have empty ones
|
||||
returnData.push(tempEntry);
|
||||
}
|
||||
|
@ -312,6 +316,61 @@ export class GoogleSheet {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Looks for a specific value in a column and if it gets found it returns the whole row
|
||||
*
|
||||
* @param {string[][]} inputData Data to to check for lookup value in
|
||||
* @param {number} keyRowIndex Index of the row which contains the keys
|
||||
* @param {number} dataStartRowIndex Index of the first row which contains data
|
||||
* @param {ILookupValues[]} lookupValues The lookup values which decide what data to return
|
||||
* @returns {Promise<IDataObject[]>}
|
||||
* @memberof GoogleSheet
|
||||
*/
|
||||
async lookupValues(inputData: string[][], keyRowIndex: number, dataStartRowIndex: number, lookupValues: ILookupValues[]): Promise<IDataObject[]> {
|
||||
const keys: string[] = [];
|
||||
|
||||
if (keyRowIndex < 0 || dataStartRowIndex < keyRowIndex || keyRowIndex >= inputData.length) {
|
||||
// The key row does not exist so it is not possible to look up the data
|
||||
throw new Error(`The key row does not exist!`);
|
||||
}
|
||||
|
||||
// Create the keys array
|
||||
for (let columnIndex = 0; columnIndex < inputData[keyRowIndex].length; columnIndex++) {
|
||||
keys.push(inputData[keyRowIndex][columnIndex]);
|
||||
}
|
||||
|
||||
const returnData = [
|
||||
inputData[keyRowIndex],
|
||||
];
|
||||
|
||||
// Loop over all the lookup values and try to find a row to return
|
||||
let rowIndex: number;
|
||||
let returnColumnIndex: number;
|
||||
lookupLoop:
|
||||
for (const lookupValue of lookupValues) {
|
||||
returnColumnIndex = keys.indexOf(lookupValue.lookupColumn);
|
||||
|
||||
if (returnColumnIndex === -1) {
|
||||
throw new Error(`The column "${lookupValue.lookupColumn}" could not be found!`);
|
||||
}
|
||||
|
||||
// Loop over all the items and find the one with the matching value
|
||||
for (rowIndex = dataStartRowIndex; rowIndex < inputData.length; rowIndex++) {
|
||||
if (inputData[rowIndex][returnColumnIndex].toString() === lookupValue.lookupValue.toString()) {
|
||||
returnData.push(inputData[rowIndex]);
|
||||
continue lookupLoop;
|
||||
}
|
||||
}
|
||||
|
||||
// If value could not be found add an empty one that the order of
|
||||
// the returned items stays the same
|
||||
returnData.push([]);
|
||||
}
|
||||
|
||||
return this.structureData(returnData, 1, keys, true);
|
||||
}
|
||||
|
||||
|
||||
async convertStructuredDataToArray(inputData: IDataObject[], range: string, keyRowIndex: number): Promise<string[][]> {
|
||||
let startColumn, endColumn;
|
||||
let sheet: string | undefined = undefined;
|
||||
|
|
|
@ -9,6 +9,7 @@ import {
|
|||
import {
|
||||
GoogleSheet,
|
||||
IGoogleAuthCredentials,
|
||||
ILookupValues,
|
||||
ISheetUpdateData,
|
||||
} from './GoogleSheet';
|
||||
|
||||
|
@ -44,6 +45,11 @@ export class GoogleSheets implements INodeType {
|
|||
value: 'append',
|
||||
description: 'Appends the data to a Sheet',
|
||||
},
|
||||
{
|
||||
name: 'Lookup',
|
||||
value: 'lookup',
|
||||
description: 'Looks for a specific column value and then returns the matching row'
|
||||
},
|
||||
{
|
||||
name: 'Read',
|
||||
value: 'read',
|
||||
|
@ -150,7 +156,7 @@ export class GoogleSheets implements INodeType {
|
|||
},
|
||||
|
||||
// ----------------------------------
|
||||
// Read & Update
|
||||
// Read & Update & lookupColumn
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Data Start Row',
|
||||
|
@ -194,6 +200,43 @@ export class GoogleSheets implements INodeType {
|
|||
description: 'Index of the row which contains the key. Starts with 0.',
|
||||
},
|
||||
|
||||
|
||||
// ----------------------------------
|
||||
// lookup
|
||||
// ----------------------------------
|
||||
{
|
||||
displayName: 'Lookup Column',
|
||||
name: 'lookupColumn',
|
||||
type: 'string',
|
||||
default: '',
|
||||
placeholder: 'Email',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: [
|
||||
'lookup'
|
||||
],
|
||||
},
|
||||
},
|
||||
description: 'The name of the column in which to look for value.',
|
||||
},
|
||||
{
|
||||
displayName: 'Lookup Value',
|
||||
name: 'lookupValue',
|
||||
type: 'string',
|
||||
default: '',
|
||||
placeholder: 'frank@example.com',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: [
|
||||
'lookup'
|
||||
],
|
||||
},
|
||||
},
|
||||
description: 'The value to look for in column.',
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
// Update
|
||||
// ----------------------------------
|
||||
|
@ -259,6 +302,33 @@ export class GoogleSheets implements INodeType {
|
|||
// TODO: Should have something like add metadata which does not get passed through
|
||||
|
||||
return this.prepareOutputData(items);
|
||||
} else if (operation === 'lookup') {
|
||||
// ----------------------------------
|
||||
// lookup
|
||||
// ----------------------------------
|
||||
|
||||
const sheetData = await sheet.getData(range);
|
||||
|
||||
if (sheetData === undefined) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const dataStartRow = this.getNodeParameter('dataStartRow', 0) as number;
|
||||
const keyRow = this.getNodeParameter('keyRow', 0) as number;
|
||||
|
||||
const items = this.getInputData();
|
||||
|
||||
const lookupValues: ILookupValues[] = [];
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
lookupValues.push({
|
||||
lookupColumn: this.getNodeParameter('lookupColumn', i) as string,
|
||||
lookupValue: this.getNodeParameter('lookupValue', i) as string,
|
||||
});
|
||||
}
|
||||
|
||||
const returnData = await sheet.lookupValues(sheetData, keyRow, dataStartRow, lookupValues);
|
||||
|
||||
return [this.helpers.returnJsonArray(returnData)];
|
||||
} else if (operation === 'read') {
|
||||
// ----------------------------------
|
||||
// read
|
||||
|
@ -312,7 +382,6 @@ export class GoogleSheets implements INodeType {
|
|||
const keyRow = this.getNodeParameter('keyRow', 0) as number;
|
||||
const dataStartRow = this.getNodeParameter('dataStartRow', 0) as number;
|
||||
|
||||
|
||||
const setData: IDataObject[] = [];
|
||||
items.forEach((item) => {
|
||||
setData.push(item.json);
|
||||
|
|
Loading…
Reference in a new issue