From 88efb9958711bac446b6a698dfba50afd2b46132 Mon Sep 17 00:00:00 2001 From: Michael Kret <88898367+michael-radency@users.noreply.github.com> Date: Wed, 15 Nov 2023 11:33:47 +0200 Subject: [PATCH] fix(Google Sheets Node): Append exceeding grid limits (#7684) Github issue / Community forum post (link here to close automatically): https://community.n8n.io/t/error-appending-data-with-google-sheets/28691 --- .../v2/actions/sheet/append.operation.ts | 35 +++++++++--- .../actions/sheet/appendOrUpdate.operation.ts | 41 ++++++++++---- .../Google/Sheet/v2/helpers/GoogleSheet.ts | 53 ++++++++++--------- 3 files changed, 85 insertions(+), 44 deletions(-) diff --git a/packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/append.operation.ts b/packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/append.operation.ts index 6508cee1f3..b17f8d9ffd 100644 --- a/packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/append.operation.ts +++ b/packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/append.operation.ts @@ -191,6 +191,14 @@ export const description: SheetProperties = [ ...handlingExtraData, displayOptions: { show: { '/columns.mappingMode': ['autoMapInputData'] } }, }, + { + displayName: 'Use Append', + name: 'useAppend', + type: 'boolean', + default: false, + description: + 'Whether to use append instead of update(default), this is more efficient but in some cases data might be misaligned', + }, ], }, ]; @@ -228,17 +236,28 @@ export async function execute( if (setData.length === 0) { return []; + } else if (options.useAppend) { + await sheet.appendSheetData( + setData, + sheetName, + headerRow, + (options.cellFormat as ValueInputOption) || cellFormatDefault(nodeVersion), + false, + undefined, + undefined, + options.useAppend as boolean, + ); } else { await sheet.appendEmptyRowsOrColumns(sheetId, 1, 0); - } - await sheet.appendSheetData( - setData, - sheetName, - headerRow, - (options.cellFormat as ValueInputOption) || cellFormatDefault(nodeVersion), - false, - ); + await sheet.appendSheetData( + setData, + sheetName, + headerRow, + (options.cellFormat as ValueInputOption) || cellFormatDefault(nodeVersion), + false, + ); + } if (nodeVersion < 4 || dataMode === 'autoMapInputData') { return items; diff --git a/packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/appendOrUpdate.operation.ts b/packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/appendOrUpdate.operation.ts index 6a3d5b37c8..6edb17d3d2 100644 --- a/packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/appendOrUpdate.operation.ts +++ b/packages/nodes-base/nodes/Google/Sheet/v2/actions/sheet/appendOrUpdate.operation.ts @@ -202,6 +202,14 @@ export const description: SheetProperties = [ ...handlingExtraData, displayOptions: { show: { '/columns.mappingMode': ['autoMapInputData'] } }, }, + { + displayName: 'Use Append', + name: 'useAppend', + type: 'boolean', + default: false, + description: + 'Whether to use append instead of update(default), this is more efficient but in some cases data might be misaligned', + }, ], }, ]; @@ -394,17 +402,30 @@ export async function execute( await sheet.batchUpdate(updateData, valueInputMode); } if (appendData.length) { - await sheet.appendEmptyRowsOrColumns(sheetId, 1, 0); const lastRow = sheetData.length + 1; - await sheet.appendSheetData( - appendData, - range, - headerRow + 1, - valueInputMode, - false, - [columnNames.concat([...newColumns])], - lastRow, - ); + if (options.useAppend) { + await sheet.appendSheetData( + appendData, + range, + headerRow + 1, + valueInputMode, + false, + [columnNames.concat([...newColumns])], + lastRow, + options.useAppend as boolean, + ); + } else { + await sheet.appendEmptyRowsOrColumns(sheetId, 1, 0); + await sheet.appendSheetData( + appendData, + range, + headerRow + 1, + valueInputMode, + false, + [columnNames.concat([...newColumns])], + lastRow, + ); + } } if (nodeVersion < 4 || dataMode === 'autoMapInputData') { diff --git a/packages/nodes-base/nodes/Google/Sheet/v2/helpers/GoogleSheet.ts b/packages/nodes-base/nodes/Google/Sheet/v2/helpers/GoogleSheet.ts index 4eddfa584a..fe1983a2aa 100644 --- a/packages/nodes-base/nodes/Google/Sheet/v2/helpers/GoogleSheet.ts +++ b/packages/nodes-base/nodes/Google/Sheet/v2/helpers/GoogleSheet.ts @@ -247,24 +247,8 @@ export class GoogleSheet { data: string[][], valueInputMode: ValueInputOption, lastRow?: number, + useAppend?: boolean, ) { - // const body = { - // range, - // values: data, - // }; - - // const query = { - // valueInputOption: valueInputMode, - // }; - - // const response = await apiRequest.call( - // this.executeFunctions, - // 'POST', - // `/v4/spreadsheets/${this.id}/values/${this.encodeRange(range)}:append`, - // body, - // query, - // ); - const lastRowWithData = lastRow || (((await this.getData(range, 'UNFORMATTED_VALUE')) as string[][]) || []).length + 1; @@ -275,6 +259,7 @@ export class GoogleSheet { valueInputMode, lastRowWithData, data.length, + useAppend, ); return response; @@ -286,6 +271,7 @@ export class GoogleSheet { valueInputMode: ValueInputOption, row: number, rowsLength?: number, + useAppend?: boolean, ) { const [name, _sheetRange] = sheetName.split('!'); const range = `${name}!${row}:${rowsLength ? row + rowsLength - 1 : row}`; @@ -299,13 +285,25 @@ export class GoogleSheet { valueInputOption: valueInputMode, }; - const response = await apiRequest.call( - this.executeFunctions, - 'PUT', - `/v4/spreadsheets/${this.id}/values/${this.encodeRange(range)}`, - body, - query, - ); + let response; + + if (useAppend) { + response = await apiRequest.call( + this.executeFunctions, + 'POST', + `/v4/spreadsheets/${this.id}/values/${this.encodeRange(range)}:append`, + body, + query, + ); + } else { + response = await apiRequest.call( + this.executeFunctions, + 'PUT', + `/v4/spreadsheets/${this.id}/values/${this.encodeRange(range)}`, + body, + query, + ); + } return response; } @@ -386,6 +384,7 @@ export class GoogleSheet { usePathForKeyRow: boolean, columnNamesList?: string[][], lastRow?: number, + useAppend?: boolean, ): Promise { const data = await this.convertObjectArrayToSheetDataArray( inputData, @@ -393,8 +392,9 @@ export class GoogleSheet { keyRowIndex, usePathForKeyRow, columnNamesList, + useAppend ? null : '', ); - return this.appendData(range, data, valueInputMode, lastRow); + return this.appendData(range, data, valueInputMode, lastRow, useAppend); } getColumnWithOffset(startColumn: string, offset: number): string { @@ -700,6 +700,7 @@ export class GoogleSheet { keyRowIndex: number, usePathForKeyRow: boolean, columnNamesList?: string[][], + emptyValue: string | null = '', ): Promise { const decodedRange = this.getDecodedSheetRange(range); @@ -730,7 +731,7 @@ export class GoogleSheet { value = item[key] as string; } if (value === undefined || value === null) { - rowData.push(''); + rowData.push(emptyValue as string); return; } if (typeof value === 'object') {