import type { IExecuteFunctions, IDataObject, INodeExecutionData } from 'n8n-workflow'; import type { GoogleSheet } from '../../helpers/GoogleSheet'; import { getRangeString, prepareSheetData, untilSheetSelected, } from '../../helpers/GoogleSheets.utils'; import type { ILookupValues, RangeDetectionOptions, SheetProperties, SheetRangeData, ValueRenderOption, } from '../../helpers/GoogleSheets.types'; import { dataLocationOnSheet, outputFormatting } from './commonDescription'; export const description: SheetProperties = [ { displayName: 'Filters', name: 'filtersUI', placeholder: 'Add Filter', type: 'fixedCollection', typeOptions: { multipleValueButtonText: 'Add Filter', multipleValues: true, }, default: {}, options: [ { displayName: 'Filter', name: 'values', values: [ { // eslint-disable-next-line n8n-nodes-base/node-param-display-name-wrong-for-dynamic-options displayName: 'Column', name: 'lookupColumn', type: 'options', typeOptions: { loadOptionsDependsOn: ['sheetName.value'], loadOptionsMethod: 'getSheetHeaderRowWithGeneratedColumnNames', }, default: '', description: 'Choose from the list, or specify an ID using an expression', }, { displayName: 'Value', name: 'lookupValue', type: 'string', default: '', hint: 'The column must have this value to be matched', }, ], }, ], displayOptions: { show: { resource: ['sheet'], operation: ['read'], }, hide: { ...untilSheetSelected, }, }, }, { displayName: 'Options', name: 'options', type: 'collection', placeholder: 'Add Option', default: {}, displayOptions: { show: { resource: ['sheet'], operation: ['read'], }, hide: { ...untilSheetSelected, }, }, options: [ dataLocationOnSheet, outputFormatting, { displayName: 'When Filter Has Multiple Matches', name: 'returnAllMatches', type: 'options', default: 'returnFirstMatch', options: [ { name: 'Return First Match', value: 'returnFirstMatch', description: 'Return only the first match', }, { name: 'Return All Matches', value: 'returnAllMatches', description: 'Return all values that match', }, ], description: 'By default only the first result gets returned, Set to "Return All Matches" to get multiple matches', }, ], }, ]; export async function execute( this: IExecuteFunctions, sheet: GoogleSheet, sheetName: string, ): Promise { const items = this.getInputData(); const nodeVersion = this.getNode().typeVersion; let length = 1; if (nodeVersion > 4.1) { length = items.length; } const returnData: INodeExecutionData[] = []; for (let itemIndex = 0; itemIndex < length; itemIndex++) { const options = this.getNodeParameter('options', itemIndex, {}); const outputFormattingOption = ((options.outputFormatting as IDataObject)?.values as IDataObject) || {}; const dataLocationOnSheetOptions = ((options.dataLocationOnSheet as IDataObject)?.values as RangeDetectionOptions) || {}; if (dataLocationOnSheetOptions.rangeDefinition === undefined) { dataLocationOnSheetOptions.rangeDefinition = 'detectAutomatically'; } const range = getRangeString(sheetName, dataLocationOnSheetOptions); const valueRenderMode = (outputFormattingOption.general || 'UNFORMATTED_VALUE') as ValueRenderOption; const dateTimeRenderOption = (outputFormattingOption.date || 'FORMATTED_STRING') as string; const sheetData = (await sheet.getData( range, valueRenderMode, dateTimeRenderOption, )) as SheetRangeData; if (sheetData === undefined || sheetData.length === 0) { return []; } const { data, headerRow, firstDataRow } = prepareSheetData( sheetData, dataLocationOnSheetOptions, ); let responseData = []; const lookupValues = this.getNodeParameter( 'filtersUI.values', itemIndex, [], ) as ILookupValues[]; if (lookupValues.length) { const returnAllMatches = options.returnAllMatches === 'returnAllMatches' ? true : false; if (nodeVersion <= 4.1) { for (let i = 1; i < items.length; i++) { const itemLookupValues = this.getNodeParameter( 'filtersUI.values', i, [], ) as ILookupValues[]; if (itemLookupValues.length) { lookupValues.push(...itemLookupValues); } } } responseData = await sheet.lookupValues( data as string[][], headerRow, firstDataRow, lookupValues, returnAllMatches, ); } else { responseData = sheet.structureArrayDataByColumn(data as string[][], headerRow, firstDataRow); } returnData.push( ...responseData.map((item, index) => { return { json: item, pairedItem: { item: itemIndex }, }; }), ); } return returnData; }