1
1
mirror of https://github.com/n8n-io/n8n.git synced 2024-09-11 13:15:28 +03:00

Add lookup operation to GoogleSheets-Node

This commit is contained in:
Jan Oberhauser 2019-08-27 20:27:00 +02:00
parent 27e52254b1
commit d9c7a8ee04
2 changed files with 132 additions and 4 deletions

View File

@ -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;

View File

@ -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);